最近仔细研究了以下公司中使用的SequenceFile文件格式,SequenceFile的格式比较紧凑,实现了从中间读取文件内容(便于hadoop将文件进行适当地切分),同时也可以支持仅读取文件的元数据功能。

概述

经过总结后的文件格式图大概如下:


 

其中进入到SequenceFile的所有记录,都需要根据一定的hash规则确定一个HashKey。相对而言,记录块是比较简单的,每个记录块中仅包含块的大小,以及该块的数据;元数据就相对而言比较复杂,其中Metadata size是总体的记录数,每个HashKey均可以直接定位到记录的位置(offset, length, number记载着这些信息)。

其中需要注意的是,记录是严格有序的,写文件需要按照HashKey的顺序进行写入,也就是说,不能向该文件中append一条HashKey在当前Key之前的数据,一旦文件写完成,可能不能再更改。

实现的类图大概如下:


 

其中Writer负责写入文件,最重要的方法就是append,注意append的key顺序要保证;Reader负责读取文件,遍历next直到没有可用数据。

文件的写入

写入是由多次append执行的,每次append仅仅会写入其中的RecordBlock数据,而将元数据放在内存中:

 if (length < 0) {
throw new IOException("negative length values not allowed: " + length);
}
this.out.write(val, offset, length);
++this.number;

等到最后所有数据都已经写入完成后,执行writeTailer写入尾部的文件特征码,版本,元数据和元数据长度等信息:

private void writeTailer() throws IOException {
this.lastPos = this.out.getPos();
this.out.write(XXSequenceFile.VERSION, 0, XXSequenceFile.VERSION.length);
Text.writeString(this.out, valClass.getName());
this.metadata.write(this.out);
long currentPos = this.out.getPos();
this.out.writeInt((int) (currentPos - this.lastPos));
}

经过测试,我们向其中写入3条String数据:{“A”, “BA”, “Cba”}(其hash值分别为1,63,2)的结果为:

0000000: 0141 0343 6261 0242 414d 5a53 4551 0119  .A.Cba.BAXXSEQ..
0000010: 6f72 672e 6170 6163 6865 2e68 6164 6f6f org.apache.hadoo
0000020: 702e 696f 2e54 6578 7400 0000 0003 0000 p.io.Text.......
0000030: 0001 3100 0000 0000 0000 0000 0000 0000 ..1.............
0000040: 0000 0200 0000 0000 0000 0100 0000 0132 ...............2
0000050: 0000 0000 0000 0002 0000 0000 0000 0004 ................
0000060: 0000 0000 0000 0001 0000 0002 3633 0000 ............63..
0000070: 0000 0000 0006 0000 0000 0000 0003 0000 ................
0000080: 0000 0000 0001 0000 007d 0a .........}.

文件的读取

那么这种类型的文件,读取从哪里开始?就是从最后面的length(int格式),我们直接跳转到最后4个字节:

this.in.seek(this.length - 4);
int tailLength = this.in.readInt();
this.contentEnd = this.length - 4 - tailLength;
this.in.seek(this.contentEnd);

这样可以直接定位到元数据的位置,然后将读取元数据至内存:

this.metadata.readFields(this.in);

最后通过setMeta()方法,设置key要读取的位置,其中参数就为HashKey,根据HashKey已经能够查找到对应的offset偏移量,定位到记录的所在:

 XXSequenceFileMeta smeta = this.metadata.get(meta);
if (smeta != null) {
this.partIn = new XXSequenceFile.PartInputStream(this.in, smeta.getOffset(),
smeta.getOffset() + smeta.getLength());
this.number = smeta.getNumber();
} else {
this.partIn = new MzSequenceFile.PartInputStream(this.in);
this.number = 0;
}

这样就实现了一整套SequenceFile文件写入/读取的功能,文件格式紧凑,并且可以从任意地方开始读取。

