HDFS Java API 位于 org.apache.hadoop.fs
包中,这些API能够支持的操作包括打开文件、读写文件、删除文件等。Hadoop类库中最终面向用户提供的接口类是FileSystem
。该类是一个抽象类,只能通过get
方法获取到具体的类。该类封装了大部分文件操作,如mkdir
、delete
等。
8
8
org.apache.hadoop
hadoop-client
2.7.3
junit
junit
4.12
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
并在客户端本地进行数据追加合并从而获得整个文件。
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
)。
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没有写入数据的权限,需要伪造用户或修改操作权限