Hadoop: the definitive guide 第三版 拾遗 第四章 之CompressionCodec

来源:互联网 发布:淘宝售假会怎么样 编辑:程序博客网 时间:2024/05/18 02:39

本文转自:http://blog.csdn.net/hadoop_


第四章中提到了通过CompressionCodec对streams进行压缩和解压缩,并提供了示例程序:

输入:标准输入流

输出:压缩后的标准输出流

原示例程序:

[java] view plaincopy
  1. // cc StreamCompressor A program to compress data read from standard input and write it to standard output  
  2. import org.apache.hadoop.conf.Configuration;  
  3. import org.apache.hadoop.io.IOUtils;  
  4. import org.apache.hadoop.io.compress.CompressionCodec;  
  5. import org.apache.hadoop.io.compress.CompressionOutputStream;  
  6. import org.apache.hadoop.util.ReflectionUtils;  
  7.   
  8. // vv StreamCompressor  
  9. public class StreamCompressor {  
  10.   
  11.   public static void main(String[] args) throws Exception {  
  12.     String codecClassname = args[0];  
  13.     Class<?> codecClass = Class.forName(codecClassname);  
  14.     Configuration conf = new Configuration();  
  15.     CompressionCodec codec = (CompressionCodec)  
  16.       ReflectionUtils.newInstance(codecClass, conf);  
  17.       
  18.     CompressionOutputStream out = codec.createOutputStream(System.out);  
  19.     IOUtils.copyBytes(System.in, out, 4096false);  
  20.     out.finish();  
  21.   }  
  22. }  
  23. // ^^ StreamCompressor  

该实例程序通过CompressionCodec的createOutputStream(OutputStream out)方法获得CompressionOutputStream对象。

第12行因参数固定,可以直接写成String codecClassname="org.apache.hadoop.io.compress.GzipCodec";

即从命令行接受一个CompressionCodec实现类的参数,然后通过ReflectionUtils把实例化这个类,调用CompressionCodec的接口方法对标准输出流进行封装,封装成一个压缩流,通过IOUtils类的copyBytes方法把标准输入流拷贝到压缩流中,最后调用CompressionCodec的finish方法,完成压缩。

在hadoop集群的hadoop根目录下使用如下命令验证该程序(通过linux的gunzip完成解压缩):

[java] view plaincopy
  1. $echo "Hello world" |  hadoop jar xxxx.jar com.tht.hadoopIO.StreamCompressor  org.apache.hadoop.io.compress.GzipCodec | gunzip -  

下面对改程序做进一步修改:

一、更改输出路径:即标准输入流压缩后的存放位置。

输入:标准输入流

输出:压缩后的文件存放到HDFS上

示例代码如下:

[java] view plaincopy
  1. package com.tht.hadoopIO;  
  2.   
  3. import java.net.URI;  
  4.   
  5. import org.apache.hadoop.conf.Configuration;  
  6. import org.apache.hadoop.fs.FileSystem;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.IOUtils;  
  9. import org.apache.hadoop.io.compress.CompressionCodec;  
  10. import org.apache.hadoop.io.compress.CompressionOutputStream;  
  11. import org.apache.hadoop.util.ReflectionUtils;  
  12.   
  13. //vv StreamCompressor  
  14. public class StreamCompressor {  
  15.   
  16.     public static void main(String[] args) throws Exception {  
  17.         String codecClassname = "org.apache.hadoop.io.compress.GzipCodec";  
  18.         String outputUri = "hdfs://master:9000/in/test.gz";  
  19.           
  20.         Class<?> codecClass = Class.forName(codecClassname);  
  21.         Configuration conf = new Configuration();  
  22.         FileSystem fs = FileSystem.get(URI.create(outputUri), conf);  
  23.           
  24.         CompressionCodec codec = (CompressionCodec) ReflectionUtils  
  25.                 .newInstance(codecClass, conf);   
[java] view plaincopy
  1.         CompressionOutputStream out = codec.createOutputStream(fs.create(new Path(outputUri)));  
  2.         IOUtils.copyBytes(System.in, out, 4096false);  
  3.         out.finish();  
  4.     }  
  5. }  
  6. // ^^ StreamCompressor  

当然,在此路径outputUri:,,,/test.gz是指压缩后的文件存放位置和文件名及扩展名,如果改为...../test.txt.gz则指以.txt格式的压缩文件,后缀名是gz。

二、更改输入文件,即将输入文件路径定为HDFS上的文件。

输入:HDFS上存放文件

输出:压缩后的文件存放至HDFS上

示例代码如下:

