HDFS

HDFS的基本介绍

  • HDFS: 分布式文件存储系统
  • 目的: 存储海量数据
  • 分布式文件存储过程:
HDFS.assets/image-20210126091428422.png
  • HDFS的应用场景:

      1. 存储非常大的文件(GB TB PB), 适合于做批量化高吞吐的业务
      1. 一次写入、多次读取 : 对数据没有修改的要求, 但是需要多次读取, HDFS不支持随机修改文件中数据
      • 思考, 什么数据一般不需要修改的? 过去已经既定发生过数据
      1. 在有限成本下, 存储更多数据
      1. 需要高容错性: 数据不能给丢失了
      1. 需要具备扩展能力
  • HDFS不适用场景:

      1. 需要进行随机修改的场景
      1. 需要交互式强场景
      1. 存储大量的小文件场景

HDFS的架构及核心概念

HDFS.assets/image-20210126154219072.png
1
2
3
4
5
6
7
8
9
10
11
注意: 
假设现在有一个300M 文件, 请问分几个块呢? 3个块
第一个块: 128M
第二个块: 128M
第三个块: 44M
假设还有一个150M文件, 请问分2个块?
第一个块为: 128M
第二个块为 22M
一个块最大为128M , 请问第一个文件中第三个块和第二个文件的第二个块, 是否会占用128M大小呢? 不会的
最终一个文件块占用多大的磁盘空间, 取决于存储数据大小
一个块只能代表一个文件的内容
  • 副本的机架感知原理, 以及网络拓扑机制

  • HDFS.assets/image-20210126104910139.png
    1
    2
    3
    4
    说明: 
    第一副本:优先放置到离写入客户端最近的DataNode节点,如果上传节点就是DataNode,则直接上传到该节点,如果是集群外提交,则随机挑选一台磁盘不太满,CPU不太忙的节点。
    第二个副本:放置在另一个机架中, 某一个服务器中
    第三个副本:放置在与第二个同机架的不同机器中

HDFS的原理

namenode是如何存储元数据的流程

  1. HDFS.assets/image-20210126153813295.png

    SNN辅助节点流程方案

    HDFS.assets/image-20210126172339363.png

    从整个流程中 可以发现, SNN在对namenode元数据进行冷备份(备份前一个小时的元数据或者前一个edits达到64M的数据), 在一些特殊场景下, 可以基于SNN进行元数据的恢复工作, 此种操作, 可能无法恢复全部的数据, 但是也可以恢复到1个小时以前(或者…)的数据

HDFS的数据写入的流程

  • HDFS.assets/image-20210126162059920.png

HDFS的数据读取流程

  • HDFS.assets/image-20210126165717681.png

HDFS相关的shell操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
一、简介

linux alias 是命令的一种别称,输入

alias

可以看到像下面这样的结果:

alias vi="vim"

也即,输入vi后,被自动定向到vim这个命令了。alias的作用就是,可以简写命令。


二、修改alias

若要添加自己的alias,格式如下

alias la="ls -al --color=auto"


三、修改配置文件

上述命令,在用户登出后就无效了,可以用修改配置文件的办法,使每次都能够自动生效。

若要修改用户(而非全部用户)自己的alias,可以修改~/.bashrc文件

vi ~/.bashrc

再最后面加上你自己定义的alias,如

alias la="ls -al --color=auto"

这个修改,要下次登录的时候才能生效。想要即刻生效,可以输入

source ~/.bashrc


四、常用的alias

这个根据个人爱好了,可以google之~找到你自己喜欢的alias


PS: 修改全局的alias可以修改系统配置文件,我这里就不说了。

还有其他的方面知识,如交互式、非交互式登录的配置文件,这个也不多说了。
alias hls='hadoop fs -ls'
alias hlsr='hadoop fs -lsr'
alias hcp='hadoop fs -cp '
alias hmv='hadoop fs -mv'
alias hget='hadoop fs -get'
alias hput='hadoop fs -put'
alias hrm='hadoop fs -rm'
alias hmkdir='hadoop fs -mkdir'
alias hcat='hadoop fs -cat'
alias hrmr='hadoop fs -rmr'
alias hstat='hadoop fs -stat'
alias htest='hadoop fs -test'
alias htext='hadoop fs -text'
alias htouchz='hadoop fs -touchz'
alias hdu='hadoop fs -du'
alias hdus='hadoop fs -dus'
alias hchmod='hadoop fs -chmod'
alias hchgrp='hadoop fs -chgrp'
alias hchown='hadoop fs -chown'
alias htail='hadoop fs -tail'
  • HDFS的操作命令基本格式:
