一、HDFS概述
1.1 HDFS概念
HDFS ( Hadoop Distributed File System ) ,Hadoop分布式文件系统,通过目录树(/)来定位文件。是根据google发表的论文翻版的。论文为GFS(Google File System)Google 文件系统
1.2 HDFS优缺点
1.2.1 优点
① 高容错性:保存多个副本,提高容错性,副本丢失或宕机自动恢复。默认存3份。
② 简单的一致性模型:一次写入,多次读取,不能修改。
③ 适合大数据的处理:数据规模上,能够处理数据规模达到 GB、TB、甚至PB级别的数据。文件规模上,能够处理百万规模以上的文件数量,数量相当之大。
④运行在廉价的机器上。
1.2.2 缺点
① 不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。
② 无法高效的对大量小文件进行存储。
③ 一个文件只能有一个写,不允许多个线程同时写。也不支持文件修改。
1.3 HDFS架构
① Client:客户端。负责文件切分;与NameNode交互,获取文件的位置信息;与DataNode交互,读取或者写入数据;
② NameNode:管理数据块映射;处理客户端的读写请求;配置副本策略;管理HDFS的名称空间;
③ SecondaryNameNode:有两个作用,一是镜像备份,二是日志与镜像的定期合并。它会保存合并后的命名空间镜像的副本,并在namenode发生故障时启用。
④ DataNode:负责存储client发来的数据块block;执行数据块的读写操作。
1.4 HDFS块大小
块的大小可以通过配置参数(hdfs-site.xml 文件中dfs.blocksize)来规定。
默认大小在hadoop2.x版本中是128M,老版本中是64M。
二、HDFS命令行操作
动作 | 命令 | 例子 |
输出命令参数 | hadoop fs -help | hadoop fs -help ls |
显示根目录信息 | hadoop fs -ls | hadoop fs -ls / |
创建目录 | hadoop fs -mkdir | hadoop fs -mkdir /foodir |
删除文件或文件夹 | hadoop fs -rm | hadoop fs -rm -r -f /foodir |
拷贝 | hadoop fs -cp | hadoop fs -cp /test/1.txt /2.txt |
移动 | hadoop fs -mv | hadoop fs -mv /2.txt /test/ |
显示文件内容 | hadoop fs -cat | hadoop fs -cat /test/1.txt |
本地剪切粘贴到HDFS | hadoop fs -moveFromLocal | hadoop fs -moveFromLocal ./3.txt /test |
追加文件 | hadoop fs -appendToFile | hadoop fs -appendToFile 2.txt /test /1.txt |
本地拷贝到HDFS | hadoop fs -copyFromLocal 或者 hadoop fs -put | hadoop fs -copyFromLocal 4.txt /test |
HDFS拷贝到本地 | hadoop fs -copyToLocal 或者 hadoop fs -get | hadoop fs -copyToLocal /test/1.txt ./5.txt |
合并下载多个文件 | hadoop fs -getmerge | hadoop fs -getmerge /test/* ./result.txt |
统计可用空间信息 | hadoop fs -df | hadoop fs -df -h / |
统计文件夹的大小信息 | hadoop fs -du | hadoop fs -du -h / |
设置HDFS中文件的副本数量 | hadoop fs -setrep | hadoop fs -setrep 2 /test/6.txt |
三、通过API操作HDFS
3.1 获取文件系统
@Test
public void initHDFS() throws Exception {
// 1 创建配置信息对象
Configuration configuration = new Configuration();
// 2 获取文件系统
FileSystem fs = FileSystem.get(configuration);
// 3 打印文件系统
System.out.println(fs.toString());
}
3.2 HDFS文件上传
参数优先级:① 客户端代码中设置的值 > ② classpath下的用户自定义配置文件 > ③ 服务器的默认配置。
@Test
public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {
// 1 获取文件系统
Configuration configuration = new Configuration();
// configuration.set("dfs.replication", "2"); 设置副本数量
FileSystem fs = FileSystem.get(new URI("hdfs://Master:9000"), configuration, "root");
// 2 上传文件
fs.copyFromLocalFile(new Path("e:/hello.txt"), new Path("/hello.txt"));
// 3 关闭资源
fs.close();
}
3.3 HDFS文件下载
@Test
public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException{
// 1 获取文件系统
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://Master:9000"), configuration, "root");
// 2 执行下载操作
// boolean delSrc 指是否将原文件删除
// Path src 指要下载的文件路径
// Path dst 指将文件下载到的路径
// boolean useRawLocalFileSystem 是否开启文件效验
fs.copyToLocalFile(false, new Path("/hello1.txt"), new Path("e:/hello1.txt"), true);
// 3 关闭资源
fs.close();
}
3.4 HDFS文件详情查看
@Test
public void testListFiles() throws IOException, InterruptedException, URISyntaxException {
// 1获取文件系统
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://Master:9000"), configuration, "root");
// 2 获取文件详情
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
while (listFiles.hasNext()) {
LocatedFileStatus status = listFiles.next();
// 输出详情
// 文件名称
System.out.println(status.getPath().getName());
// 长度
System.out.println(status.getLen());
// 权限
System.out.println(status.getPermission());
// z组
System.out.println(status.getGroup());
// 获取存储的块信息
BlockLocation[] blockLocations = status.getBlockLocations();
for (BlockLocation blockLocation : blockLocations) {
// 获取块存储的主机节点
String[] hosts = blockLocation.getHosts();
for (String host : hosts) {
System.out.println(host);
}
}
}
}
3.5 HDFS文件和文件夹判断
@Test
public void testListStatus() throws IOException, InterruptedException, URISyntaxException {
// 1获取文件系统
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://Master:9000"), configuration, "root");
// 2 判断是否是文件还是文件夹
FileStatus[] listStatus = fs.listStatus(new Path("/"));
for (FileStatus fileStatus : listStatus) {
// 如果是文件
if (fileStatus.isFile()) {
System.out.println(fileStatus.getPath().getName() + " is a file!");
} else {
System.out.println(fileStatus.getPath().getName() + " is not a file!");
}
}
}
四、通过IO流操作HDFS
4.1 HDFS文件上传
@Test
public void putFileToHDFS() throws IOException, InterruptedException, URISyntaxException {
// 1 获取文件系统
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://Master:9000"), configuration, "root");
// 2 创建输入流
FileInputStream fis = new FileInputStream(new File("e:/hello.txt"));
// 3 获取输出流
FSDataOutputStream fos = fs.create(new Path("/hello4.txt"));
// 4 流对接
IOUtils.copyBytes(fis, fos, configuration);
// 5 关闭资源
IOUtils.closeStream(fis);
IOUtils.closeStream(fos);
}
4.2 HDFS文件下载
@Test
public void getFileFromHDFS() throws IOException, InterruptedException, URISyntaxException{
// 1 获取文件系统
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://Master:9000"), configuration, "root");
// 2 获取输入流
FSDataInputStream fis = fs.open(new Path("/hello4.txt"));
// 3 获取输出流
//FileInputStream fos = new FileInputStream(new File("e:/hello.txt"));
// 4 流对接 输出到控制台
IOUtils.copyBytes(fis, System.out, configuration);
// 5 关闭资源
IOUtils.closeStream(fis);
}
4.3 定位读取文件
4.3.1 下载第一块
@Test
public void readFileSeek1() throws IOException, InterruptedException, URISyntaxException{
// 1 获取文件系统
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://Master:9000"), configuration, "root");
// 2 获取输入流
FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));
// 3 创建输出流
FileOutputStream fos = new FileOutputStream(new File("e:/hadoop-2.7.2.tar.gz.part1"));
// 4 流的拷贝
byte[] buf = new byte[1024];
for(int i =0 ; i < 1024 * 128; i++){
fis.read(buf);
fos.write(buf);
}
// 5 关闭资源
IOUtils.closeStream(fis);
IOUtils.closeStream(fos);
}
4.3.2 下载第二块
@Test
public void readFileSeek2() throws IOException, InterruptedException, URISyntaxException{
// 1 获取文件系统
Configuration configuration = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://Master:9000"), configuration, "root");
// 2 打开输入流
FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));
// 3 定位输入数据位置
fis.seek(1024*1024*128);
// 4 创建输出流
FileOutputStream fos = new FileOutputStream(new File("e:/hadoop-2.7.2.tar.gz.part2"));
// 5 流的对拷
IOUtils.copyBytes(fis, fos, configuration);
// 6 关闭资源
IOUtils.closeStream(fis);
IOUtils.closeStream(fos);
}
4.3.3 合并文件
找到文件所在位置,搜索栏搜索cmd
在 window 命令窗口中执行:type hadoop-2.7.2.tar.gz.part2 >> hadoop-2.7.2.tar.gz.part1
重命名文件名:hadoop-2.7.2.tar.gz.part1为hadoop-2.7.2.tar.gz