我有5GB通过Apache Thrift序列化的数据,以及一个包含数据格式的.thrift文件。我尝试使用thriftpy和官方thrift包,但无法理解如何打开这些文件。
这些数据来自http://www.iesl.cs.umass.edu/data/wiki-links的扩展数据集
数据格式的描述可以在https://code.google.com/p/wiki-link/wiki/ExpandedDataset找到
回答:
Scala的设置可以在ThriftSerializerFactory.scala文件中找到。由于Thrift库中大多数事物的命名是一致的,您可以大致按照Scala的示例来构建您的Python代码:
package edu.umass.cs.iesl.wikilink.expanded.processimport org.apache.thrift.protocol.TBinaryProtocolimport org.apache.thrift.transport.TIOStreamTransportimport java.io.Fileimport java.io.BufferedOutputStreamimport java.io.FileOutputStreamimport java.io.BufferedInputStreamimport java.io.FileInputStreamimport java.util.zip.{GZIPOutputStream, GZIPInputStream} object ThriftSerializerFactory { def getWriter(f: File) = { val stream = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(f)), 2048) val protocol= new TBinaryProtocol(new TIOStreamTransport(stream)) (stream, protocol) } def getReader(f: File) = { val stream = new BufferedInputStream(new GZIPInputStream(new FileInputStream(f)), 2048) val protocol = new TBinaryProtocol(new TIOStreamTransport(stream)) (stream, protocol) } }
您基本上是设置了一个流传输和二进制协议。如果数据保持压缩状态,您需要添加gzip部分,但是一旦数据解压缩后,就不需要这个部分了。
WikiLinkItemIterator.scala中的代码展示了如何使用上面的工厂类读取数据文件。
class PerFileWebpageIterator(f: File) extends Iterator[WikiLinkItem] { var done = false val (stream, proto) = ThriftSerializerFactory.getReader(f) private var _next: Option[WikiLinkItem] = getNext() private def getNext(): Option[WikiLinkItem] = try { Some(WikiLinkItem.decode(proto)) } catch {case _: TTransportException => {done = true; stream.close(); None}} def hasNext(): Boolean = !done && (_next != None || {_next = getNext(); _next != None}) def next(): WikiLinkItem = if (hasNext()) _next match { case Some(wli) => {_next = None; wli} case None => {throw new Exception("Next on empty iterator.")} } else throw new Exception("Next on empty iterator.")}
实现步骤:
- 像上面一样实现Thrift协议栈工厂(顺便说一句,这是推荐的模式)
- 实例化每个记录的根元素,在我们的例子中是一个
WikiLinkItem
- 调用
instance.read(proto)
来读取一条数据记录