1
2
3
hadoop fs <args>:  通用文件系统操作 既可以操作HDFS文件系统, 也可以操作本地文件系统, 默认操作hdfs文件系统
默认取决于: 在 core-site.xml中 fs.defaultFS
hdfs dfs <args>: 操作HDFS文件系统
  • 常用命令介绍:

      1. ls
      • 作用: 查看某一个路径的目录结构
    1
    2
    3
    4
    5
    6
    格式: 
    hdfs dfs -ls [-R] 路径
    参数说明:
    -R : 是否递归获取某个目录所有子目录内容
    案例:
    hdfs dfs -ls /
      1. mkdir
      • 作用: 创建目录
    1
    2
    3
    4
    5
    6
    格式: 
    hdfs dfs -mkdir [-p] 路径
    参数说明:
    -p : 创建多级目录时 需要添加
    案例:
    hdfs dfs -mkdir -p /aaa/bbb/ccc
      1. put
      • 作用: 用于上传文件
    1
    2
    3
    4
    5
    6
    格式:
    hdfs dfs -put srcLocalFilePath hdfsDirPath

    案例:
    hdfs dfs -put jdk-8u241-linux-x64.tar.gz /aaa/bbb/ccc

      1. moveFromLocal
      • 作用: 将本地文件系统的文件移动到HDFS中
    1
    2
    3
    4
    5
    格式: 
    hdfs dfs -moveFromLocal srcLocalFilePath hdfsDirPath

    案例:
    hadoop fs -moveFromLocal jdk-8u241-linux-x64.tar.gz /aaa/bbb
      1. moveToLocal
      • 作用: 将HDFS的文件系统文件数据移动到本地文件系统
    1
    2
    3
    4
    格式:
    hdfs dfs -moveToLocal hdfsFilePath srcLocalDirPath
    案例:
    此命令未实现
    HDFS.assets/image-20210126112858178.png
      1. get
      • 作用: 从HDFS中下载数据到本地文件系统
    1
    2
    3
    4
    5
    6
    7
    格式: 
    hdfs dfs -get hdfsFilePath srcLocalDirPath

    案例:
    hadoop fs -get /aaa/bbb/jdk-8u241-linux-x64.tar.gz ~

    注意: 此操作下载后, 在HDFS中, 依然存在, 相当于是读取数据操作
      1. getmerge
      • 作用: 合并下载
    1
    2
    3
    4
    5
    #格式: 
    hdfs dfs -getmerge hdfsFilePath1 hdfsFilePath2 ... srcLocalFilePath

    #案例:
    hdfs dfs -getmerge /aaa/bbb/jdk-8u241-linux-x64.tar.gz /aaa/bbb/ccc/jdk-8u241-linux-x64.tar.gz ~/jdk_merge.gz
      1. mv
      • 作用: 在hdfs中 从一个目录移动到另一个目录, 或者进行重命名操作
    1
    2
    3
    4
    5
    6
    #格式: 
    hdfs dfs -mv srchdfsFilePath disthdfsFilePath
    #案例:
    hdfs dfs -mv /aaa/bbb/ccc/jdk-8u241-linux-x64.tar.gz /

    #注意: 此处移动是在hdfs内部进行数据移动
      1. rm
      • 作用: 删除HDFS中数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    格式: 
    hdfs dfs -rm [-r -f -skipTrash] 删除的hdfs的文件路径或者目录路径

    参数说明:
    -r: 表示是否递归删除(删除目录需要携带)
    -f: 强制删除
    -skipTrash: 跳过垃圾桶 (一般不使用)
    案例:
    hdfs dfs -rm /jdk.gz

    注意:
    默认情况下, 删除数据, 本质上将其移动到垃圾桶

    hdfs的垃圾桶, 默认情况 到达7天后, 自动删除过期数据
    在生产中, 建议不要跳过垃圾桶, 将删除数据放置到回收站, 给自己一次反悔机会
      1. cat
      • 作用: 查看某个文件的内容
    1
    2
    3
    4
    5
    6
    格式 :
    hdfs dfs -cat hdfsFilePath
    案例:
    hdfs dfs -cat /aaa.txt

    注意: 此操作只适合查看小文件的数据
      1. du
      • 作用: 查看目录或者文件的大小
    1
    2
    3
    4
    5
    6
    格式: 
    hdfs dfs -du [-h] hdfsFilePath|hdfsDirPath
    参数说明:
    -h : 表示友好展示文件大小
    案例:
    hdfs dfs -du /jdk-8u241-linux-x64.tar.gz
      1. chmod
      • 作用: 设置权限
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    格式: 
    hdfs dfs -chmod 权限编号(3位) hdfsPath
    权限 4 2 1法则:
    4: 可读
    2: 可写
    1: 可执行
    案例:
    hdfs dfs -chmod 755 /jdk.gz
    描述: 所属用户为可读可写可执行, 其他所有的用户可读可执行权限

    注意:
    在hdfs中, 由于我们在hdfs-site.xml中将hdfs的权限已经关闭了, 所以不管设置任何权限, 都没有用
    对于root而言, 即使开启了权限设置, 对这个用户也是无效的

    在HDFS中, 权限管理只能防止好人做错事, 而不能防止坏人做坏事
      1. chown
      • 作用: 设置所属用户和所属用户组
    1
    2
    3
    4
    5
    6
    7
    格式:
    hdfs dfs -chown [-R] 所属用户:所属组 路径

    参数说明:
    -R : 表示是否递归设置所属用户和所属组
    案例:
    hdfs dfs -chown itcast:itcast /aaa.txt
      1. appendToFile
      • 作用: 追加数据到hdfs的某一个文件中 (修改文件数据)
    1
    2
    3
    4
    5
    格式: 
    hdfs dfs -appendToFile srcLocalFilePath hdfsFilePath

    案例:
    hdfs dfs -appendToFile bbb.txt /aaa.txt
  1. hdfs的高级shell命令
  • hdfs的安全模式

    • hdfs的安全模式, 是hdfs的保护机制, 当刚刚启动HDFS的时候, 系统会自动的进入安全模式下, 在此模式下, 开始校验副本块是否安全(完整), 如果校验发现都是OK, hdfs会自动离开安全模式(30s), 在运行的过程中, 如果发现块出现问题, 依然会进入安全模式的;

    • hdfs会自动维护块信息, 当发现某个块副本数量少, 自动新增, 如果发现块的副本变多了, 自动减少的

    • 安全模式的相关的操作:

      1
      2
      3
      hdfs  dfsadmin  -safemode  get #查看安全模式状态
      hdfs dfsadmin -safemode enter #进入安全模式
      hdfs dfsadmin -safemode leave #离开安全模式
    • HDFS.assets/image-20210126145641088.png
  • hdfs的基准测试

    • ​ hdfs的基准测试, 主要目的就是为了检测刚刚搭建好的HDFS集群, 整体吞吐量是多大

    • 检测方案:

        1. 向hdfs一次性写入多个文件, 测试其写入时间和写入数据量的比例
        1
        hadoop jar /export/server/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -write -nrFiles 10 -fileSize 10MB
        1. 从hdfs一次性读取多个文件, 测试其读取时间和读取数据量之间的比例
        1
        hadoop jar /export/server/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar  TestDFSIO -read -nrFiles 10 -fileSize 10MB
        1. 清空基准测试的数据:
        1
        hadoop jar /export/server/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -clean
      • 注意:

        • 在生产中进行检测的时候, 一定要多测试几次, 而且每次测试, 采用不同的文件数量和数据量来测试, 这样测出结果会比较准确一些

