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);}}}