1. 压缩从头说
一般来说,数据存在冗余度。数据包括图像文本视频音频。减少数据的冗余度,让数据的体积更小一点,这叫压缩。从压缩后的数据,重新解析出原始数据,叫解压缩。
压缩无处不在。压缩的算法非常多。
对Hadoop来说,有两个地方需要用到压缩:其一,在HDFS上存储数据文件,压缩之后数据体积更小,有利存储;其二,集群间的通讯需要压缩数据,这样可以提高网络带宽的利用率。如果用MapReduce处理压缩文件,那么要求压缩算法能支持文件分割,因为MapReduce的过程需要将文件分割成多个切片,如果压缩算法不支持分割,就不能做切片了。
在Java里,一切输入输出都用流的方式进行。一个可以读取字节序列的对象叫输入流。文件,网络连接,内存区域,都可以是输入流。一个可以写入字节序列的对象叫输出流。文件,网络连接,内存区域,都可以是输出流。
Hadoop如何压缩?假设,输入流是A,输出流是B。A和B有很多种可能,可以是文件,网络连接,内存区域,标准输入,标准输出的两两组合。做压缩的话,先选择压缩算法,然后根据压缩算法创建相应的压缩器,然后用压缩器和输出流B创建压缩输出流C,最后,将数据从输入流A复制到压缩输出流C即可进行压缩并输出结果。
如果是解压缩,先选择解压缩算法,然后根据解压缩算法创建相应的解压缩器,然后用解压缩器和输入流A创建压缩输入流C,最后,将数据从输入流C复制到输出流B即可进行解压缩并输出结果。
2.从文件到文件的压缩
2.1 文件和目录结构
这个程序将HDFS上的一个文本文件压缩到另外一个文件。
创建目录~/cprsf2f存放源代码、编译和打包结果。在cprsf2f目录下,有两个子目录,分别是src目录和classes目录,src目录存放Java源代码,class存放编译结果。在src目录下,只有一个源代码文件CprsF2F.java。
2.2 CprsF2F.java源文件的代码
-
packagecom.brianchen.hadoop;
importjava.net.URI;
importjava.io.InputStream;
importjava.io.OutputStream;
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.io.compress.CompressionCodec;
importorg.apache.hadoop.io.IOUtils;
importorg.apache.hadoop.fs.Path;
importorg.apache.hadoop.fs.FileSystem;
importorg.apache.hadoop.util.ReflectionUtils;
public classCprsF2F{
public staticvoid main(String[] args) throws Exception{
if(args.length != 3){
System.err.println("Usage:CprsF2F cmps_name src target");
System.exit(2);
}
Class<?>codecClass = Class.forName(args[0]);
Configurationconf = new Configuration();
CompressionCodeccodec = (CompressionCodec)ReflectionUtils.newInstance(codecClass,conf);
InputStreamin = null;
OutputStreamout = null;
FileSystem fs= FileSystem.get(URI.create(args[1]), conf);
try{
in =fs.open(new Path(args[1]));
out =codec.createOutputStream(fs.create(new Path(args[2])));
IOUtils.copyBytes(in,out, conf);
}finally{
IOUtils.closeStream(in);
IOUtils.closeStream(out);
}
}
}
2.3 编译
“cd~/cprsf2f”
“jvac-cp /home/brian/usr/hadoop/hadoop-1.2.1/hadoop-core-1.2.1.jar -d./class/ src/*.java”
2.4 打包
“jar-cvf cprsf2f.jar -C ./class/ .”
2.5 执行
“cd~/usr/hadoop/hadoop-1.2.1”
“echo"hellowrod" >> a.txt”
“./bin/hadoopfs -put a.txt a.txt”
“./bin/hadoopjar /home/brian/cprsf2f/cprsf2f.jar com.brianchen.hadoop.CprsF2Forg.apache.hadoop.io.compress.GzipCodec a.txt b.txt”
“./bin/hadoopfs -cat b.txt”
“./bin/hadoopfs -cat b.txt|gunzip”
首先需要确认Hadoop已经启动。用echo命令创建一个内容是”helloworld”的文件a.txt。将a.txt文件复制到HDFS。执行jar,将文件a.txt压缩成b.txt。压缩完毕之后,执行cat,检查b.txt内容,这时候显示的是乱码,因为原始内容已经被压缩了。然后再执行“./bin/hadoopfs -cat b.txt | gunzip”,这次会显示出”helloworld”,因为管道命令gunzip会将压缩文件的内容进行解压缩然后输出。
3.从标准输入到文件的压缩
3.1 文件和目录结构
这个程序从标准输入读取字符串,然后讲它压缩到HDFS的文件存储。创建目录~/cprsin2f存放源代码、编译和打包结果。在cprsin2f目录下,有两个子目录,分别是src目录和classes目录,src目录存放Java源代码,class存放编译结果。在src目录下,只有一个源代码文件CprsIn2F.java。
3.2 CprsIn2F.java源文件的代码
-
packagecom.brianchen.hadoop;
importjava.net.URI;
importjava.io.OutputStream;
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.io.compress.CompressionCodec;
importorg.apache.hadoop.io.IOUtils;
importorg.apache.hadoop.fs.Path;
importorg.apache.hadoop.fs.FileSystem;
importorg.apache.hadoop.util.ReflectionUtils;
public classCprsIn2F{
public staticvoid main(String[] args) throws Exception{
if(args.length != 2){
System.err.println("Usage:CprsIn2F cmps_name target");
System.exit(2);
}
Class<?>codecClass = Class.forName(args[0]);
Configurationconf = new Configuration();
CompressionCodeccodec = (CompressionCodec)ReflectionUtils.newInstance(codecClass,conf);
OutputStreamout = null;
FileSystem fs= FileSystem.get(URI.create(args[1]), conf);
try{
out =codec.createOutputStream(fs.create(new Path(args[1])));
IOUtils.copyBytes(System.in,out, 4096, false);
}finally{
IOUtils.closeStream(out);
}
}
}
3.3 编译
“cd~/cprsin2f”
“jvac-cp /home/brian/usr/hadoop/hadoop-1.2.1/hadoop-core-1.2.1.jar -d./class/ src/*.java”
3.4 打包
“jar-cvf cprsf2f.jar -C ./class/ .”
3.5 执行
“cd~/usr/hadoop/hadoop-1.2.1”
“echo“hello, world!” | ./bin/hadoop jar/home/brian/cprsf2f/cprsf2f.jar com.brianchen.hadoop.CprsF2Forg.apache.hadoop.io.compress.GzipCodec hello.txt”
“./bin/hadoopfs -cat hello.txt”
“./bin/hadoopfs -cat hello.txt|gunzip”
首先需要确认Hadoop已经启动。注意,第二行的命令的双引号需要写上去,这是表示输出字符串。用echo命令将”helloworld”输出到标准输入,然后用管道的方式执行jar,将标准输入的字符串压缩到HDFS的hello.txt。“org.apache.hadoop.io.compress.GzipCodec”,这个是Hadoop的Gzip压缩器类的类名。压缩完毕之后,执行cat,检查hello.txt内容,这时候显示的是乱码,因为原始内容已经被压缩了。然后再执行“./bin/hadoopfs -cat hello.txt | gunzip”,这次会显示出”hello,world!”,因为管道命令gunzip会将压缩文件的内容进行解压缩然后输出。
4从文件到文件的解压缩
4.1 文件和目录结构
这个程序把压缩文件压解缩到另外一个文件。创建目录~/dcprsf2f存放源代码、编译和打包结果。在dcprsf2f目录下,有两个子目录,分别是src目录和classes目录,src目录存放Java源代码,class存放编译结果。在src目录下,只有一个源代码文件DcprsF2F.java。
4.2 DcprsF2F.java源文件的代码
-
packagecom.brianchen.hadoop;
importjava.net.URI;
importjava.io.InputStream;
importjava.io.OutputStream;
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.io.compress.CompressionCodec;
importorg.apache.hadoop.io.IOUtils;
importorg.apache.hadoop.fs.Path;
importorg.apache.hadoop.fs.FileSystem;
importorg.apache.hadoop.util.ReflectionUtils;
public classDcprsF2F{
public staticvoid main(String[] args) throws Exception{
if(args.length != 3){
System.err.println("Usage:CprsF2F cmps_name src target");
System.exit(2);
}
Class<?>codecClass = Class.forName(args[0]);
Configurationconf = new Configuration();
CompressionCodeccodec = (CompressionCodec)ReflectionUtils.newInstance(codecClass,conf);
InputStreamin = null;
OutputStreamout = null;
FileSystem fs= FileSystem.get(URI.create(args[1]), conf);
try{
in =codec.createInputStream(fs.open(new Path(args[1])),codec.createDecompressor());
out =fs.create(new Path(args[2]));
IOUtils.copyBytes(in,out, conf);
}finally{
IOUtils.closeStream(in);
IOUtils.closeStream(out);
}
}
}
4.3 编译
“cd~/dcprsf2f”
“jvac-cp /home/brian/usr/hadoop/hadoop-1.2.1/hadoop-core-1.2.1.jar -d./class/ src/*.java”
4.4 打包
“jar-cvf dcprsf2f.jar -C ./class/ .”
4.5 执行
“cd~/usr/hadoop/hadoop-1.2.1”
“./bin/hadoopjar /home/brian/cprsf2f/cprsf2f.jar com.brianchen.hadoop.DcprsF2Forg.apache.hadoop.io.compress.GzipCodec hello.txt hello_dec.txt”
“./bin/hadoopfs -cat hello.txt”
“./bin/hadoopfs -cat hello_dec.txt”
首先需要确认Hadoop已经启动。压缩文件hello.txt是5.3节创建的,在这里直接使用。将压缩文件hello.txt解压缩到文件hello_c.txt。“org.apache.hadoop.io.compress.GzipCodec”,这个是Hadoop的Gzip压缩器类的类名。压缩完毕之后,执行cat,检查hello.txt内容,这时候显示的是乱码。然后再执行“./bin/hadoopfs -cat hello_dec.txt”,这次会显示出”hello,world!”。