服务器与服务器之间数据拷贝操作

服务器之间数据远程拷贝: scp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
方式1:指定用户名,命令执行后需要再输入密码;  从本地拷贝到远程
scp -r local_folder remote_username@remote_ip:remote_folder
例如:
scp -r hadoop root@node2:/export/server
简写方案: 远端目的地路径和当前路径是一致的, 并且操作用户也是一样的
scp -r hadoop node2:$PWD

注意,如果实现了ssh免密登录之后,则不需要输入密码即可拷贝。


方式二: 从远程拷贝到本地:
格式:
scp [email protected]:/root/test.txt /root/test.txt

例如:
scp root@node1:/export/server/hadoop /export/server

hdfs集群之间数据拷贝

1
2
3
4
5
6
格式: 
hadoop distcp 第一个集群的路径 目的地集群路径
案例:
hadoop distcp hdfs://node1:8020/jdk-8u241-linux-x64.tar.gz hdfs://cluster2:8020/
描述:
将 第一个集群中 根目录下的jdk包 发送给第二个集群的根目录下

hdfs的归档文件

  • 目的: 用于小文件的合并操作, 从而得到一个更大的文件

  • 场景: 在hdfs中以及存在了大量的小文件, 需要进行合并的场景

  • 通过java代码实现一种小文件合并操作 请问, 此种操作, 有什么弊端吗?

    1. 重新获取每一个文件不是很方便 2) 合并只能合并同类型的数据

    所以说, java合并操作, 比较适合于同类型的文本数据合并操作, 其他的都不适用了

  • 而归档文件, 类似于 windows中压缩方案, 但是规约文件不会进行缩 只会进行压: 归档文件后缀名为 .har

  • 有什么好处呢?

