hadoop 将HDFS上多个小文件合并到SequenceFile里
背景:hdfs上的文件最好和hdfs的块大小的N倍。如果文件太小,浪费namnode的元数据存储空间以及内存,如果文件分块不合理也会影响mapreduce中map的效率。
本例中将小文件的文件名作为key,其内容作为value生成SequenceFile
1、生成文件
//将目标目录的所有文件以文件名为key,内容为value放入SequenceFile中
//第一个参数是需要打包的目录,第二个参数生成的文件路径和名称
private static void combineToSequenceFile(String[] args) throws IOException {
String sourceDir = args[0];
String destFile = args[1]; List<String> files = getFiles(sourceDir); Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path destPath = new Path(destFile);
if (fs.exists(destPath)) {
fs.delete(destPath, true);
} FSDataInputStream in = null; Text key = new Text();
BytesWritable value = new BytesWritable(); byte[] buff = new byte[4096];
SequenceFile.Writer writer = null; SequenceFile.Writer.Option option1 = SequenceFile.Writer.file(new Path(destFile));
SequenceFile.Writer.Option option2 = SequenceFile.Writer.keyClass(key.getClass());
SequenceFile.Writer.Option option3 = SequenceFile.Writer.valueClass(value.getClass());
SequenceFile.Writer.Option option4 = SequenceFile.Writer.compression(SequenceFile.CompressionType.RECORD);
try {
writer = SequenceFile.createWriter(conf, option1, option2, option3, option4);
for (int i = 0; i < files.size(); i++) {
Path path = new Path(files.get(i).toString());
System.out.println("读取文件:" + path.toString());
key = new Text(files.get(i).toString());
in = fs.open(path);
// 只能处理小文件,int最大只能表示到1个G的大小,实际上大文件放入SequenceFile也没有意义
int length = (int) fs.getFileStatus(path).getLen();
byte[] bytes = new byte[length];
// read最多只能读取65536的大小
int readLength = in.read(buff);
int offset = 0;
while (readLength > 0) {
System.arraycopy(buff, 0, bytes, offset, readLength);
offset += readLength;
readLength = in.read(buff);
}
System.out.println("file length:" + length + ",read length:" + offset);
value = new BytesWritable(bytes);
System.out.printf("[%s]\t%s\t%s\n", writer.getLength(), key, value.getLength());
writer.append(key, value);
}
} finally {
IOUtils.closeStream(in);
IOUtils.closeStream(writer);
IOUtils.closeStream(fs);
} }
查找文件:
private static List<String> getFiles(String dir) throws IOException {
Configuration conf = new Configuration();
Path path = new Path(dir);
FileSystem fs = null;
List<String> filelist = new ArrayList<>();
try {
fs = FileSystem.get(conf);
//对单个文件或目录下所有文件和目录
FileStatus[] fileStatuses = fs.listStatus(path);
for (FileStatus fileStatus : fileStatuses) {
//递归查找子目录
if (fileStatus.isDirectory()) {
filelist.addAll(getFiles(fileStatus.getPath().toString()));
} else {
filelist.add(fileStatus.getPath().toString());
}
}
return filelist;
} finally {
IOUtils.closeStream(fs);
}
}
2、还原压缩的SequenceFile文件
//将combineToSequenceFile生成的文件分解成原文件。
private static void extractCombineSequenceFile(String[] args) throws IOException {
String sourceFile = args[0];
// String destdir = args[1];
Configuration conf = new Configuration();
Path sourcePath = new Path(sourceFile); SequenceFile.Reader reader = null;
SequenceFile.Reader.Option option1 = SequenceFile.Reader.file(sourcePath); Writable key = null;
Writable value = null;
// Text key = null;
// BytesWritable value = null; FileSystem fs = FileSystem.get(conf);
try {
reader = new SequenceFile.Reader(conf, option1);
key = (Writable) ReflectionUtils.newInstance(reader.getKeyClass(), conf);
value = (Writable) ReflectionUtils.newInstance(reader.getValueClass(), conf); //在知道key和value的明确类型的情况下,可以直接用其类型
// key = ReflectionUtils.newInstance(Text.class, conf);
// value = ReflectionUtils.newInstance(BytesWritable.class, conf);
long position = reader.getPosition();
while (reader.next(key, value)) {
FSDataOutputStream out = fs.create(new Path(key.toString()), true);
//文件头会多出4个字节,用来标识长度,而本例中原文件头是没有长度的,所以不能用这个方式写入流
// value.write(out);
out.write(((BytesWritable)value).getBytes(),0,((BytesWritable)value).getLength()); // out.write(value.getBytes(),0,value.getLength());
System.out.printf("[%s]\t%s\t%s\n", position, key, out.getPos());
out.close();
position = reader.getPosition();
}
} finally {
IOUtils.closeStream(reader);
IOUtils.closeStream(fs);
}
}
hadoop 将HDFS上多个小文件合并到SequenceFile里的更多相关文章
- 第3节 mapreduce高级:5、6、通过inputformat实现小文件合并成为sequenceFile格式
1.1 需求 无论hdfs还是mapreduce,对于小文件都有损效率,实践中,又难免面临处理大量小文件的场景,此时,就需要有相应解决方案 1.2 分析 小文件的优化无非以下几种方式: 1. 在数据 ...
- Hadoop MapReduce编程 API入门系列之小文件合并(二十九)
不多说,直接上代码. Hadoop 自身提供了几种机制来解决相关的问题,包括HAR,SequeueFile和CombineFileInputFormat. Hadoop 自身提供的几种小文件合并机制 ...
- HDFS操作及小文件合并
小文件合并是针对文件上传到HDFS之前 这些文件夹里面都是小文件 参考代码 package com.gong.hadoop2; import java.io.IOException; import j ...
- Hadoop经典案例(排序&Join&topk&小文件合并)
①自定义按某列排序,二次排序 writablecomparable中的compareto方法 ②topk a利用treemap,缺点:map中的key不允许重复:https://blog.csdn.n ...
- hive小文件合并设置参数
Hive的后端存储是HDFS,它对大文件的处理是非常高效的,如果合理配置文件系统的块大小,NameNode可以支持很大的数据量.但是在数据仓库中,越是上层的表其汇总程度就越高,数据量也就越小.而且这些 ...
- hive优化之小文件合并
文件数目过多,会给HDFS带来压力,并且会影响处理效率,可以通过合并Map和Reduce的结果文件来消除这样的影响: set hive.merge.mapfiles = true ##在 map on ...
- MR案例:小文件合并SequeceFile
SequeceFile是Hadoop API提供的一种二进制文件支持.这种二进制文件直接将<key, value>对序列化到文件中.可以使用这种文件对小文件合并,即将文件名作为key,文件 ...
- Hive merge(小文件合并)
当Hive的输入由非常多个小文件组成时.假设不涉及文件合并的话.那么每一个小文件都会启动一个map task. 假设文件过小.以至于map任务启动和初始化的时间大于逻辑处理的时间,会造成资源浪费.甚至 ...
- hadoop(十)hdfs上传删除文件(完全分布式七)|12
集群测试 上传小文件到集群,随便选择一个小文件上传到hdfs的根目录 [shaozhiqi@hadoop102 hadoop-3.1.2]$ bin/hdfs dfs -put wcinput/wc. ...
随机推荐
- DSP5509的GPIO学习-第5篇
1. 使用CCS V6.1版本,目前已经不局限于仅仅把实验搞清楚了,要深入去探究内部的原理,本章看下GPIO实验 2. 在CCS启动的时候,提示,这个问题是什么,XDAIS是什么?XDAIS (eXp ...
- NPOI List数据源 导出excel
List数据源生成HSSFWorkbook通用方法: public class WorkBook { public static HSSFWorkbook BuildSwitchData<T&g ...
- VS Help Viewer 显示内容为HTML源码的问题
万恶的IE10 为了学习,安装了一套Windows Server 2012+SQL 2012+VS 2012的环境,整体感觉还不错,只是在使用Help Viewer查看帮助的时候,发现显示内容居然为H ...
- PS 旋转任意角度的照片
1.选择标尺工具 2.在图片上画一个线,然后工具栏--图像--图像旋转
- Linux命令应用大词典-第9章 数字计算
9.1 bc:任意精度的计算器 9.2 dc:一个任意精度的计算器 9.3 expr:将表达式的值打印到标准输出 9.1 bc:任意精度的计算器 9.2 dc:一个任意精度的计算器 9.3 expr: ...
- 初学DirectX(1)
初学Direct X (1) Direct3D设备用于访问视频卡的帧缓冲区,以及后台缓冲区.由于IDE是vs2013,默认安装了direct 9,只需要在使用头文件(1)并像使用库文件(2)即可 #i ...
- python中为什么 if/while/def/class语句需要冒号?
python中冒号主要用于增强可读性(ABC语言实验的结果之一).考虑一下这个: if a == b print(a) 与 if a == b: print(a) 注意第二种方法稍微容易一些.请进一步 ...
- Java 集合学习--HashMap
一.HashMap 定义 HashMap 是一个基于散列表(哈希表)实现的键值对集合,每个元素都是key-value对,jdk1.8后,底层数据结构涉及到了数组.链表以及红黑树.目的进一步的优化Has ...
- MySql优化浅析
优化点:合理的使用索引,可以大幅度提升sql查询效率,特别查询的表的数据量大的时候,效果明显.一.引言 公司的产品XX出行上线正式运营,随着数据量的变大,司机2000+,日订单1万+,注册乘客26W+ ...
- IMPI Python集群运行报错:
Intel MPI环境利用hostfile多主机运行下报错 HYDU_process_mfile_token (../../utils/args/args.c:523): token slots no ...