一个适合MapReduce处理的gz压缩方式

最近在筹备hadoop,测试集群只有普通的6个虚拟机,每个1G内存,100G硬盘。所以在yarn进行资源调度的时候比较纠结,硬盘空间也有限。在执行作业的时候就希望能够尽量对输入数据进行压缩。


hadoop可以直接处理gz格式的压缩文件,但不会产生split,而是不论多大都直接交给一个Mapper去做,因为gz在算法上不支持split。虽然bzip2支持split,但压缩速度又比较慢,gz可以说是最常用的压缩方式了。


一开始想当然的尝试压缩分卷,结果当然是失败,因为不管分多少个卷,gz还是要以一个整体来进行解压。


因为我只是处理文本数据,而且都是基于文本行,每一行之间不像xml那样会具有什么嵌套关系,所以动手写了一个压缩程序,在对大文件进行压缩的时候,如果产生的压缩文件大于一个设定值,那就再新建一个文件继续压缩。


package util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream;

public class CompressUtils
{
/**
* 将文件压缩成GZIP分片
* @param inputFile 输入文件
* @param outputDir 输出目录
* @param outputFileName 输出文件名
* @param splitSize 分片大小
*/
public static void compressToSplitsUseGZIP(File inputFile, File outputDir, String outputFileName, int splitSize)
throws Exception
{
String separator = System.getProperty("line.separator");
int split = 0;
long limit = splitSize * 1024 * 1024L;
File outputSplit = new File(outputDir, outputFileName + split + ".gz");
outputSplit.createNewFile();
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), "UTF-8"));
PrintWriter out = new PrintWriter(new GZIPOutputStream(new FileOutputStream(outputSplit)), false);
String line = null;
long fileLength = outputSplit.length();
long maxInc = 0L;
while (true)
{
line = br.readLine();
if (line == null)
{
break;
}

if (fileLength + maxInc > limit)
{
if (out != null)
{
out.close();
out = null;
outputSplit = new File(outputDir, outputFileName + (++split) + ".gz");
outputSplit.createNewFile();
fileLength = outputSplit.length();
out = new PrintWriter(new GZIPOutputStream(
new FileOutputStream(outputSplit)), false);
}
}

for (byte b : line.getBytes())
{
out.write(b);
}
for (byte b : separator.getBytes())
{
out.write(b);
}
out.flush();

long currentLength = outputSplit.length();
long inc = currentLength - fileLength;
if (inc >= maxInc)
{
maxInc = inc;
}
fileLength = currentLength;
}
br.close();
try
{
out.close();
}
catch (Exception e)
{
}
}

public static void main(String[] args)
throws Exception
{
File inputFile = new File(args[0]);
File outputDir = new File(args[1]);
String outputFileName = args[2];
int splitSize = Integer.parseInt(args[3]);
compressToSplitsUseGZIP(inputFile, outputDir, outputFileName, splitSize);
}
}


命令行参数:D:\temp\test.txt D:\temp test 64

这样产生的压缩文件每一个都会小于64MB,最多相差不到100k。考虑的因素比较少,这里只是把大致的算法写了一下,倒是满足需求了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值