一种SequenceFile的格式研究的更多相关文章

  1. 几种web字体格式

    目前,文字信息仍是网站最主要的内容,随着CSS3技术的不断成熟,Web字体逐渐成为话题,这项让未来Web更加丰富多彩的技术拥有多种实现方案,其中之一是通过@font-face属性在网页中嵌入自定义字体 ...

  2. Java学习-013-文本文件读取实例源代码(两种数据返回格式)

    此文源码主要为应用 Java 读取文本文件内容实例的源代码.若有不足之处,敬请大神指正,不胜感激! 1.读取的文本文件内容以一维数组[LinkedList<String>]的形式返回,源代 ...

  3. JSON——IT技术人员都必须要了解的一种数据交换格式

    JSON作为目前Web主流的数据交换格式,是每个IT技术人员都必须要了解的一种数据交换格式.尤其是在Ajax和REST技术的大行其道的当今,JSON无疑成为了数据交换格式的首选! 今天大家就和猪哥一起 ...

  4. 【转载】总结:几种生成HTML格式测试报告的方法

    总结:几种生成HTML格式测试报告的方法 写自动化测试时,一个很重要的任务就是生成漂亮的测试报告. 1.用junit或testNg时,可以用ant辅助生成html格式: <target name ...

  5. 常用两种数据交换格式之XML和JSON的比较

    目前,在web开发领域,主要的数据交换格式有XML和JSON,对于XML相信每一个web developer都不会感到陌生: 相比之下,JSON可能对于一些新步入开发领域的新手会感到有些陌生,也可能你 ...

  6. XML和JSON两种数据交换格式的比较

    在web开发领域,主要的数据交换格式有XML和JSON,对于在 Ajax开发中,是选择XML还是JSON,一直存在着争议,个人还是比较倾向于JSON的.一般都输出Json不输出xml,原因就是因为 x ...

  7. 多媒体开发之h264的三种字节流格式---annexb 哥伦布/mp4 以及还有一种rtp传输流格式

    ------------------------------------author:pkf ------------------------------------------time:2015-1 ...

  8. U盘的几种分类及格式

    u盘常见的几种分类: 1.按u盘材质来分,可以分为金属u盘.塑料u盘.软胶u盘.皮革u盘.木质u盘.珠宝u盘等.这些主要是考虑u盘本身外壳所用材质的. 2.从u盘容量来分,就是8GB.16GB.32G ...

  9. 总结:几种生成html格式测试报告的方法

    写自动化测试时,一个很重要的任务就是生成漂亮的测试报告. 1.用junit或testNg时,可以用ant辅助生成html格式: <target name="report" d ...

随机推荐

  1. SpringInAction--XML配置Spring Aop

    前面学习了如何用注解的方式去配置Spring aop,今天把XML配置的方法也看了下,下面顺便也做了个记录 先把spring中用xml配置aop的配置元素给贴出来: <aop:advisor&g ...

  2. Getting command line access to PHP and MySQL running MAMP on OSX

    建立自己profile路径应该在/Users/yourname/,最后要运行. ./.profile使文件生效,和windows中给添加环境变量是一个道理,还可以看出linux和UNIX默认运行路径为 ...

  3. Shell 循环中实现展示进度百分比的脚本方法

    Shell 循环中实现展示进度百分比的脚本方法 当我需要处理一个几万行的文件的时候,需要处理的时间是比较长的.我一开始的想法是,没处理一行,就输出一个 # 号.但是这样还是会出现很多很多的 # 号,即 ...

  4. Android敏捷开发、CI(持续集成)探究

    比较老的几篇文章,依旧有学习价值 http://blog.csdn.net/baodinglaolang/article/details/9530695 http://blog.csdn.net/ba ...

  5. 解决在django中应用keras模型时出现的ValueError("Tensor %s is not an element of this graph." % obj)问题

    用keras训练好模型,再在django初始化加载模型,这个过程没有问题,但是在调用到模型执行model.predict()的时候就报错: raise ValueError("Tensor ...

  6. linux环境搭建记录

    第一次搭建环境,部署服务,在此记录一下过程 1.项目用到的hosts设置好 2.mkdir data,在data文件夹下建server,log,soft,resource路径,上载jdk.zip到so ...

  7. 【pandas】pandas.Series.str.split()---字符串分割

    原创博文,转载请注明出处! 本文代码的github地址       series中的元素均为字符串时,通过str.split可将字符串按指定的分隔符拆分成若干列的形式. 例子: 拆分以逗号为分隔符的字 ...

  8. Git详解之十 Git常用命令

    下面是我整理的常用 Git 命令清单.几个专用名词的译名如下. Workspace:工作区 Index / Stage:暂存区 Repository:仓库区(或本地仓库) Remote:远程仓库 一. ...

  9. CXF生成本地ws调用代码测试webservice

    package com.free.webservice.client; import java.util.List; import cn.com.webxml.*; public class Weat ...

  10. SEO中H1标签的用法- 1

    在网上找了很多关于H1标签对SEO意义的资料,不可否认H1对SEO具有重大的意义,但是具体情况每个人有每个人的见解吧.这里主要根据网上搜索的资料,以及自己的一些经验整理出来的,但是本人毕竟不是专业SE ...