Hadoop小文件合并
1、背景
在实际项目中,输入数据往往是由许多小文件组成,这里的小文件是指小于HDFS系统Block大小的文件(默认128M), 然而每一个存储在HDFS中的文件、目录和块都映射为一个对象,存储在NameNode服务器内存中,通常占用150个字节。 如果有1千万个文件,就需要消耗大约3G的内存空间。如果是10亿个文件呢,简直不可想象。所以在项目开始前, 我们选择一种适合的方案来解决本项目的小文件问题
2、介绍
本地 D:\data目录下有 2012-09-17 至 2012-09-23 一共7天的数据集,我们需要将这7天的数据集按日期合并为7个大文件上传至 HDFS
3、数据
本地 D:\data目录下的所有数据,如下图所示:
4、分析
基于项目的需求,我们通过下面几个步骤完成
1、获取 D:\data目录下的所有日期路径,循环所有日期路径,通过globStatus()方法获取所有txt格式文件路径。
2、最后通过IOUtils.copyBytes(in, out, 4096, false)方法将数据集合并为大文件,并上传至 HDFS
5、实现
自定义RegexAcceptPathFilter类实现 PathFilter,比如只接受D:\data\2012-09-17日期目录下txt格式的文件
-
/**
-
* @ProjectName FileMerge
-
* @PackageName com.buaa
-
* @ClassName RegexAcceptPathFilter
-
* @Description 接受 regex 格式的文件
-
* @Date 2016-04-18 21:58:07
-
*/
-
public static class RegexAcceptPathFilter implements PathFilter {
-
private final String regex;
-
-
public RegexAcceptPathFilter(String regex) {
-
this.regex = regex;
-
}
-
-
-
public boolean accept(Path path) {
-
boolean flag = path.toString().matches(regex);
-
return flag;
-
}
-
}
实现主程序 merge 方法,完成数据集的合并,并上传至 HDFS
-
/**
-
* 合并
-
*
-
* @param srcPath 源目录
-
* @param destPath 目标目录
-
*/
-
public static void merge(String srcPath,String destPath) {
-
try{
-
// 读取hadoop文件系统的配置
-
Configuration conf = new Configuration();
-
-
// 获取远端文件系统
-
URI uri = new URI(HDFSUri);
-
FileSystem remote = FileSystem.get(uri, conf);
-
-
// 获得本地文件系统
-
FileSystem local = FileSystem.getLocal(conf);
-
-
// 获取data目录下的所有文件路径
-
Path[] dirs = FileUtil.stat2Paths(local.globStatus(new Path(srcPath)));
-
-
FSDataOutputStream out = null;
-
FSDataInputStream in = null;
-
-
for (Path dir : dirs) {
-
// 文件名称
-
String fileName = dir.getName().replace("-", "");
-
// 只接受目录下的.txt文件
-
FileStatus[] localStatus = local.globStatus(new Path(dir + "/*"), new RegexAcceptPathFilter("^.*.txt$"));
-
// 获得目录下的所有文件
-
Path[] listedPaths = FileUtil.stat2Paths(localStatus);
-
// 输出路径
-
Path block = new Path(destPath + "/" + fileName + ".txt");
-
// 打开输出流
-
out = remote.create(block);
-
for (Path p : listedPaths) {
-
// 打开输入流
-
in = local.open(p);
-
// 复制数据
-
IOUtils.copyBytes(in, out, 4096, false);
-
// 关闭输入流
-
in.close();
-
}
-
if (out != null) {
-
// 关闭输出流
-
out.close();
-
}
-
}
-
}catch(Exception e){
-
logger.error("", e);
-
}
-
}
6、一些运行代码
-
/**
-
* main方法
-
*
-
* @param args
-
*/
-
public static void main(String[] args) {
-
merge("D:\\data\\*","/buaa");
-
}
7、结果
转自:https://blog.csdn.net/lzxyzq/article/details/51317671
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南