如何不借助本地文件系统将HDFS内多文件合并为单个HDFS文件?
嘿,刚好我之前也碰到过这个HDFS多文件合并的问题,给你几个完全不用依赖本地文件系统的靠谱解决方案:
方案1:从源头避免生成多文件(最省心)
既然你的多文件是MapReduce作业输出的,那最简单的办法就是让作业直接输出单个文件——MapReduce默认会给每个Reducer生成一个part-r-xxxx文件,所以只要把Reducer数量设为1就行:
提交作业时指定参数
hadoop jar your-mapreduce-job.jar -D mapreduce.job.reduces=1
或者在代码中配置
Configuration conf = new Configuration(); // 设置Reducer数量为1 conf.setInt("mapreduce.job.reduces", 1); Job job = Job.getInstance(conf);
⚠️ 注意:这个方法适合数据集不大的场景,因为所有数据都会集中到一个Reducer处理,数据量过大时会拖慢作业速度。
方案2:用Hadoop FileSystem API写个轻量合并工具
如果已经生成了多文件,不想重新跑作业,可以写个简单的Java程序,直接在HDFS内部完成文件合并,完全不经过本地:
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import java.io.IOException; import java.util.Arrays; public class HDFSInternalMerger { public static void main(String[] args) throws IOException { Configuration conf = new Configuration(); FileSystem hdfs = FileSystem.get(conf); // 替换成你的MapReduce输出目录 Path inputDir = new Path("/user/your-name/mr-output-dir"); // 替换成你要生成的合并后文件路径 Path mergedFile = new Path("/user/your-name/merged-result.txt"); // 先删除已存在的目标文件(可选) if (hdfs.exists(mergedFile)) { hdfs.delete(mergedFile, false); } // 创建目标文件输出流 try (FSDataOutputStream outStream = hdfs.create(mergedFile)) { // 遍历输入目录下的文件,跳过_SUCCESS、.crc这类无关文件 FileStatus[] fileStatuses = hdfs.listStatus( inputDir, path -> !path.getName().startsWith("_") && !path.getName().endsWith(".crc") ); // 按文件名排序,保证合并顺序和原文件一致 Arrays.sort(fileStatuses, (a, b) -> a.getPath().getName().compareTo(b.getPath().getName())); // 逐个读取文件并写入目标文件 for (FileStatus status : fileStatuses) { try (FSDataInputStream inStream = hdfs.open(status.getPath())) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inStream.read(buffer)) != -1) { outStream.write(buffer, 0, bytesRead); } } } } hdfs.close(); System.out.println("HDFS文件合并完成!"); } }
把这段代码编译打包成Jar,然后用hadoop jar命令运行即可,全程在HDFS内部操作。
方案3:巧用
hdfs dfs -appendToFile直接合并 你之前可能误解了appendToFile的用法——它其实支持HDFS到HDFS的操作!只要把源文件路径(支持通配符)和目标文件路径都设为HDFS路径就行:
# 把MapReduce输出的所有part文件追加到目标文件 hdfs dfs -appendToFile /user/your-name/mr-output-dir/part-* /user/your-name/merged-result.txt
⚠️ 注意:这个方法要求你的HDFS集群开启了追加功能(默认是开启的,若集群配置了dfs.support.append=false则无法使用)。如果目标文件已经存在,新内容会追加到文件末尾;如果不存在,会自动创建。
内容的提问来源于stack exchange,提问作者Pavan Sai Aravala
相关产品推荐
相关产品推荐

