HDFS Java API 位于 org.apache.hadoop.fs
包中,这些API能够支持的操作包括打开文件、读写文件、删除文件等。Hadoop类库中最终面向用户提供的接口类是FileSystem
。该类是一个抽象类,只能通过get
方法获取到具体的类。该类封装了大部分文件操作,如mkdir
、delete
等。
<!--指定maven项目jdk编译版本,默认是jdk1.5-->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
HDFS Java API 的一般用法
HDFS Java API为客户端提供了针对文件系统、目录和文件的各种操作功能。在客户端应用程序中,通常按以下步骤来使用HDFS Java API。
实例化Configuration类 :Configuration
类位于org.apache.hadoop.conf
包中,它封装了客户端或服务器的配置。每个配置选项是一个键/值对,通常以XML
格式保存。
Configuration conf = new Configuration();
默认情况下,Configuration 的实例会自动加载HDFS的配置文件core-site.xml,从中获取Hadoop集群的配置信息。为了保证程序能够成功加载,一般放于项目根目录下。
实例化FileSystem类:FileSystem
类是客户端访问文件系统的入口,是Hadoop
为客户端提供的一个抽象的文件系统。DistributedFileSystem
类是FileSystem
的一个具体实现,是HDFS
真正的客户端API
。
FileSytem fs = FileSystem.get(uri, conf, user); //伪装用户操作文件系统
设置目标对象的路径:HDFS API提供Path类来封装HDFS文件路径。Path类位于org.apache.hadoop.fs
包中。
Path path = new Path("/test");
执行文件或目录操作:得到FileSystem实例之后,就可以使用该实例提供的方法成员来执相应的操作,例如打开文件、创建文件、重名文件、删除文件或检测文件是否存在等。
返回值类型 | 方法名称及参数 | 功能说明 |
void |
| 从本地磁盘复制文件到HDFS |
void |
| 从HDFS复制文件到本地磁盘 |
abstract boolean |
| 修改目录或文件名 |
boolean |
| 删除指定文件 |
long |
| 返回文件长度 |
boolean |
| 指定文件是否为目录 |
boolean |
| 指定 path 是否为文件 |
boolean |
| 建立子目录 |
boolean |
| 检查指定文件是否存在 |
long | getBlockSize(Path f) | 返回指定文件的数据块大小 |
short | getDefaultReplication(Path f) | 返回默认的副本系数 |
abstract FileStatus | getFileStatus(Path f) | 返回指定文件的状态 |
void | moveFromLocalFile(Path[] src, Path dsc) | 把本地文件迁移到HDFS |
void | moveToLocalFile(Path src, Path dsc) | 把HDFS文件迁移到本地磁盘 |
FSDataInputStream | open(Path f) | 打开指定的文件 |
FSDataOutputStream | create(Path f) | 创建一个文件 |
文件上传与下载
@Test
public void testUpload() throws Exception{
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create("hdfs://node:9000"), conf,"root");
fs.copyFromLocalFile(new Path("E:\\大数据搭建环境工具\\《HIVE环境搭建1》.pdf"),new Path("/"));
System.out.println("文件上传成功~");
}
@Test
public void hdfsDownLoad() throws Exception{
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create("hdfs://node:9000"), conf,"root");
fs.copyToLocalFile(new Path("/《HIVE环境搭建1》.pdf"),new Path("E:\\test.pdf"));
System.out.println("文件数据读取成功~");
}
文件读取
客户端将要读取的文件路径发送给NameNode
,NameNode
获取文件的元信息(主要是block
的存放位置信息)返回给客户端,客户端根据返回的信息找到相应DatNode
逐个获取文件的block
并在客户端本地进行数据追加合并从而获得整个文件。
- HDFS 客户端通过
DistributedFileSystem
对象的open()
方法打开要读取的文件。 -
DistributedFileSystem
负责向远程的名称节点NameNode
发起RPC
调用,得到文件的数据块信息,返回数据块列表。对于每个数据块,NameNode
返回该数据块的DataNode
地址 -
DistributedFileSystem
返回一个FSDataInputStream
对象给客户端,客户端调用FSDataInputStream
对象的read()
方法开始读取数据 - 通过对数据流反复调用
read()
方法,把数据从数据节点传输到客户端 - 当客户端读取完数据时,调用
FSDataInputStream
对象的close()
方法关闭读取流。
返回值 | 方法名词及参数 | 说明 |
int | read(byte[] buf) | 把数据读取到缓冲中。 |
void | seek(long offset) | 指定输入流的第offset字节 |
readBoolean、readByte、readInt、readUTF、.... | 这些方法继承自 |
@Test
public void hdfsReader() throws Exception{
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create("hdfs://node:9000"), conf,"root");
Path path = new Path("/file/test2.txt");
FSDataInputStream fis = fs.open(path);
byte[] b = new byte[1024];
int len = -1;
while ((len=fis.read(b))!=-1){
System.out.println(new String(b, 0, len));
}
System.out.println("文件数据读取成功~");
}
文件写入
客户端要向HDFS
写数据,首先跟NameNode
通信以确认可以写文件并获得接收文件Block
的DataNode
,然后客户端按顺序将文件逐个Block
传递给相应DataNode
,并由接收到Block
的DataNode
负责向其他DataNode
复制Block
副本默认情况下每个Block
都有三个副本,HDFS 数据存储单元(Block
)。
- HDSF客户端调用
DistributedFileSystem
对象的create()
方法创建一个文件写入流对象 -
DistributedFileSystem
对象向远程的NameNode
节点发起一次RPC
调用,NameNode
检查该文件是否已经存在,以及客户端是否有权限新建文件 - 客户端调用
FSOutputStream
对象的write()
方法写数据,数据先被写入缓冲区,再被切分为一个个数据包。 - 每个数据包被发送到由
NameNode
节点分配的一组数据节点的一个节点上,在这组数据节点组成的管道上依次传输数据包 - 管道上的数据节点按反向顺序返回确认信息,最终由管道中的第一个数据节点将整条管道的确认信息发送给客户端
- 客户端完成写入,调用
close()
方法关闭文件写入流 - 通知
NameNode
文件写入成功
返回值 | 方法名称 | 说明 |
void | close() | 关闭输出流 |
long | getPos() | 获取输出流的当前位置 |
void | hflush() | 清理客户端用户缓冲中的数据 |
void | hsync() | 把客户端用户缓冲中的数据同步到磁盘之中 |
writeByte、writeChars、writeInt、writeUTF | 这写方法继承自java.io.DataOutputStream |
@Test
public void hdfsWriter() throws Exception{
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create("hdfs://node:9000"), conf,"root");
Path path = new Path("/file/test2.txt");
FSDataOutputStream fos = fs.create(path);
fos.writeUTF("你好,我是客户端传递的数据1");
fos.writeUTF("你好,我是客户端传递的数据2");
fos.writeUTF("你好,我是客户端传递的数据3");
fos.close();
fs.close();
System.out.println("文件数据写入成功~");
}
Permission denied: user=xx, access=WRITE, inode="/file/test.txt" :root:supergroup:drwxr-xr-x
,表示user=xx没有写入数据的权限,需要伪造用户或修改操作权限