HDFS Java API 实战:文件创建 + Shell 脚本封装执行(附完整代码)
在大数据生态中,HDFS(Hadoop Distributed File System)是数据存储的核心组件。实际开发中,常需通过 Java API 操作 HDFS(如创建文件、上传数据),并通过 Shell 脚本简化执行流程。本文将详解 HDFS Java API 创建文件的核心逻辑、环境配置、完整代码,以及 Shell 脚本封装方案,帮助开发者快速落地 HDFS 文件操作需求。
一、核心原理与环境准备
1. 核心逻辑
HDFS Java API 创建文件的核心流程:
关键要点:
- Configuration:加载 HDFS 配置(如 NameNode 地址);
- FileSystem:HDFS 文件系统操作核心类,需通过FileSystem.get()获取实例;
- FSDataOutputStream:HDFS 文件输出流,用于写入数据。
2. 环境准备
|
工具 / 依赖 |
版本要求 |
作用描述 |
|
Java |
8+ |
核心开发语言 |
|
Hadoop |
3.x(示例:3.3.4) |
HDFS 核心依赖,提供 Java API |
|
Maven |
3.6+ |
依赖管理工具 |
|
集群环境 |
本地 Hadoop / 远程集群 |
需确保 HDFS 服务正常运行 |
3. 依赖配置(pom.xml)
需引入 Hadoop 核心依赖(HDFS API 包含在hadoop-hdfs-client中):
<dependencies>
<!-- Hadoop 核心依赖 -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.3.4</version>
</dependency>
<!-- HDFS Client 依赖(包含创建文件API) -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs-client</artifactId>
<version>3.3.4</version>
</dependency>
<!-- 日志依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.36</version>
<scope>runtime</scope>
</dependency>
</dependencies>
二、Java API 创建 HDFS 文件核心代码
Java 代码实现 “连接 HDFS→创建文件→写入内容→关闭资源” 全流程,代码仅 40 余行,支持本地 / 远程 HDFS 集群:
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 org.apache.hadoop.io.IOUtils;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URI;
public class HdfsFileCreator {
// HDFS 核心配置(根据实际集群修改)
private static final String HDFS_URI = "hdfs://localhost:9000"; // NameNode地址
private static final String HDFS_USER = "hadoop"; // HDFS操作用户(需与集群用户一致)
public static void main(String[] args) {
// 入参校验(接收2个参数:HDFS文件路径、文件内容)
if (args.length != 2) {
System.err.println("用法:java HdfsFileCreator <HDFS文件路径> <文件内容>");
System.exit(1);
}
String hdfsFilePath = args[0]; // 示例:/user/hadoop/test.txt
String fileContent = args[1]; // 示例:"Hello HDFS from Java API"
Configuration conf = new Configuration();
FileSystem fs = null;
InputStream in = null;
FSDataOutputStream out = null;
try {
// 1. 配置HDFS URI
conf.set("fs.defaultFS", HDFS_URI);
// 2. 获取FileSystem实例(指定用户,避免权限问题)
fs = FileSystem.get(new URI(HDFS_URI), conf, HDFS_USER);
// 3. 构造HDFS文件路径
Path path = new Path(hdfsFilePath);
// 4. 检查文件是否已存在,存在则删除(可选,根据需求调整)
if (fs.exists(path)) {
System.out.println("文件已存在,删除旧文件:" + hdfsFilePath);
fs.delete(path, false); // false:不递归删除(仅删除文件)
}
// 5. 创建文件并获取输出流
out = fs.create(path);
// 6. 写入文件内容(将字符串转为输入流)
in = new ByteArrayInputStream(fileContent.getBytes("UTF-8"));
// 7. 拷贝数据(IOUtils为Hadoop工具类,自动处理流)
IOUtils.copyBytes(in, out, conf);
System.out.println("HDFS文件创建成功!路径:" + hdfsFilePath);
} catch (Exception e) {
System.err.println("HDFS文件创建失败:" + e.getMessage());
e.printStackTrace();
System.exit(1);
} finally {
// 8. 关闭资源(避免泄漏)
IOUtils.closeStream(in);
IOUtils.closeStream(out);
try {
if (fs != null) fs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
关键代码说明
- 配置与权限:
-
- HDFS_URI:NameNode 地址(本地集群默认hdfs://localhost:9000,远程集群替换为hdfs://namenode-ip:9000);
-
- HDFS_USER:需指定 HDFS 集群的有效用户(如hadoop),避免权限拒绝(Permission denied)。
- 文件创建:fs.create(path) 用于创建新文件,返回FSDataOutputStream流;
- 资源关闭:使用 Hadoop 提供的IOUtils.closeStream()工具类,安全关闭流与FileSystem实例;
- 入参设计:支持通过命令行传入 HDFS 文件路径和内容,便于 Shell 脚本调用。

三、Shell 脚本封装执行(一键运行)
为简化执行流程,编写 Shell 脚本封装 “编译→打包→运行” 全步骤,无需手动执行复杂命令:
1. Shell 脚本(create_hdfs_file.sh)
#!/bin/bash
# 描述:HDFS文件创建脚本(封装Java程序执行)
# 用法:./create_hdfs_file.sh <HDFS文件路径> <文件内容>
# 检查入参
if [ $# -ne 2 ]; then
echo "用法错误!正确用法:"
echo "./create_hdfs_file.sh <HDFS文件路径> <文件内容>"
echo "示例:./create_hdfs_file.sh /user/hadoop/test.txt 'Hello HDFS'"
exit 1
fi
# 定义变量
HDFS_FILE_PATH=$1
FILE_CONTENT=$2
PROJECT_DIR=$(cd $(dirname $0); pwd) # 项目根目录
JAR_NAME="hdfs-file-creator-1.0.jar" # 打包后的JAR文件名
MAIN_CLASS="HdfsFileCreator" # 主类名
# 1. 编译Java代码(需确保当前目录为项目根目录,src/main/java为源码路径)
echo "开始编译Java代码..."
javac -cp $(hadoop classpath) -d $PROJECT_DIR/target/classes $PROJECT_DIR/src/main/java/HdfsFileCreator.java
# 2. 打包为JAR文件(无需Manifest,通过指定主类运行)
echo "开始打包JAR文件..."
jar -cvf $PROJECT_DIR/target/$JAR_NAME -C $PROJECT_DIR/target/classes .
# 3. 运行Java程序(通过hadoop jar命令执行,自动加载Hadoop依赖)
echo "开始创建HDFS文件:$HDFS_FILE_PATH"
hadoop jar $PROJECT_DIR/target/$JAR_NAME $MAIN_CLASS $HDFS_FILE_PATH "$FILE_CONTENT"
# 4. 检查执行结果
if [ $? -eq 0 ]; then
echo "文件创建成功!可通过以下命令验证:"
echo "hadoop fs -ls $(dirname $HDFS_FILE_PATH)" # 列出目录
echo "hadoop fs -cat $HDFS_FILE_PATH" # 查看文件内容
else
echo "文件创建失败!"
exit 1
fi
2. 脚本关键说明
- 依赖加载:使用hadoop classpath自动获取 Hadoop 所有依赖的类路径,避免手动配置复杂依赖;
- 编译打包:
-
- javac 编译 Java 代码,输出 class 文件到target/classes目录;
-
- jar 命令打包 class 文件为 JAR(无需手动创建 Manifest 文件);
- 运行方式:通过hadoop jar命令运行 JAR 包,Hadoop 会自动加载自身依赖,避免类找不到(ClassNotFoundException);
- 结果验证:脚本执行成功后,自动提示验证命令(hadoop fs -ls/hadoop fs -cat)。
四、运行测试步骤(本地 Hadoop 示例)
1. 前提条件
- 本地 Hadoop 集群已启动(start-dfs.sh);
- 已配置JAVA_HOME和HADOOP_HOME环境变量(确保hadoop命令可全局执行)。
2. 测试步骤
(1)项目目录结构
确保项目目录结构如下(与 Shell 脚本适配):
hdfs-file-creator/
├── src/
│ └── main/
│ └── java/
│ └── HdfsFileCreator.java # Java核心代码
└── create_hdfs_file.sh # Shell脚本
(2)赋予脚本执行权限
chmod +x create_hdfs_file.sh
(3)执行脚本创建 HDFS 文件
./create_hdfs_file.sh /user/hadoop/test.txt "Hello HDFS from Shell + Java API"
(4)验证结果
脚本执行成功后,输出如下信息:
开始编译Java代码...
开始打包JAR文件...
开始创建HDFS文件:/user/hadoop/test.txt
HDFS文件创建成功!路径:/user/hadoop/test.txt
文件创建成功!可通过以下命令验证:
hadoop fs -ls /user/hadoop
hadoop fs -cat /user/hadoop/test.txt
执行验证命令,确认文件存在且内容正确:
# 查看文件是否存在
hadoop fs -ls /user/hadoop
# 查看文件内容
hadoop fs -cat /user/hadoop/test.txt
五、避坑指南与常见问题解决
1. 权限问题(Permission denied)
- 原因:HDFS_USER配置错误,或执行用户无 HDFS 目录写入权限;
- 解决:
-
- 确认HDFS_USER为集群有效用户(如hadoop);
-
- 给 HDFS 目录授权:hadoop fs -chmod 777 /user/hadoop(测试环境,生产环境谨慎使用)。
2. 连接超时(Connection refused)
- 原因:NameNode 地址错误,或 HDFS 服务未启动;
- 解决:
-
- 检查HDFS_URI是否正确(远程集群需确保 NameNode IP 可访问);
-
- 启动 HDFS 服务:start-dfs.sh。
3. 类找不到(ClassNotFoundException)
- 原因:未加载 Hadoop 依赖,或 JAR 包打包错误;
- 解决:
-
- 编译时通过-cp $(hadoop classpath)加载依赖;
-
- 运行时使用hadoop jar命令,而非java -jar。
4. 中文乱码
- 原因:文件内容包含中文时,编码不一致;
- 解决:Java 代码中指定 UTF-8 编码(new ByteArrayInputStream(fileContent.getBytes("UTF-8")))。
六、进阶扩展与最佳实践
1. 功能扩展
- 文件上传:修改 Java 代码,支持从本地文件上传到 HDFS(将ByteArrayInputStream替换为FileInputStream);
- 批量创建:扩展 Shell 脚本,支持从配置文件读取多个文件路径和内容,批量创建;
- 权限设置:创建文件时指定权限(如fs.create(path, (short) 0644)),0644 表示所有者可读可写,其他用户可读。
2. 生产环境最佳实践
- 配置分离:将HDFS_URI、HDFS_USER等配置抽离为配置文件(如hdfs-config.properties),避免硬编码;
- 日志输出:集成 Logback/Log4j,将运行日志输出到文件,便于问题排查;
- 异常重试:添加重试机制(如网络波动导致创建失败时,重试 3 次);
- 安全认证:若 HDFS 集群开启 Kerberos 认证,需在Configuration中添加 Kerberos 配置(如krb5.conf路径、认证票据)。
总结
本文通过 “Java API 核心实现 + Shell 脚本封装”,提供了一套轻量、可落地的 HDFS 文件创建方案:
- Java 代码简洁高效(40 余行),覆盖连接、创建、写入、资源释放全流程,支持本地 / 远程集群;
- Shell 脚本一键运行,封装编译、打包、执行步骤,降低使用门槛;
- 解决了权限、依赖、编码等常见问题,可直接应用于开发 / 测试环境。
该方案适用于大数据场景中 HDFS 文件的自动化创建需求(如定时任务、数据导入前置步骤),如需扩展其他 HDFS 操作(如删除、重命名、上传文件夹),可基于本文代码框架快速迭代。
更多推荐
所有评论(0)