HDFS压缩和解压缩的实例

压缩操作

这里用bz2的方式进行压缩,bz2压缩方式是可切分的
可切分:对应的压缩算法是否可以搜索数据流的任意位置并进一步往下读取数据。

package cn.codec;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
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.util.ReflectionUtils;


public class Codecbz2Test {
	public static void main(String[] args)throws Exception {

                //首先我们需要导入bz2压缩算法的具体类,这里是为了下面用反射机制获取类对象做铺垫

		String CodecClass = "org.apache.hadoop.io.compress.BZip2Codec";

                //这里是你需要压缩的文件路径,我这里是在家目录下的sogou500w文件

		String localPath = "/home/abc/sogou500w";

                //这里是你压缩过后上传到hdfs上的路径,这里要注意一下,由于我们压缩文件过后文件的名字发生改变(多了后缀名)因此我们要写压缩过后的文件名,也就是加上.bz2的文件名(这里我重命名了一下,将sogou500w重命名为sogou500w2)

		String hdfsPath= "hdfs://master:9000/sogou500w2.bz2";

                 //利用反射机制通过类名获取类对象

		Class
  codecClass = Class.forName(CodecClass);

                //获取配置文件对象,并将它加载到内存中

		Configuration conf = new Configuration();

                //重点来了。我们通过Hadoop提供的ReflectionUtils工具类中的newInstance来获取指定的压缩格式类。这里返回的是该类的泛型,因此需要强转一下。

		CompressionCodec codec = (CompressionCodec)ReflectionUtils.newInstance(codecClass, conf);

                //创建一个文件系统(HDFS文件系统)对象

		FileSystem fs = FileSystem.get(URI.create(hdfsPath), conf);

                //打开一个输入流,将我们要压缩的文件“放”到输入流中

		InputStream in = new BufferedInputStream(new FileInputStream(localPath));

                //打开输出流,将我们要输出的文件路径对象放入输出流中

		OutputStream out = fs.create(new Path(hdfsPath)); 

                //将输出流加工一下,转换为“压缩过后”的输出流

		CompressionOutputStream cout = codec.createOutputStream(out);

                //利用hadoop提供的工具类将文件写入hdfs中

		IOUtils.copyBytes(in, cout, 1024, true);

                //打印结果

		System.out.println("complete!!!!!!!");
		
	}


}

解压缩操作

解压缩可以根据压缩文件的后缀来自动检测压缩类型(很智能 ?/滑稽脸)

package cn.codec;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
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.CompressionCodecFactory;


public class CodecInputStreamtest {
	public static void main(String[] args) {
		//这里我们用传入的第一个参数作为我们要解压缩的文件地址的uri
		String uri = args[0];

                //获取配置文件对象,并加载到内存中

		Configuration conf = new Configuration();

                //这里我们将输入流和输出流定义出来方便下面使用

		InputStream in = null;
		OutputStream out = null;
		try{

                //获取文件系统对象

		FileSystem fs = FileSystem.get(URI.create(uri), conf);   

                //将uri封装成hadoop的Path对象

		Path inpath = new Path(uri);

                //获取一个压缩格式的工厂类,为下面做铺垫

		CompressionCodecFactory factory = new CompressionCodecFactory(conf);

                //调用工厂类的getCodec方法,这时就得到了压缩格式的对象(这里就是智能匹配压缩格式的关键)

		CompressionCodec codec = factory.getCodec(inpath);

                //这里的意思是调用工厂的removeSuffix方法将文件后缀名去除第二个参数就是文件的后缀名。这里其实是文件解压过后的地址,大家想一想,文件压缩前都是带着后缀名,将文件解压过后文件的后缀就消失了,这里就相当于文件解压后的地址

		String outputuri = CompressionCodecFactory.removeSuffix(uri, codec.getDefaultExtension());
		//创建一个输入流
		in = codec.createInputStream(fs.open(inpath));

                //创建一个输出流

		out = fs.create(new Path(outputuri));

                //将文件写入hdfs中

		IOUtils.copyBytes(in, out, 1024, false);
		}catch(Exception e){
			e.printStackTrace();
		}finally{

                        //关闭流

			IOUtils.closeStream(in);
			IOUtils.closeStream(out);
		}
				
	}


}
Leave A Comment