Hadoop SequenceFile

apache原文:http://hadoop.apache.org/docs/r1.0.4/api/org/apache/hadoop/io/SequenceFile.html


概念:

SequenceFile是一个由二进制序列化过的key/value的字节流组成的文本存储文件,它可以在map/reduce过程中的input/output 的format时被使用。

在map/reduce过程中,map处理文件的临时输出就是使用SequenceFile处理过的。 所以一般的SequenceFile均是在FileSystem中生成,供map调用的原始文件。






在存储结构上,SequenceFile主要由一个Header后跟多条Record组成。


Header主要包含了Key classname,Value classname,存储压缩算法,用户自定义元数据等信息,此外,还包含了一些同步标识,用于快速定位到记录的边界。


每条Record以键值对的方式进行存储,用来表示它的字符数组可依次解析成:记录的长度、Key的长度、Key值和Value值,并且Value值的结构取决于该记录是否被压缩。



数据压缩有利于节省磁盘空间和加快网络传输,SeqeunceFile支持两种格式的数据压缩,分别是:record compression和block compression。


record compression如上图所示,是对每条记录的value进行压缩。


block compression是将一连串的record组织到一起,统一压缩成一个block,如上图。


block信息主要存储了:块所包含的记录数、每条记录Key长度的集合、每条记录Key值的集合、每条记录Value长度的集合和每条记录Value值的集合
注:每个block的大小是可通过io.seqfile.compress.blocksize属性来指定的。



读写实例代码:

分旧API和新API


package filedemo;

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.IntWritable;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.SequenceFile.Reader;
import org.apache.hadoop.io.SequenceFile.Writer;
import org.apache.hadoop.io.Text;
import org.junit.Test;

public class SequenceFileDemo2 {

	@Test
	public void writerOldApi() throws Exception {

		// String uri = "file:///D://B.txt"; //本地windows
		String uri = "hdfs://hello110:9000/testdata/oldApi.seq";

		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI(uri), conf, "hadoop");
		Path path = new Path(uri);

		IntWritable key = new IntWritable();
		Text value = new Text();

		Writer writer = null;
		try {
			// 方法一 writer = SequenceFile.createWriter(fs, conf, path,
			// key.getClass(), value.getClass());该方法已过时
			writer = new Writer(fs, conf, path, key.getClass(), value.getClass());
			for (int i = 0; i < 100; i++) {
				key.set(i);
				value.set("now the number is :" + i);
				System.out.printf("[%s]\t[%s]\t%s\t%s\n", "写入",writer.getLength(), key, value);
				writer.append(key, value);
			}

		} finally {
			IOUtils.closeStream(writer);
		}
	}
	
	@Test
	public void readerOldApi() throws Exception {
		
		// String uri = "file:///D://B.txt"; //本地windows
		String uri = "hdfs://hello110:9000/testdata/oldApi.seq";

		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI(uri), conf, "hadoop");
		Path path = new Path(uri);
		
		IntWritable key = new IntWritable();
		Text value=new Text();

		
		Reader reader =null;
		try {
			reader=new Reader(fs, path, conf);
			while(reader.next(key, value)){
				System.out.printf("[%s]\t%s\t%s\n", "读取", "key", key);
				System.out.printf("[%s]\t%s\t%s\n", "读取", "value", value);
			}
			
		} finally {
			IOUtils.closeStream(reader);
		}
	}
	
	@Test
	public void writerNewApi() throws Exception {
		/*
		 * windows环境使用hdfs://的时候,如果没有使用FileSystem指定用户,
		 * 那么会以当前windows用户去访问,如果当前windows用户名和Linux的不同,则会报错:
		 * Exception in thread "main" org.apache.hadoop.security.AccessControlException: Permission denied: user=xxxx
		 * 故而本demo用了 file://
		 * 解决方法:
		 * 1、修改windows当前用户名为相应的linux-hadoop的用户。win10系统较难修改用户名。
		 * 2、在linux上增加当前windows用户为hadoop的用户
		 */
		
		//String uri = "hdfs://hello110:9000/testdata/newApi.seq"; 
		String uri = "file:///D://newApi.seq";

		Configuration conf = new Configuration();
		Path path = new Path(uri);

		IntWritable key = new IntWritable();
		Text value = new Text();

		Writer writer = null;

		try {
			writer = SequenceFile.createWriter(conf,Writer.file(path), Writer.keyClass(key.getClass()),
					Writer.valueClass(value.getClass()));
			
			for (int i = 0; i < 100; i++) {
				key.set(i);
				value.set("now the new number is :" + i);
				System.out.printf("[%s]\t%s\t%s\n", writer.getLength(), key, value);
				writer.append(key, value);
			}

		} finally {
			IOUtils.closeStream(writer);
		}
	}
	
	
	@Test
	public void readerNewApi() throws Exception {
		
		String uri = "file:///D://newApi.seq";

		Configuration conf = new Configuration();
		Path path = new Path(uri);

		IntWritable key = new IntWritable();
		Text value = new Text();
		
		Reader reader=null;
		
		try {
			reader=new Reader(conf, Reader.file(path));
			while(reader.next(key, value)){
				System.out.printf("[%s]\t%s\t%s\n", "读取", "key", key);
				System.out.printf("[%s]\t%s\t%s\n", "读取", "value", value);
			}
			
		} finally {
			IOUtils.closeStream(reader);
		}
		
	}
	
	

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

松门一枝花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值