二、HDFS的应用开发
HDFS的JAVA API操作
- 需要注意客户端身份的设定 使得身份符合hdfs对应路径的操作权限
- 配置环境变量(HADOOP_HOME、path)
- 因为在windows上做HDFS客户端应用开发,需要设置Hadoop环境,而且要求是windows平台编译的Hadoop,否则会报“找不到winutils.exe”的错误。hadoop涉及往windows进行数据写操作的时候 需要winutils工具跟windows平台进行交互,负责数据的写操作。该工具由hadoop提供 但是需要下载源码在windows编译。
- 解决:下载hadoop源码 在windows平台编译(支持C++环境)
- 配置:把windows版本的hadoop在操作系统上配置环境变量 重启idea - 搭建开发环境(创建maven工程,引入pom依赖)
HADOOP_HOME=hadoop安装目录
path=%HADOOP_HOME%\bin
方案一,使用cdh仓库的依赖:
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/clouderarepos/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0-mr1-cdh5.14.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.6.0-cdh5.14.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.6.0-cdh5.14.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.6.0-cdh5.14.0</version>
</dependency>
</dependencies>
方案二,使用apache hadooop的依赖:
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
注:两种方案api都一样。
- 构建客户端对象
Configuration:该类的对象封装了客户端或者服务器的配置。
FileSystem:该类的对象是一个文件系统对象,可以用该对象的一些方法来对文件进行操作,通过FileSystem的静态方法get获得该对象。
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class HdfsTest {
public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
// 配置参数,指定相关属性信息
Configuration config = new Configuration();
/*
设置文件系统为hdfs
通过FileSystem静态对象获取文件系统实例
构造文件系统实例同时指定操作文件系统的用户身份
*/
/* 方案一:
config.set("fs.defaultFS", "hdfs://node01:9000");
System.setProperty("HADOOP_USER_NAME", "root");
FileSystem fs = FileSystem.get(config);
*/
// 方案二:
FileSystem fs = FileSystem.get(new URI("hdfs://node01:9000"), config, "root");
// 创建文件夹
fs.mkdirs(new Path("/createByJava"));
// 上传文件
fs.copyFromLocalFile(new Path("D:\\test\\1.txt"), new Path("/createByJava/1.txt"));
// 下载文件
fs.copyToLocalFile(new Path("/createByJava/1.txt"), new Path("D:\\test\\2.txt"));
// 更加底层的方式操作hdfs,后续mr、spark程序底层都是通过stream形式操作文件的
FSDataOutputStream out = fs.create(new Path("/createByJava/2.txt"));
FileInputStream in = new FileInputStream("D:\\test\\1.txt");
IOUtils.copy(in, out);
// 关闭文件系统
fs.close();
}
}
get方法从conf中的一个参数fs.defaultFS的配置值判断具体是什么类型的文件系统。如果我们的代码中没有指定fs.defaultFS,并且工程classpath下也没有给定相应的配置,conf中的默认值就来自于hadoop的jar包中的core-default.xml,默认值为:file:///,则获取的将不是一个DistributedFileSystem的实例,而是一个本地文件系统的客户端对象。