使用 Hadoop API 操作HDFS文件系统

本文最后更新于:2 年前

HDFS 在生产应用中主要是 Java 客户端的开发,其核心步骤是从 HDFS 提供的 API 中构造一个 HDFS 的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS 上的文件。

客户端核心类:

  • Configuration :配置对象类,用于加载或设置参数属性。
  • FileSystem:文件系统对象基类,针对不同文件系统有不同具体实现。该类封装了文件系统的相关操作方法。

API 核心类

org.apache.hadoop.conf.Configuration

org.apache.hadoop.conf.Configuration是配置对象类,封装了客户端或服务器的配置,用于加载或设置参数属性。

配置信息都是 hadoop 的默认配置,如果想要将配置修改成用户自定义配置,可以通过两种方式:

  • 通过配置文件(修改 core-site.cml 和 hdfs.xml)

  • 通过该对象实现,通过 < 属性名:属性值 >(k-v)指定

    1
    2
    3
    4
    Configuration conf = new Configuration ();
    // 设置文件系统为 HDFS ,并指定存储的副本数为 1
    conf .set ("fs.defaultFS" ,"hdfs://192.168.59.100:9000" );
    conf .set ("dfs.replication" ,"1" );

org.apache.hadoop.fs.FileSystem

org.apache.hadoop.fs.FileSystem 是文件系统对象抽象基类,针对不同文件系统有不同具体实现,可以被分布式文件系统继承。该类封装了文件系统的相关操作方法。

所有可能使用 Hadoop 文件系统的代码,都会用到这个类。虽然 Hadoop 为 FileSystem 提供了很多的具体实现,但是还是建议使用该抽象类完成文件系统的操作,这样做可以在不同的文件系统中移植。

  • 方式一

    主要用于在配置信息对象中已经指定了 Hadoop 的文件系统。

    1
    FileSystem fs = FileSystem .get (Configuration conf );
  • 方式二

    用于在 conf(配置信息对象)中没有指定 Hadoop 使用的文件系统时,通过 URI 指定文件系
    统。

    1
    FileSystem fs = FileSystem .get (URI arg0 , Configuration arg1 );
  • 方式三

    用于在 conf(配置信息对象)中没有指定 Hadoop 使用的文件系统时,通过 URI 指定文件系
    统,同时指定用户名。

    1
    2
    //String user 为指定的用户名, Hadoop 允许指定其他名称的用户名
    FileSystem fs = FileSystem .get (URI uri , Configuration conf , String user )

API操作HDFS文件系统

获取连接

1
2
3
4
5
6
7
8
9
10
11
//创建配置对象实例
Configuration conf = new Configuration ();

//获取 hadoop 文件系统对象
// 参数 1:hdfs 的地址   参数 2:配置对象
FileSystem fs = FileSystem.get(new URI ("hdfs://192.168.59.100:9000" ), conf );
System .out .println ("获取连接成功 ~" );

//关闭客户端和hdfs的连接
fs .close ();
}

如果报权限错误,可添加一行语句设置客户端的访问权限:

1
2
3
4
5
6
7
8
9
10
11
//设置客户端的访问权限,以具备权限在hdfs上进行访问
System.setProperty("HADOOP_USER_NAME","root");

//创建配置对象实例
Configuration conf = new Configuration ();
//设置我们要操作的文件系统是HDFS,并且指定HDFS操作地址
conf.set("fs.defaultFS", "hdfs://192.168.59.100:9000");
//创建FileSystem对象实例
fs = FileSystem.get(conf);
System .out .println ("获取连接成功 ~" );
fs.close();

文件操作

查看目录

org.apache.hadoop.fs.FileStatus :一个用于向客户端展示系统中的文件和目录的元数据的接口。展示的信息包括:路径、文件大小、块大小、副本信息、所有者、群组、修改时间等。

获得具体的实例对象方法如下:

1
FileSystem .listStatus ();

查看目录代码具体内容如下:

1
2
3
4
5
6
7
//查看目录
FileStatus[] arr = fs.listStatus(new Path("/"));

//遍历打印
for (FileStatus f : arr) {
System.out.println(f);
}

创建文件夹

1
2
3
4
//首先判断文件夹是否存在,不存在就创建
if (!fs.exists(new Path("/idea"))){
fs.mkdirs(new Path("/idea"));
}

上传文件

常用方法

1
2
3
4
5
6
7
8
9
10
11
12
//创建本地输入流读取本地数据
InputStream in = new FileInputStream(new File("HDFSTest.txt"));

//获取HDFS输出流
FSDataOutputStream out = fs.create(new Path("/HDFSTest.txt"));

//数据传输
IOUtils.copyBytes(in, out, conf);

//关流
out.close();
in.close();

或:

1
2
3
4
5
6
7
//创建本地文件路径
Path src = new Path("D:\\Desktop\\setup.txt");
//创建hdfs上传路径
Path dst = new Path("/idea/setup.txt");

//上传本地文件至hdfs
fs.copyFromLocalFile(src,dst);

下载文件

常用方法

1
2
3
4
5
6
7
8
FSDataInputStream in = fs.open(new Path("/idea/setup.txt"));
//创建本地文件的输出流
OutputStream out = new FileOutputStream(new File("D:/setup.txt"));
//通过Hadoop的IO工具包完成数据传输
IOUtils.copyBytes(in, out, conf);
//关流
out.close();
in.close();

或:

1
2
3
4
5
6
7
//源路径:hdfs的路径
Path src = new Path("/idea/setup.txt");
//目标路径:local本地文件路径
Path dst = new Path("D:/setup.txt");

//下载hdfs文件至本地
fs.copyToLocalFile(src,dst);

删除文件

常用方法

1
2
3
4
5
6
7
8
9
10
11
12
fs.delete(new Path("/.txt.txt"));
//删除空目录
fs.delete(new Path("/park04"));
//删除非空目录
fs.delete(new Path("/park01"));

/*
* 参数1:要删除的文件/目录的路径
* 参数2:true表示递归删除,
* false只能删除文件或空目录,如果要删除的目录不为空,会报以下异常:
*/
fs.delete(new Path("/park01"), false);

查看文件内容

常用方法

1
2
3
4
5
6
7
8
9
10
//获取读取数据的输入流
FSDataInputStream in = fs.open(new Path("/test1.txt"));
//读取输入流的内容
BufferedReader read = new BufferedReader(new InputStreamReader(in,"utf-8"));

//按行读取的内容
String line = null;
while((line=read.readLine())!=null){
System.out.println(line);
}

文件查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 用正则表达式过滤文件路径
*/
public class RegexPathFilter implements PathFilter {

private String regex;

public RegexPathFilter(String regex) {
this.regex = regex;
}

@Override
public boolean accept(Path path) {
return path.toString().matches(regex);
}
}
1
2
3
4
5
6
//文件查询--匹配txt文件
FileStatus[] listStatuses = fs.listStatus(new Path("/"), new RegexPathFilter("^.*(.txt)+$"));

for (FileStatus f : listStatuses) {
System.out.println(f);
}

重命名/移动

常用方法

1
2
3
4
5
6
7
8
//重命名
fs.rename(new Path("/setup.txt"), new Path("/null.txt"));

//移动
fs.rename(new Path("/null.txt"), new Path("/idea"));

//移动+重命名
fs.rename(new Path("/idea/null.txt"), new Path("/move.txt"));


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!