HDFS的Java操作
HDFS在生产应用中主要是客户端的开发,其核心步骤是从HDFS提供的API中构造一个HDFS的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS上的文件
搭建开发环境
开发工具:IDEA
管理工具:Maven
JDK:1.8
Hadoop:2.7.4
建议在Linux/Unix下进行hadoop应用的开发,不会存在兼容性问题。如在window上做客户端应用开发,需要设置以下环境:
- 在windows的某个目录下解压一个hadoop的安装包
- 到网上下载winutils支持和hadoop.dll等文件,丢到HADOOP_HOME\bin目录中去,将其中的hadoop.dll在c:/windows/System32下也丢一份;你可以直接到这里下载
- 在window系统中配置HADOOP_HOME指向你解压的安装包
- 在windows系统的path变量中加入hadoop的bin目录
开始创建项目
新建一个maven项目
编辑pom.xml,引入hadoop客户端依赖
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.4</version>
</dependency>
编写测试类,构造HDFS客户端实例
public class HdfsClient {
private FileSystem fs;
@Before
public void init() throws Exception {
// 构造一个配置参数对象
// 参数优先级说明:代码中设置的会覆盖classpath下的配置,classpath下的配置覆盖hadoop-client.jar中的默认配置
Configuration conf = new Configuration();
// 这里暂不做任何配置,使用的是jar包的默认值
/*
参数一:NameNode所在节点
参数二:配置参数对象
参数三:用户身份
*/
fs = FileSystem.get(new URI("hdfs://hadoop.master:9000"), conf, "hadoop");
}
}
上传文件
/**
* 上传文件到HDFS
*/
@Test
public void testPutFile() throws Exception {
// 本地文件路径
Path src = new Path("/Users/gethin/test.file");
// 上传到HDFS的目标路径
Path dst = new Path("/");
fs.copyFromLocalFile(src,dst);
fs.close();
}
下载文件
/**
* 从HDFS下载文件到本地
*/
@Test
public void testDownloadFileToLocal() throws Exception {
// 要下载的文件路径(HDFS上)
Path src = new Path("/test.file");
// 本地保存路径
Path dst = new Path("/Users/gethin/");
fs.copyToLocalFile(src, dst);
fs.close();
}
目录创建、删除及重命名
/**
* 目录创建、删除及重命名
*/
@Test
public void testMkdirAndDeleteAndRename() throws Exception {
// 创建目录(支持递归创建)
fs.mkdirs(new Path("/a1/b1/c1"));
// 删除文件夹 ,如果是非空文件夹,参数2必须给值true
fs.delete(new Path("/b1"), true);
// 重命名文件或文件夹,将a1修改成a2
fs.rename(new Path("/a1"), new Path("/a2"));
}
查看目录信息(不能理解的话直接跑下一,看下结果就明白了)
/**
* 查看目录信息,只显示文件
*/
@Test
public void testListFiles() throws Exception {
// 查看根目录
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
while (listFiles.hasNext()) {
LocatedFileStatus fileStatus = listFiles.next();
System.out.println(fileStatus.getPath().getName()); // 文件名
System.out.println(fileStatus.getBlockSize()); // 块的大小
System.out.println(fileStatus.getPermission()); // 块的副本
System.out.println(fileStatus.getLen()); // 块的数据长度
// 数据块在哪些节点上
BlockLocation[] blockLocations = fileStatus.getBlockLocations();
for (BlockLocation bl : blockLocations) {
// 数据块的偏移量
System.out.println("block-length:" + bl.getLength() + "--" + "block-offset:" + bl.getOffset());
String[] hosts = bl.getHosts(); // 块的副本都在哪些节点上
for (String host : hosts) {
System.out.println(host); // 主机名
}
}
System.out.println("--------------打印的分割线--------------");
}
}
查看文件及文件夹信息
/**
* 查看文件及文件夹信息
*/
@Test
public void testListAll() throws Exception {
FileStatus[] listStatus = fs.listStatus(new Path("/"));
for (FileStatus fstatus : listStatus) {
// 是文件
if (fstatus.isFile()){
System.out.println("f-- " + fstatus.getPath().getName());
}else {
// 是目录
System.out.println("d-- " + fstatus.getPath().getName());
}
}
}