整套大数据学习资料(视频+笔记)百度网盘无门槛下载:http://www.edu360.cn/news/content?id=3377

4.4.3Avro数据文件

hadoop 花牛 7℃ 0评论

Avro的对象容器文件格式主要用于存储Avro对象序列。这与Hadoop顺序文件的设计非常相似。主要区别在于Avro数据文件主要是面向跨语言使用而设计的,所以,可以用Python写入文件,而用C语言来读取文件。

数据文件的头部分包含元数据,包括一个Avro模式和一个sync marker(同 步标识),紧接着是一系列包含序列化Avro对象的数据块(压缩可选)。数据块由sync marker来分隔,它对该文件而言,是唯一的(特定文件的标识信息存储在文件头部),并且允许在文件中搜索到任意位置之后通过块边界快速地重新进行同步。因此,Avro数据文件是可切分的,适合MapReduce快速处理。

将Avro的对象写到数据文件与写到数据流类似。像以前一样,我们使用一个DatumWriter,但没有用Encoder,而是用DatumWriter来创建一个DataFileWriter实例。然后便可以新建一个数据文件(该文件一般有.avro扩展名)并向它附加新写入的对象:

File file = new File("data.avro");
DatumWriter<GenericRecord> writer = new GenericDatumWriter<GenericRecord>(schema);
DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(writer);
dataFileWriter.create(schema, file);
dataFileWriter.append(datum);
dataFileWriter.close();

写入数据文件的对象必须遵循相应的文件模式,否则在调用append()方法时会抛出异常。

这个例子演示了如何将对象写到本地文件(前面代码段中的java.io.File), 但使用重载的DataFileWriter的create()方法,可以将数据对象写到任何一个java.io.OutputStream对象中。例如,通过对FileSystem对象调用create()方法可以返回OutputStream对象,进而将文件写到HDFS中。

从数据文件中读取对象与前面例子中在内存数据流中读取数据类似,只有一个重要的区别:我们不需要指定模式,因为可以从文件元数据中读取它。事实上,还可以对DataFileReader实例调用getSchema()方法来获取该模式,并验证该模式是否和原始写入对象的模式相同:

DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>();
DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, reader);
assertThat("Schema is the same", schema, is(dataFileReader.getSchema()));

DataFileReader对象是一个常规的Java迭代器,由此我们可以调用其hashNext()和next()方法来迭代其数据对象。下面的代码检査是否只有一条记录以及该记录是否有期望的字段值:

assertThat(dataFileReader.hasNext(), is(true));
GenericRecord result = dataFileReader.next();
assertThat(result.get("left").toString(), is("L"));
assertThat(result.get("right").toString(), is("R"));
assertThat(dataFileReader.hasNext(), is(false));

但是,更适合的做法是使用重载并将返回对象实例作为输入参数(该例中,

GenericRecord对象),而非直接使用next()方法,因为这样会可以实现对象,减少对象分配和垃圾回收所产生的开销,特别是文件中包含有很多对象时。代码如下所示:

GenericRecord record = null;
while (dataFileReader.hasNext()) {
    record = dataFileReader.next(record);
    // process record
}

如果对象重用不是那么重要,则可以使用如下更简短的形式:

for (GenericRecord record : dataFileReader) {
    // process record
}

如果是一般的从Hadoop文件系统中读取文件,可以使用Avro的Fslnput对象来指定使用Hadoop Path对象作为输入对象。事实上,DataFileReader对象提供对Avro数据文件的随机访问(通过seek()和sync()方法)。但在大多数情况下,如果顺序访问数据流足够了,则使用DataFileStream对象。DataFileStream对象可以从任意Java InputStream对象中读取数据。

转载请注明:全栈大数据 » 4.4.3Avro数据文件

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址