5.3 文件格式
来源:互联网 发布:js字符串获取指定下标 编辑:程序博客网 时间:2024/06/16 09:45
5.3 文件格式
有很多文件格式自身也是数据结构。在Hive那章中,我们介绍了ORC文件——优化记录列式文件存储。Hadoop还支持其他一些流行的文件格式。
5.3.1 Sequence文件格式
Sequence文件是包含二进制键值对的一种文件格式。Sequence文件中的每一条记录都含有一个键和键对应的值。Sequence文件把多个较小的文件合并成单个较大的文件,这样可以缓解Hadoop中由于小文件过多而产生的问题。此时,文件名作为键,键的值就是文件内容。Sequence文件因为可以切分成可配置的数据块,所以得到广泛的应用。Sequence文件还能和快速压缩方法集成,如LZO或Snappy,从而在提高处理速度的同时,还能减少存储和带宽的消耗。
下图展示了Sequence文件内部格式。文件的开头是一个魔数(magic number),即SEQ的二进制表示,之后是1个版本字节和头部信息(header)。头部信息存有文件的元数据,如键和值的类名(字符串形式的名字)。比如键或值属于Text类,那么org.apache.hadoop.io.Text就会写入头部。类名后面是布尔值,表示是否启用了压缩,而块压缩也是按此顺序启用。之后会写入压缩编解码器的类名,接着是用户相关元数据的键值对,最后头部信息会以同步(sync)标记结尾。同步标记也能用来标记文件中记录的边界,而且它们都是随机生成的。因为同步标记会有存储开销,所以它们的总大小不会超过总文件大小的1%。这也就意味着,同步标记会出现在一组记录的后面。
每条记录都包含对应的元数据,如记录长度和键长度。键和值的实际内容以字节的形式跟在元数据之后。长度用IntWritable类序列化为4字节的整型值。如果启用了记录压缩,会使用头部信息中定义的压缩编解码器来压缩值,但这不会改变记录结构。当启用压缩时,键不会被压缩。
进行块压缩时,记录被分组成块。块的大小的最小值由io.seqfile.compress.blocksize属性决定。在每个块的开始位置会写入一个同步标记。这个同步标记为16字节,由(UID()+’@’+时间或网络地址)表达式的hash值所组成。块压缩也会对键做压缩。块使用VIntWritable序列化来存储记录数,键长度和键。
读写Sequence文件
以下代码演示了如何使用SequenceFile格式来读写文件。writeSequenceFile方法获取待转换的源文件路径和输出文件路径这两个参数。SequenceFile类中的createWriter静态方法用于创建写入器处理器。写入处理器的append方法获取键和值,并把它们追加写入文件。以下代码读取一个CSV文件,然后以行数为键,行内容为值写入输出文件。
package MasteringHadoop;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.io.*;import org.apache.hadoop.util.ReflectionUtils;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.URI;public class MasteringHadoopSequenceFile { public static void writeSequenceFile(String textFile, String seqFile) throws IOException{ Path readPath = new Path(textFile); Path writePath = new Path(seqFile); Configuration conf = new Configuration(false); FileSystem fs = FileSystem.get(URI.create(textFile), conf); BufferedReader bufferedReader = null; SequenceFile.Writer sequenceFileWriter = null; try{ bufferedReader = new BufferedReader (new InputStreamReader (fs.open(readPath))); //创建Sequence写入处理器 sequenceFileWriter = SequenceFile.createWriter(conf, SequenceFile.Writer.file(writePath), SequenceFile.Writer.keyClass(LongWritable.class), SequenceFile.Writer.valueClass(Text.class)); String line = null; LongWritable key = new LongWritable(); Text value = new Text(); long lineCount = 0; while((line = bufferedReader.readLine()) != null){ key.set(lineCount); lineCount++; value.set(line); sequenceFileWriter.append(key, value); } } catch(IOException ioEx){ ioEx.printStackTrace(); } finally{ if(sequenceFileWriter != null) sequenceFileWriter.close(); if(bufferedReader != null) bufferedReader.close(); } } public static void readSequenceFile(String seqFile) throws IOException{ Path readPath = new Path(seqFile); Configuration conf = new Configuration(false); FileSystem fs = FileSystem.get(URI.create(seqFile), conf); SequenceFile.Reader reader = null; try{ //创建读取器 reader = new SequenceFile.Reader(conf, SequenceFile.Reader.file(readPath)); //可以从Sequence文件的头部信息中获取键和值的类型。ReflectionUtils有些工具方法可以基于这些类型创建对象。 Writable key = (Writable)ReflectionUtils.newInstance(reader.getKeyClass(), conf); Writable value = (Writable)ReflectionUtils.newInstance(reader.getValueClass(), conf); while(reader.next(key,value)){ System.out.println("key: " + key.toString()); //读取文件时,syncSeen方法可指出在文件中是否遇到了同步标记 if(reader.syncSeen()){ System.out.println("sync: "); } } } catch(IOException ioEx){ ioEx.printStackTrace(); } finally{ if(reader != null){ reader.close(); } } } public static void main(String[] args){ try{ writeSequenceFile(args[0], args[1]); readSequenceFile(args[1]); } catch(IOException ioEx){ ioEx.printStackTrace(); } System.out.println("Task has finished!"); }}
执行参数:
./input/countrycodes.txt ./output/seqoutput
以下Hadoop指令也可以读取Sequence文件:
hadoop fs -text /usr/input/countrycodes.seq
5.3.2 MapFile格式
从结构上来说,MapFile和SequenceFile一样。此外,MapFile文件提供了对键的索引。MapFile的键必须是WritableComparable类型,值必须是Writable类型。而SequenceFile的键和值可通过任何序列化框架进行序列化。
创建MapFile后,会生成两个相关文件,一个存有数据,另一个存有索引。这些文件都是SequenceFile类型。数据SequenceFile存有所有数据记录,并以键排序。索引SequenceFile存有键和其在文件中偏移量。索引文件中的键是通过采样而得的,所以其中不会存放所有的键。io.map.index.interval属性的值可以指定采样间隔。以下例子展示了countrycodes.map文件中的数据和索引文件:
hadoop fs -ls countrycodes.map/Found 2 items-rw-r--r-- 3 sandeepkaranth supergroup 10033 2014-06-08 14:20 countrycodes.map/data-rw-r--r-- 3 sandeepkaranth supergroup 166 2014-06-08 14:35 countrycodes.map/indexhadoop fs -text countrycodes.map/index127 5088hadoop fs -text countrycodes.map/data241 vi,Virgin Islands (USA)242 vn,Vietnam243 vu,Vanuatu244 wf,Wallis and Futuna Islands...
MapFile格式有助于进行Map侧连接。在连接时,可以根据数据和索引文件的有序性来切分数据集,再将其传输给单个Map任务。创建MapFile格式文件的API类似于创建SequenceFile的API。以下代码演示了如何使用MapFile.fix()静态方法把SequenceFile转换为MapFile:
package MasteringHadoop;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.io.MapFile;import org.apache.hadoop.io.SequenceFile;import java.io.IOException;import java.net.URI;public class MasteringHadoopMapFile { public static void writeMapFile(String seqFile) throws IOException { Path readPath = new Path(seqFile); Path mapPath = new Path(readPath, MapFile.DATA_FILE_NAME); Configuration conf = new Configuration(false); FileSystem fs = FileSystem.get(URI.create(seqFile), conf); SequenceFile.Reader reader = null; try{ reader = new SequenceFile.Reader(conf, SequenceFile.Reader.file(mapPath)); Class keyClass = reader.getKeyClass(); Class valueClass = reader.getValueClass(); MapFile.fix(fs, readPath, keyClass, valueClass, false, conf); } catch(IOException ioEx){ ioEx.printStackTrace(); } catch(Exception ex){ ex.printStackTrace(); } finally{ if(reader != null){ reader.close(); } } } public static void main(String[] args){ try{ writeMapFile(args[0]); } catch(IOException ioEx){ ioEx.printStackTrace(); } }}
执行参数:
./output
将SequenceFile文件改名为data并复制到./output文件中,可以看到程序执行后,生成了index文件。
**5.3.3 其他数据结构
Hadoop也支持其他可持久化的数据结构,它们都是MapFile的变体。以下列举了其中一些结构。
- SetFile
- ArrayFile
- BloomMapFile
- 5.3 文件格式
- 文件格式
- 文件格式
- 文件格式
- 文件格式
- 文件格式
- NME3.5.3中的新工程文件格式
- 【文件格式】BMP文件格式
- MIDI 文件格式
- AVI文件格式
- RealMedia文件格式
- 文件格式大全
- MP3文件格式
- BMP文件格式
- MP3文件格式
- AVI文件格式
- MIDI 文件格式
- AVI文件格式
- 第13节:scala编程之模式匹配
- (最高性能)高效求一个数是否为素数,6倍原理
- 并发编程(13)-线程池
- jquery操作vml的坑
- Sql 上机实验1
- 5.3 文件格式
- A + B Problem II
- Docker(一) 入门简介和在CentOS 7 上安装
- DB2直接修改表结构后表无法操作的处理方法
- jenkins--20--简单入门
- Windows Office Excel 数据字典的批量替换代码
- 为何优秀的程序员会不断离去
- 机器学习中的数学(5)-强大的矩阵奇异值分解(SVD)及其应用
- Android前端 Java后端 集成支付宝支付