1
2
3
1) 压在一起后, 依然可以看到里面有那些文件
2) 压在一起后, 也可以将其解压出来
3) 压在一起可以不局限于任何类型
  • 如何使用呢?
      1. 如何构建归档文件
1
2
3
4
5
6
7
8
9
语法格式:
hadoop archive -archiveName name -p <parent> <src>* <dest>
例如:
hadoop archive -archiveName test.har -p /config /outputdir
说明:
将 /config目录下所有的文件或者目录合并到test.har文件中, 然后将这个归档文件放置在 /outputdir

需求: 在 /smallFile 目录下 有很多的小文件, 需要进行合并操作
hadoop archive -archiveName smallMerge.har -p /smallFile /harFile
    1. 如何查看合并后的文件
1
2
3
4
格式:
hadoop fs -ls har://hdfs-node1:8020/outputdir/test.har
案例:
hdfs dfs -ls har://hdfs-node1:8020/harFile/smallMerge.har
    1. 如何解压归档文件
1
2
3
4
5
6
格式: 
hadoop fs -cp har:///outputdir/test.har/* /config2

案例:
hdfs dfs -mkdir -p /harOpen
hdfs dfs -cp har://hdfs-node1:8020/harFile/smallMerge.har/* /harOpen

注意事项:

1
2
3
4
5
6
7
1.	Hadoop archives是特殊的档案格式。一个Hadoop archive对应一个文件系统目录。Hadoop archive的扩展名是*.har;
2. 创建archives本质是运行一个Map/Reduce任务,所以应该在Hadoop集群上运行创建档案的命令,要提前启动Yarn集群;
3. 创建archive文件要消耗和原文件一样多的硬盘空间;
4. archive文件不支持压缩,尽管archive文件看起来像已经被压缩过;
5. archive文件一旦创建就无法改变,要修改的话,需要创建新的archive文件。事实上,一般不会再对存档后的文件进行修改,因为它们是定期存档的,比如每周或每日;
6. 当创建archive时,源文件不会被更改或删除;

hdfs的快照机制

hdfs的快照的目的: 对hdfs文件系统进行备份操作

​ 可以对hdfs中某个目录进行快照的拍摄, 注意在拍摄之后, 不会产生任何的内容, 只要当对以及拍摄快照的目录进行修改之后, 记录那些修改的信息即可 —– 差异化快照

  • 1 开启指定目录的快照功能 :
    • 默认hdfs对目录的快照功能是关闭状态
1
hdfs dfsadmin -allowSnapshot 路径   
  • 2 禁用指定目录的快照功能(默认就是禁用状态)
1
hdfs dfsadmin -disallowSnapshot 路径  
  • 3 给某个路径创建快照snapshot

    1
    hdfs dfs  -createSnapshot 路径  
    1. 指定快照名称进行创建快照snapshot
1
hdfs dfs -createSanpshot 路径  名称    
  • 5 ) 给快照重新命名
1
hdfs dfs -renameSnapshot 路径 旧名称 新名称
  • 6 列出当前用户所有可快照目录

    1
    hdfs  lsSnapshottableDir    
  • 7 比较快照目录中, 两个快照的不同之处

