HDFS 编程实践主要涉及三种方式:Shell 命令、Web 界面以及 Java API。通过 Shell 可以快速管理文件,Web 页面适合监控集群状态,而 Java API 则提供了更灵活的开发能力。本文以 Hadoop 3.x 版本为例,介绍这些操作的核心用法及实战流程。
HDFS 常用 Shell 命令
hadoop fs 是 HDFS 最常用的命令工具,适用于本地和分布式文件系统。相比 hadoop dfs 或 hdfs dfs(仅支持 HDFS),hadoop fs 的通用性更强。基本语法如下:
hadoop fs [genericOptions][commandOptions]
以下是一些高频使用的命令,实际开发中建议熟记:
hadoop fs -ls <path>:查看指定路径的文件详情。hadoop fs -ls -R <path>:递归列出目录内容。hadoop fs -cat <path>:输出文件内容到标准输出。hadoop fs -mkdir [-p] <paths>:创建文件夹,-p支持递归创建。hadoop fs -copyFromLocal <localsrc> <dst>:上传本地文件到 HDFS。hadoop fs -put <localsrc> <dst>:功能同上传,也支持从 stdin 读取。hadoop fs -get [-ignorecrc] [-crc] <src> <localdst>:下载 HDFS 文件到本地。hadoop fs -rm -r <path>:递归删除文件或目录。hadoop fs -setrep [-R] <path>:修改文件副本系数。hadoop fs -test -ezd <path>:测试文件属性(存在、大小、是否为目录)。
HDFS Web 管理界面
配置好集群后,可以通过浏览器访问 NameNode 的 Web UI(默认端口 9870)。例如在伪分布式模式下,访问 http://localhost:9870 即可查看文件系统信息。
该界面能直观展示节点分布、存储日志及文件浏览情况。虽然大部分功能可通过 Shell 命令实现,但 Web 界面在排查问题时更为便捷。例如,通过'Browse the filesystem'查看目录结构,等价于执行 hadoop fs -ls /。
HDFS Java API 实战
Hadoop 核心基于 Java 构建,Java API 是进行复杂业务逻辑开发的首选。下面介绍核心类及一个完整的文件合并示例。
核心 API 类
- FileSystem:通用文件系统抽象基类,所有 HDFS 操作的基础。
- FileStatus:获取文件和目录的元数据(大小、权限、所有者等)。
- FSDataInputStream / FSDataOutputStream:用于读写 HDFS 文件。
- Configuration:加载配置文件(如 core-site.xml)中的参数。
- Path:表示 HDFS 中的文件路径。
- PathFilter:自定义过滤器,用于筛选特定路径的文件。
实例:合并 HDFS 文件
假设我们需要将 HDFS 目录下符合特定规则的文件合并为一个新文件。以下是完整实现步骤。
1. 项目初始化
在 Eclipse 中创建 Java 工程,命名为 HDFSExample。确保 JDK 版本与 Hadoop 兼容(推荐 JDK 1.8+)。
2. 引入依赖
Hadoop 的 JAR 包通常位于安装目录下的 share/hadoop 子目录中。需要手动添加以下依赖到项目 Build Path:
hadoop-common相关 JAR 包hadoop-hdfs相关 JAR 包- 对应的
lib子目录下的依赖
具体路径参考你的实际安装位置,例如 /usr/local/hadoop/share/hadoop/common。
3. 编写代码
创建一个名为 MergeFile 的主类。这里我们自定义了一个 MyPathFilter 来过滤掉不需要的后缀文件(如 .abc)。
import java.io.IOException;
import java.io.PrintStream;
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
/**
* 过滤掉文件名满足特定条件的文件
*/
class MyPathFilter implements PathFilter {
String reg = null;
MyPathFilter(String reg) {
this.reg = reg;
}
public boolean accept(Path path) {
if (!(path.toString().matches(reg))) return true;
return false;
}
}
/**
* 利用 FSDataOutputStream 和 FSDataInputStream 合并 HDFS 中的文件
*/
public class MergeFile {
Path inputPath = null; // 待合并的文件所在的目录的路径
Path outputPath = null; // 输出文件的路径
public MergeFile(String input, String output) {
this.inputPath = new Path(input);
this.outputPath = new Path(output);
}
public void doMerge() throws IOException {
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://localhost:9000");
conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
FileSystem fsSource = FileSystem.get(URI.create(inputPath.toString()), conf);
FileSystem fsDst = FileSystem.get(URI.create(outputPath.toString()), conf);
// 过滤掉输入目录中后缀为.abc 的文件
FileStatus[] sourceStatus = fsSource.listStatus(inputPath, new MyPathFilter(".*\\.abc"));
FSDataOutputStream fsdos = fsDst.create(outputPath);
PrintStream ps = new PrintStream(System.out);
// 分别读取过滤之后的每个文件的内容,并输出到同一个文件中
for (FileStatus sta : sourceStatus) {
System.out.print("路径:" + sta.getPath() + " 文件大小:" + sta.getLen() + " 权限:" + sta.getPermission() + " 内容:");
FSDataInputStream fsdis = fsSource.open(sta.getPath());
byte[] data = new byte[1024];
int read = -1;
while ((read = fsdis.read(data)) > 0) {
ps.write(data, 0, read);
fsdos.write(data, 0, read);
}
fsdis.close();
}
ps.close();
fsdos.close();
}
public static void main(String[] args) throws IOException {
MergeFile merge = new MergeFile("hdfs://localhost:9000/user/hadoop/", "hdfs://localhost:9000/user/hadoop/merge.txt");
merge.doMerge();
}
}
4. 编译运行
确保 Hadoop 集群已启动,且目标目录下存在测试文件。在 Eclipse 中选择 Run As -> Java Application 即可执行。
控制台会输出处理日志,若成功,可在终端验证结果:
./bin/hdfs dfs -cat /user/hadoop/merge.txt
5. 打包部署
生产环境中,通常需要将应用打包成 JAR 提交到集群运行。
- 在 Eclipse 中选择
Export -> Runnable JAR file。 - 设置主类为
MergeFile-HDFSExample。 - 勾选
Extract required libraries into generated JAR以包含依赖。 - 导出为
HDFSExample.jar。
使用 hadoop jar 命令提交任务:
./bin/hadoop jar ./myapp/HDFSExample.jar
总结
HDFS 的编程接口丰富且实用。对于简单的文件管理,Shell 命令效率最高;对于需要监控的场景,Web 界面一目了然;而对于复杂的业务逻辑,Java API 提供了足够的灵活性。掌握 FileSystem 类的使用、理解流式读写机制,并结合 PathFilter 等工具,就能高效地构建基于 Hadoop 的数据处理应用。


