标签:
在一些应用中,我们需要一种特殊的数据结构来存储数据,并进行读取,这里就分析下为什么用SequenceFile格式文件。
Hadoop SequenceFile
Hadoop提供的SequenceFile文件格式提供一对key,value形式的不可变的数据结构。同时,HDFS和MapReduce job使用SequenceFile文件可以使文件的读取更加效率。
SequenceFile的格式
SequenceFile的格式是由一个header 跟随一个或多个记录组成。前三个字节是一个Bytes SEQ代表着版本号,同时header也包括key的名称,value class , 压缩细节,metadata,以及Sync markers。Sync markers的作用在于可以读取任意位置的数据。
在recourds中,又分为是否压缩格式。当没有被压缩时,key与value使用Serialization序列化写入SequenceFile。当选择压缩格式时,record的压缩格式与没有压缩其实不尽相同,除了value的bytes被压缩,key是不被压缩的。
在Block中,它使所有的信息进行压缩,压缩的最小大小由配置文件中,io.seqfile.compress.blocksize配置项决定。
SequenceFile的MapFile
一个MapFile可以通过SequenceFile的地址,进行分类查找的格式。使用这个格式的优点在于,首先会将SequenceFile中的地址都加载入内存,并且进行了key值排序,从而提供更快的数据查找。
写SequenceFile文件:
将key按100-1以IntWritable object进行倒叙写入sequence file,value为Text objects格式。在将key和value写入Sequence File前,首先将每行所在的位置写入(writer.getLength())
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.Text;
import java.io.IOException;
import java.net.URI;
public classSequenceFileWriteDemo {private static final String[] DATA ={"One, two, buckle my shoe","Three, four, shut the door","Five, six, pick up sticks","Seven, eight, lay them straight","Nine, ten, a big fat hen"};public static void main(String[] args) throwsIOException {
String uri= args[0];
Configuration conf= newConfiguration();
FileSystem fs=FileSystem.get(URI.create(uri), conf);
Path path= newPath(uri);
IntWritable key= newIntWritable();
Text value= newText();
SequenceFile.Writer writer= null;try{
writer=SequenceFile.createWriter(fs, conf, path,
key.getClass(), value.getClass());for (int i = 0; i < 100; i++) {
key.set(100 -i);
value.set(DATA[i%DATA.length]);
System.out.printf("[%s]\t%s\t%s\n", writer.getLength(), key, value);
writer.append(key, value);
}
}finally{
IOUtils.closeStream(writer);
}
}
}
读取SequenceFile文件:
首先需要创建SequenceFile.Reader实例,随后通过调用next()函数进行每行结果集的迭代(需要依赖序列化).
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.SequenceFile;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.util.ReflectionUtils;
import java.io.IOException;
import java.net.URI;
public classSequenceFileReadDemo {public static void main(String[] args) throwsIOException {
String uri= args[0];
Configuration conf= newConfiguration();
FileSystem fs=FileSystem.get(URI.create(uri), conf);
Path path= newPath(uri);
SequenceFile.Reader reader= null;try{
reader= newSequenceFile.Reader(fs, path, conf);
Writable key=(Writable)
ReflectionUtils.newInstance(reader.getKeyClass(), conf);
Writable value=(Writable)
ReflectionUtils.newInstance(reader.getValueClass(), conf);long position =reader.getPosition();while(reader.next(key, value)) {
//同步记录的边界
String syncSeen= reader.syncSeen() ? "*" : "";
System.out.printf("[%s%s]\t%s\t%s\n", position, syncSeen, key, value);
position= reader.getPosition(); //beginning of next record
}
}finally{
IOUtils.closeStream(reader);
}
}
}
参考文献: 《Hadoop:The Definitive Guide, 4th Edition》
标签: