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 {@Testpublic void writerOldApi() throws Exception {// String uri = "file:///D://B.txt"; //本地windowsString 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);}}@Testpublic void readerOldApi() throws Exception {// String uri = "file:///D://B.txt"; //本地windowsString 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);}}@Testpublic 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);}}@Testpublic 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);}}}