[java] view plaincopy
  1. import java.io.InputStream;  
  2. import java.net.URI;  
  3.   
  4. import org.apache.hadoop.conf.Configuration;  
  5. import org.apache.hadoop.fs.FileSystem;  
  6. import org.apache.hadoop.fs.Path;  
  7. import org.apache.hadoop.io.IOUtils;  
  8. import org.apache.hadoop.io.compress.CompressionCodec;  
  9. import org.apache.hadoop.io.compress.CompressionOutputStream;  
  10. import org.apache.hadoop.util.ReflectionUtils;  
  11.   
  12. //vv StreamCompressor  
  13. public class StreamCompressor {  
  14.   
  15.     public static void main(String[] args) throws Exception {  
  16.         String codecClassname = "org.apache.hadoop.io.compress.GzipCodec";  
  17.         String uri = "hdfs://master:9000/in/test.txt";  
  18.         String outputUri = "hdfs://master:9000/in/test.txt.gz";  
  19.           
  20.         Class<?> codecClass = Class.forName(codecClassname);  
  21.         Configuration conf = new Configuration();  
  22.         FileSystem fs1 = FileSystem.get(URI.create(uri), conf);  
  23.         FileSystem fs2 = FileSystem.get(URI.create(outputUri), conf);  
  24.           
  25.         CompressionCodec codec = (CompressionCodec) ReflectionUtils  
  26.                 .newInstance(codecClass, conf);  
  27.   
  28.         InputStream in =fs1.open(new Path(uri));      
  29.         CompressionOutputStream out = codec.createOutputStream(fs2.create(new Path(outputUri)));  
  30.           
  31.         IOUtils.copyBytes(in, out, 4096false);  
  32.         in.close();  
  33.         out.close();  
  34.     }  
  35. }  
  36. // ^^ StreamCompressor  

当然了,输入输出都可以以参数形式存在。即String uri = arg[0];String outputUri =arg[1];则在执行时须加入两个路径参数。在windows eclipse下开发时会出现警告:

[java] view plaincopy
  1. 13/08/10 00:03:49 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable  

但是,只要在hadoop集群中配置好了hadoop本地库,在此就没有什么影响,照常压缩。

解压缩:

如果你想读取一个被压缩的文件的话,首先你得先通过扩展名判断该用哪种codec,可以查找压缩对应关系,这样做起来比较麻烦。
hadoop可以通过CompressionCodecFactory.getCodec(Path arg0),传入一个Path即可获得相应得codec,示例代码如下:
[java] view plaincopy
  1. //cc FileDecompressor A program to decompress a compressed file using a codec inferred from the file's extension  
  2. import java.io.InputStream;  
  3. import java.io.OutputStream;  
  4. import java.net.URI;  
  5.   
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.FileSystem;  
  8. import org.apache.hadoop.fs.Path;  
  9. import org.apache.hadoop.io.IOUtils;  
  10. import org.apache.hadoop.io.compress.CompressionCodec;  
  11. import org.apache.hadoop.io.compress.CompressionCodecFactory;  
  12.   
  13. //vv FileDecompressor  
  14. public class FileDecompressor {  
  15.   
  16.     public static void main(String[] args) throws Exception {  
  17. //      String uri = args[0];  
  18.         String uri = "hdfs://master:9000/in/word.txt.gz";  
  19.         Configuration conf = new Configuration();  
  20.         FileSystem fs = FileSystem.get(URI.create(uri), conf);  
  21.   
  22.         Path inputPath = new Path(uri);  
  23.         CompressionCodecFactory factory = new CompressionCodecFactory(conf);  
  24.         CompressionCodec codec = factory.getCodec(inputPath);  
  25.         if (codec == null) {  
  26.             System.err.println("No codec found for " + uri);  
  27.             System.exit(1);  
  28.         }  
  29.   
  30.         String outputUri = CompressionCodecFactory.removeSuffix(uri,  
  31.                 codec.getDefaultExtension());  
  32.   
  33.         InputStream in = null;  
  34.         OutputStream out = null;  
  35.         try {  
  36.             in = codec.createInputStream(fs.open(inputPath));  
  37.             out = fs.create(new Path(outputUri));  
  38.             IOUtils.copyBytes(in, out, conf);  
  39.         } finally {  
  40.             IOUtils.closeStream(in);  
  41.             IOUtils.closeStream(out);  
  42.         }  
  43.     }  
  44. }  
  45. // ^^ FileDecompressor  

报警:

同样的,如果实在window下的eclipse中运行,将会报警(不影响程序正常运行):
[java] view plaincopy
  1. 13/08/10 00:09:37 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable  
  2. 13/08/10 00:09:37 WARN snappy.LoadSnappy: Snappy native library not loaded  
注:hadoop本地库不支持windows系统。
0 0
原创粉丝点击