1
hdfs snapshotDiff 路径 快照1名称 快照2名称
  • 8 删除快照snapshot

    1
    hdfs dfs -deleteSnapshot  <path> <snapshotName>   

2.4 hdfs的回收站(垃圾桶)

hdfs的回收站默认是禁用状态, 如果需要使用, 手动在core-site.xml中进行开启:

1
2
3
4
5
<!--  开启hdfs的垃圾桶机制,删除掉的数据可以从垃圾桶中回收,单位分钟 -->
<property>
<name>fs.trash.interval</name>
<value>10080</value>
</property>

​ 一旦开启了回收站, 当执行shell的操作时候, 就会自动将删除移动到回收站目录下, 回收站默认情况下 7天之后, 自动删除数据, 此时才会将空间进行释放, 回收站出现给与我们反悔机会, 防止出现误删操作

​ 如果使用java api执行delete操作, 直接跳过回收站, 永久删除掉, 如果解决呢?

解决方案: 在java API操作的, 将需要删除的数据直接移动的回收站的目录下 即可

  • 清空回收站 (慎用)
1
hadoop fs -expunge

hdfs的javaAPI的操作

配置windows下的hadoop环境

  • 第一步, 将资料中 hadoop-2.7.5 目录拷贝到一个没有中文没有空格的目录下
HDFS.assets/image-20210127085443535.png
  • 第二步: 配置环境变量 HADOOP_HOME
  • HDFS.assets/image-20210127085649442.png
  • 第三步, 将这个HADOOP_HOME配置到path环境变量中:
  • HDFS.assets/image-20210127085827916.png
  • 注意: 配置完, 一定要一顿点确定, 千万不要点取消
  • 第四步: 将 hadoop-2.7.5目录下bin目录中 hadoop.dll文件, 放置在 c盘system32目录下
  • HDFS.assets/image-20210127090114411.png
  • 配置以上操作 目的, 是为了解决下面的两个问题:
  • HDFS.assets/image-20210127090241379.png
  • 第五步: 重启电脑

获取某个路径下所有文件listFiles

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 需求2: 查询某一个目录下所有的文件
@Test
public void test04() throws Exception{

//1. 创建java连接HDFS的FileSystem对象
URI uri = new URI("hdfs://node1:8020");
Configuration conf = new Configuration();
FileSystem fileSystem = FileSystem.get(uri, conf);

//2. 执行相关的操作: 获取根目录下所有的文件
//2.1: 执行获取某个路径的文件(递归获取)
RemoteIterator<LocatedFileStatus> listFiles = fileSystem.listFiles(new Path("/"), true);
//2.2: 遍历迭代器, 获取每一个文件
while ( listFiles.hasNext()){

LocatedFileStatus fileStatus = listFiles.next();

//2.3: 从文件状态对象中获取文件的路径
Path path = fileStatus.getPath();
//2.4: 从path路径上获取文件的名称
String name = path.getName();

System.out.println(path);
System.out.println(name);

System.out.println("--------------------------");
}


//3. 释放资源

fileSystem.close();


}

创建文件夹操作mkdirs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 需求三: 创建一个文件夹
@Test
public void test05() throws Exception{

//1. 创建fileSystem对象
Configuration conf = new Configuration();
conf.set("fs.defaultFS","hdfs://node1:8020");
FileSystem fileSystem = FileSystem.newInstance(conf);

//2. 执行相关的操作 : 创建文件夹

fileSystem.mkdirs(new Path("/javaDIR/aaa/bbb"));


//3. 释放资源
fileSystem.close();

}

上传文件操作copyFromLocalFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 需求四: 上传文件操作
@Test
public void test06() throws Exception{

//1. 创建fileSystem对象
URI uri = new URI("hdfs://node1:8020");
Configuration conf = new Configuration();
FileSystem fileSystem = FileSystem.newInstance(uri, conf);

//2. 执行相关的操作 上传命令: put
fileSystem.copyFromLocalFile(new Path("file:///D:\\大数据操作_精华篇\\day04_hadoop\\资料\\aaa.sql"), new Path("/javaDIR/aaa/bbb"));

//3. 释放资源

fileSystem.close();
}

下载文件的操作copyToLocalFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 需求五:  下载数据操作

