前言
上一篇文章《从0开始学大数据(4):Hadoop完全分布式模式的配置和应用》我们学会了如何使用三台机器去搭建HDFS文件系统,但是我们对其中的一些专业词汇如namenode,datanode,resourcemanager,nodemanager不是很熟悉,这篇文章我们需要来普及一下。
1.HDFS概念
1.1 概念
- HDFS,它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。
- HDFS的设计适合一次写入,多次读出的场景,且不支持文件的修改。适合用来做数据分析,并不适合用来做网盘应用。
1.2 组成
1)HDFS集群包括,NameNode和DataNode以及Secondary Namenode。
2)NameNode负责管理整个文件系统的元数据,以及每一个路径(文件)所对应的数据块信息。
3)DataNode 负责管理用户的文件数据块,每一个数据块都可以在多个datanode上存储多个副本。
4)Secondary NameNode用来监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS元数据的快照。
1.3 HDFS 文件块大小
2.HDFS基本命令
3.HDFS客户端操作
3.1 IDEA环境准备
3.1.1 jar包准备
1)解压hadoop-2.7.2.tar.gz到非中文目录
2)进入share文件夹,查找所有jar包,并把jar包拷贝到_lib文件夹下
目录路径:<hadoop源码路径>/share/hadoop
3)在全部jar包中查找.source.jar,并剪切到_source文件夹。
当我们把所有的jar包放入到_lib
文件夹后,还需要将source源码放入到新建的_source
文件夹下
4)在全部jar包中查找tests.jar,并剪切到_test文件夹。
3.2.2 IDEA的准备
1)配置HADOOP_HOME环境变量
#Hadoop-2.7.2
export HADOOP_HOME=/Users/martin/ThirdPart/hadoop/
export PATH=$PATH:$HADOOP_HOME/bin
2)采用hadoop编译后的bin 、lib两个文件夹(如果不生效,重新启动idea)
3)创建第一个java工程
package com.martin.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
public class HDFSClient
{
public static void main(String[] args) throws Exception {
// 1 获取文件系统
Configuration configuration = new Configuration();
// 直接配置访问集群的路径和访问集群的用户名称
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"),configuration, "martin");
// 2 把本地文件上传到文件系统中
fileSystem.copyFromLocalFile(new Path("/Users/martin/Workspace/hadoop/helloHadoop.txt"),
new Path("/helloHadoop.copy.txt"));
// 3 关闭资源
fileSystem.close();
System.out.println("over");
}
}
注意:这里IDEA添加lib包,可以看Intellij IDEA 添加jar包的三种方式
4)执行程序
执行成功后,我们可以看见文件已经上传上去了。
3.2 通过API操作HDFS
- HDFS获取文件系统
@Test
public void getFileSystem() throws Exception
{
Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "martin");
System.out.println(fileSystem.toString());
}
- 文件上传
@Test
public void uploadFile() throws Exception
{
Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "martin");
fileSystem.copyFromLocalFile(true,new Path("/Users/martin/Downloads/martin.txt"),new Path("/"));
fileSystem.close();
System.out.println("upload finish");
}
- 文件下载
@Test
public void downloadFile() throws Exception
{
Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "martin");
fileSystem.copyToLocalFile(new Path("/martin.txt"),new Path("/Users/martin/Downloads/martin_down.txt"));
fileSystem.close();
System.out.println("download finish");
}
- 创建目录
@Test
public void mkdirAtHDFS() throws Exception
{
Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"),configuration,"martin");
fileSystem.mkdirs(new Path("/martin/upload"));
fileSystem.close();
System.out.println("make dir finish");
}
- 删除目录
@Test
public void deleteAtHDFS() throws Exception
{
Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"),configuration,"martin");
fileSystem.delete(new Path("/martin/upload"), true);
fileSystem.close();
System.out.println("delete finish");
}
- 重命名目录
@Test
public void renameAtHDFS() throws Exception
{
Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "martin");
fileSystem.rename(new Path("/martin.txt"), new Path("/martin_rename.txt"));
fileSystem.close();
System.out.println("rename finish");
}
- 读取文件
@Test
public void readFileAtHDFS() throws Exception
{
Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "martin");
RemoteIterator<LocatedFileStatus> listFiles = fileSystem.listFiles(new Path("/"), true);
while (listFiles.hasNext())
{
LocatedFileStatus status = listFiles.next();
System.out.println(status.getAccessTime());
System.out.println(status.getBlockSize());
System.out.println(status.getGroup());
System.out.println(status.getPermission());
}
fileSystem.close();
System.out.println("read finish");
}
- 读取文件夹
@Test
public void readFolderAtHDFS() throws Exception
{
Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "martin");
FileStatus[] listStatus = fileSystem.listStatus(new Path("/"));
for (FileStatus status : listStatus)
{
if (status.isFile())
{
System.out.println("f---"+status.getPath().getName());
}else
{
System.out.println("d---"+status.getPath().getName());
}
}
fileSystem.close();
System.out.println("read folder finish");
}
3.3 通过IO流操作HDFS
- 通过IO流上传文件
@Test
public void putFileToHDFS () throws Exception
{
Configuration conf = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), conf, "martin");
//输出流
FSDataOutputStream fos = fileSystem.create(new Path("/martin/io_test.md"));//FSDataOutputStream
//输入流
FileInputStream fis = new FileInputStream("/Users/martin/Downloads/io_test.md");
//对接
IOUtils.copyBytes(fis,fos,conf);
fileSystem.close();
}
- 通过IO流下载文件
@Test
public void loadFileFromHDFS() throws Exception
{
Configuration conf = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), conf, "martin");
//输入流
FSDataInputStream fis = fileSystem.open(new Path("/martin/io_test.md"));
//输出流
FileOutputStream fos = new FileOutputStream("/Users/martin/Downloads/io_test_from.md");
//duijie
IOUtils.copyBytes(fis,fos,conf);
fis.close();
fos.close();
fileSystem.close();
}
- 定位文件读取
@Test
public void loadFileFromHDFSSeek1() throws Exception
{
// 1 获取文件系统
Configuration conf = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), conf, "martin");
// 2 获取输入流
FSDataInputStream fis = fileSystem.open(new Path("/martin/hadoop-2.7.2.tar.gz"));
// 3 创建输入流
FileOutputStream fos = new FileOutputStream(new File("/Users/martin/Downloads/hadoop-2.7.2.tar.gz.part1"));
// 4 流对接 ()
byte[] buf = new byte[1024];
for (int i=0;i < 1024 * 128;i++)//1024 * 1024 * 128
{
fis.read(buf);
fos.write(buf);
}
// 5 关闭资源
IOUtils.closeStream(fis);
IOUtils.closeStream(fos);
}
@Test
public void loadFileFromHDFSSeek2() throws Exception
{
Configuration conf = new Configuration();
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), conf, "martin");
FSDataInputStream fis = fileSystem.open(new Path("/martin/hadoop-2.7.2.tar.gz"));
FileOutputStream fos = new FileOutputStream(new File("/Users/martin/Downloads/hadoop-2.7.2.tar.gz.part2"));
fis.seek(1024 * 1024 * 128 );
IOUtils.copyBytes(fis,fos,conf);
IOUtils.closeStream(fis);
IOUtils.closeStream(fos);
}
小结
这章我们通过集成Hadoop的jar包,使用了常用的API对HDFS系统进行了普通操作,下章节我们来对HDFS的流数据操作原理进行了解。