背景: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里的更多相关文章

  1. 第3节 mapreduce高级:5、6、通过inputformat实现小文件合并成为sequenceFile格式

    1.1 需求 无论hdfs还是mapreduce,对于小文件都有损效率,实践中,又难免面临处理大量小文件的场景,此时,就需要有相应解决方案 1.2 分析 小文件的优化无非以下几种方式: 1.  在数据 ...

  2. Hadoop MapReduce编程 API入门系列之小文件合并(二十九)

    不多说,直接上代码. Hadoop 自身提供了几种机制来解决相关的问题,包括HAR,SequeueFile和CombineFileInputFormat. Hadoop 自身提供的几种小文件合并机制 ...

  3. HDFS操作及小文件合并

    小文件合并是针对文件上传到HDFS之前 这些文件夹里面都是小文件 参考代码 package com.gong.hadoop2; import java.io.IOException; import j ...

  4. Hadoop经典案例(排序&Join&topk&小文件合并)

    ①自定义按某列排序,二次排序 writablecomparable中的compareto方法 ②topk a利用treemap,缺点:map中的key不允许重复:https://blog.csdn.n ...

  5. hive小文件合并设置参数

    Hive的后端存储是HDFS,它对大文件的处理是非常高效的,如果合理配置文件系统的块大小,NameNode可以支持很大的数据量.但是在数据仓库中,越是上层的表其汇总程度就越高,数据量也就越小.而且这些 ...

  6. hive优化之小文件合并

    文件数目过多,会给HDFS带来压力,并且会影响处理效率,可以通过合并Map和Reduce的结果文件来消除这样的影响: set hive.merge.mapfiles = true ##在 map on ...

  7. MR案例:小文件合并SequeceFile

    SequeceFile是Hadoop API提供的一种二进制文件支持.这种二进制文件直接将<key, value>对序列化到文件中.可以使用这种文件对小文件合并,即将文件名作为key,文件 ...

  8. Hive merge(小文件合并)

    当Hive的输入由非常多个小文件组成时.假设不涉及文件合并的话.那么每一个小文件都会启动一个map task. 假设文件过小.以至于map任务启动和初始化的时间大于逻辑处理的时间,会造成资源浪费.甚至 ...

  9. hadoop(十)hdfs上传删除文件(完全分布式七)|12

    集群测试 上传小文件到集群,随便选择一个小文件上传到hdfs的根目录 [shaozhiqi@hadoop102 hadoop-3.1.2]$ bin/hdfs dfs -put wcinput/wc. ...

随机推荐

  1. leetcode笔记--7 Find the Difference

    question: Given two strings s and t which consist of only lowercase letters. String t is generated b ...

  2. Qt-Qml-播放视频-失败版-只有声音没有图像

    失败版代码 import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import QtMultimedia ...

  3. Linux命令应用大词典-第12章 程序编译

    12.1 gcc:GNU项目的C和C++编译器 12.2 gdberver:为GNU调试的远程服务器 12.3 cmake:跨平台的Makefile生成工具 12.4 indent:更改通过插入或删除 ...

  4. Angualr6访问API

    参照 草根专栏- ASP.NET Core + Ng6 实战: https://v.qq.com/x/page/a0769armuui.html 1.environment.ts 添加apiUrlBa ...

  5. Redis命令续

     Redis 集合命令 下表列出了 Redis 集合基本命令: 序号 命令及描述 1 SADD key member1 [member2] 向集合添加一个或多个成员 2 SCARD key 获取集合的 ...

  6. 通过流的方式操作hadoop的API

    通过流的方式操作hadoop的API 功能: 可以直接用来操作hadoop的文件系统 可以用在mapreduce的outputformat中设置RecordWrite 参考: 概念理解 http:// ...

  7. MyBatis中文文档

    http://mybatis.github.io/mybatis-3/zh/index.html

  8. 转:Linux 编译安装 Mysql5.7

    http://broqiang.com/2017/04/18/Mysql-Install-5.7.18-Linux-Compile/ 原文 Linux 编译安装 Mysql5.7 Ubuntu 下快速 ...

  9. Graph Theory

    Description Little Q loves playing with different kinds of graphs very much. One day he thought abou ...

  10. Java 集合框架之Collection

    此图是 java 中 Collection 相关的接口与类的关系的类图.其中,类只是集合框架的一部分,比较常用的一部分. 第一次画类图,着实很费劲,不过收获也不小. 下面是相关接口和类的解释说明.文字 ...