@Test
public void test07() throws Exception{

//1. 创建fileSystem对象
URI uri = new URI("hdfs://node1:8020");
Configuration conf = new Configuration();
FileSystem fileSystem = FileSystem.newInstance(uri, conf);

//2. 执行相关的操作 下载操作: get

fileSystem.copyToLocalFile(new Path("/javaDIR/aaa/bbb/aaa.sql"),new Path("file:///本地文件路径"));

//3. 释放资源

fileSystem.close();
}

小文件合并操作

  • 第一种实现方式: 推荐使用的, 如果不能用可以采用第二种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 需求六: 合并小文件操作
@Test
public void test08() throws Exception{

//1. 创建 HDFS的文件系统对象 和 本地文件系统对象
Configuration conf = new Configuration();
conf.set("fs.defaultFS","hdfs://node1:8020");
FileSystem dfsFileSystem = FileSystem.get(conf);

LocalFileSystem localFileSystem = FileSystem.getLocal(new Configuration());

//2. 执行相关的操作:

//2.1: 在HDFS中创建一个文件,返回一个输出流
FSDataOutputStream outputStream = dfsFileSystem.create(new Path("/javaDIR/aaa/bbb/merge.xml"));

//2.2 通过本地文件系统, 读取某个路径下所有文件
RemoteIterator<LocatedFileStatus> listFiles = localFileSystem.listFiles(new Path("file:///本地路径"), false);

while(listFiles.hasNext()){

LocatedFileStatus fileStatus = listFiles.next();

Path path = fileStatus.getPath();
//2.3: 读取文件, 获取这个文件的输入流
FSDataInputStream inputStream = localFileSystem.open(path);


//2.4: 两个流对接
int len ;
byte[] b = new byte[1024];
while( ( len= inputStream.read(b) ) != -1) {
outputStream.write(b,0,len);
outputStream.flush();
}
inputStream.close();

}
outputStream.close();

//3. 释放资源
localFileSystem.close();
dfsFileSystem.close();


}

  • 第二种实现方案:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 需求六:  小文件合并操作:  原生写法
@Test
public void test09() throws Exception{

//1. 创建DFS的文件系统对象
Configuration conf = new Configuration();
conf.set("fs.defaultFS","hdfs://node1:8020");
FileSystem fileSystem = FileSystem.get(conf);

//2. 执行相关的操作
//2.1: 在HDFS中创建一个文件, 并且获取到这个文件的输出流, 用于通过此流将数据输出大目标文件中
FSDataOutputStream outputStream = fileSystem.create(new Path("/javaDIR/aaa/bbb/merge2.xml"));

//2.2: 读取某个路径下所有文件
File fileDir = new File("D:\\day04_hadoop\\资料\\上传小文件合并");

File[] files = fileDir.listFiles();

for (File file : files) {
//2.3: 创建一个输入流: 指定读取文件对象
FileInputStream inputStream = new FileInputStream(file);

//2.4: 两个流对接
int len;
byte[] b = new byte[1024];
while( (len = inputStream.read(b) ) != -1 ) {

outputStream.write(b,0,len);

outputStream.flush();
}
// 每将一个文件写完后, 就将这个文件的输入流给关闭
inputStream.close();

}
// 当所有文件都写入到目标文件后, 然后关闭输出流
outputStream.close();

//3 释放资源

fileSystem.close();
}

文件权限的操作

    1. 开启HDFS的文件权限
1
2
3
4
5
6
7
8
9
此配置在 hdfs-site.xml中
<property>
<name>dfs.permissions.enabled</name>
<value>true</value>
</property>

更改后, 需要将hdfs-site.xml发送给node2 和 node3

然后进行重启hdfs即可
    1. 通过代码测试
    • 向一个没有权限的目录上传文件操作, 观察是否可以上传, 然后在通过模拟用户的方式来操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 需求七: 在 /hsTest01 目录上传一个  c.txt 文件
// /hsTest01的权限为: drwxr-xr-x root supergroup
@Test
public void test10() throws Exception{

//1. 创建 hdfs的文件系统对象
Configuration conf = new Configuration();

URI uri = new URI("hdfs://node1:8020");
FileSystem fileSystem = FileSystem.get(uri,conf,"root");

//2. 执行相关的操作
fileSystem.copyFromLocalFile(new Path("file:///本地文件路径"),new Path("/hsTest01"));

//3. 释放资源

fileSystem.close();


}