文件压缩可以降低存储需要的空间,并且在传输过程中加快传输速度。因此对于大量数据的处理时,压缩是十分重要的。我们考虑一下Hadoop在文件中的压缩用法。
有许多压缩方式,如下:
压缩格式 | 工具 | 算法 | 文件拓展名 | 是否可切分 |
---|---|---|---|---|
DEFLATE | 无 | DEFLATE | .deflate | 否 |
Gzip | gzip | DEFLATE | .gz | 否 |
bzip2 | bzip2 | bzip2 | bz2 | 是 |
LZO | lzop | LZO | .lzo | 否 |
LZ4 | 无 | LZ4 | .lz4 | 否 |
Snappy | 无 | Snappy | .snappy | 否 |
压缩主要考虑时间和速度,在上面的三种压缩工具中都提供了对压缩时间和压缩空间的调整参数。-1是为优化压缩速度,-9是优化压缩空间,1~9中间其他的参数介于二者之间。
另外不同的压缩有着不同的特性,
- bzip2压缩能力强,但压缩时间慢。他的解压较快
- gzip压缩能力和压缩时间介于bzip2和lzop之间
因此不同的情况有着不同的使用。
1. 使用CompressionCodec接口实现压缩和解压缩
在Hadoop中CompressionCodec接口定义了压缩和解压缩的方法。其包含许多具体的实现。
实现如下:
压缩格式 | HadoopCompressionCodec |
---|---|
DEFLATE | org.apache.hadoop.io.compress.DeFaultCodec |
gzip | org.apache.hadoop.io.compress.GZipCodec |
bzip2 | org.apache.hadoop.io.compress.BZip2Codec |
LZO | com.hadoop.compression.lzo.LzopCodec |
LZ4 | org.apache.hadoop.io.compress.Lz4Codec |
Snappy | org.apache.hadoop.io.compress.SnappyCodec |
CompressionCodec中包含两个函数用于压缩和解压:
createOutputStream(OutputStream out)
压缩out中的内容,并返回一个CompressionOutputStream对象来包含压缩结果。createInputStream(InputStream in)
解压in中的内容,并返回一个CompressionInputStream对象来包含解压结果。
2. 压缩程序
编写一个压缩程序:
import java.io.IOException;
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.compress.CompressionCodec;
import org.apache.hadoop.io.compress.CompressionOutputStream;
import org.apache.hadoop.io.compress.GzipCodec;
import org.apache.hadoop.util.ReflectionUtils;
public class GZipCodec {
public static void main(String[] args) throws IOException {
String srcUrl = args[0];
String targetUrl = args[1];
Configuration conf = new Configuration();
FileSystem inFs = FileSystem.get(URI.create(srcUrl),conf);
FileSystem outFs = FileSystem.get(URI.create(targetUrl),conf);
CompressionCodec codec = ReflectionUtils.newInstance(GzipCodec.class,conf);
FSDataInputStream inputStream = inFs.open(new Path(srcUrl));
CompressionOutputStream outputStream = codec.createOutputStream(outFs.create(new Path(targetUrl)));
IOUtils.copyBytes(inputStream, outputStream, 4096,false);
outputStream.finish();
IOUtils.closeStream(outputStream);
IOUtils.closeStream(inputStream);
System.out.println("输入文件的大小"+inFs.getFileStatus(new Path(srcUrl)).getLen()+"b");
System.out.println("输出文件的大小"+outFs.getFileStatus(new Path(targetUrl)).getLen()+"b");
System.out.printf("压缩率为%.2f%%\n",100*(1.0*outFs.getFileStatus(new