【问题标题】:C# parsing of Freebase RDF dump yields only 11.5 million N-Triples instead of 1.9 billionFreebase RDF 转储的 C# 解析仅产生 1150 万个 N-Triple,而不是 19 亿个
【发布时间】:2014-02-19 00:42:31
【问题描述】:

我正在构建一个 C# 程序来读取 Google Freebase data dump 中的 RDF 数据。首先,我编写了一个简单的循环来简单地读取文件并获取三元组的计数。然而,我的程序并没有像文档页面(上面提到的)中所说的那样获得 19 亿个计数,而是只计算了大约 1150 万个然后退出。源代码的相关部分如下(运行大约需要 30 秒)。

我在这里错过了什么?

// Simple reading through the gz file
try
{
    using (FileStream fileToDecompress = File.Open(@"C:\Users\Krishna\Downloads\freebase-rdf-2014-02-16-00-00.gz", FileMode.Open))
    {
        int tupleCount = 0;
        string readLine = "";

        using (GZipStream decompressionStream = new GZipStream(fileToDecompress, CompressionMode.Decompress))
        {
            StreamReader sr = new StreamReader(decompressionStream, detectEncodingFromByteOrderMarks: true);

            while (true)
            {
                readLine = sr.ReadLine();
                if (readLine != null)
                {
                    tupleCount++;
                    if (tupleCount % 1000000 == 0)
                    { Console.WriteLine(DateTime.Now.ToShortTimeString() + ": " + tupleCount.ToString()); }
                }
                else
                { break; }
            }
            Console.WriteLine("Tuples: " + tupleCount.ToString());
        }
    }
}
catch (Exception ex)
{ Console.WriteLine(ex.Message); }

(我尝试在dotNetRdf 中使用GZippedNTriplesParser 通过在this recommendation 上构建来读取数据,但这似乎在一开始就在RdfParseException 上令人窒息(制表符分隔符?UTF-8??) . 所以,目前,尝试推出我自己的)。

【问题讨论】:

  • 向 dotNetRDF 邮件列表或问题跟踪器提交错误报告,使解析器阻塞 Freebase 输出,我们将不胜感激

标签: c# rdf freebase


【解决方案1】:

Freebase RDF 转储由输出 200 个单独 Gzip 文件的 map/reduce 作业构建。然后将这 200 个文件连接成一个最终的 Gzip 文件。 According to the Gzip spec,连接来自多个 Gzip 文件的原始字节将生成一个有效的 Gzip 文件。符合规范的库在解压缩该文件时应该生成一个包含每个输入文件的串联内容的单个文件。

根据您看到的三元组的数量,我猜您的代码只是解压缩文件的第一个块而忽略了其他 199 个。我不是 C# 程序员,但从阅读 @ 987654322@ 看来切换到DotNetZip 就可以解决这个问题了。

【讨论】:

  • Shawn 感谢您指出我遗漏的内容! 200个文件似乎可以解释它。我按照您的建议尝试了 DotNetZip(并阅读了他们的文档),但到目前为止还无法生成一个组合的所有文件流,我可以从中执行诸如 ReadLine() 之类的操作。它似乎只读取第一个文件,类似于 .NET GZipStream。它显然可以更轻松地处理 zip(而不是 gzip)文件。我会继续做更多的实验;如果有人可以发布任何相关的代码示例,那将非常有帮助!
【解决方案2】:

我正在使用 DotNetZip 并为“gzipped chunks”解决方法创建装饰类 GzipDecorator。

sealed class GzipDecorator : Stream
{
    private readonly Stream _readStream;
    private GZipStream _gzip;
    private long _totalIn;
    private long _totalOut;

    public GzipDecorator(Stream readStream)
    {
        Throw.IfArgumentNull(readStream, "readStream");
        _readStream = readStream;
        _gzip = new GZipStream(_readStream, CompressionMode.Decompress, true);
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        var bytesRead = _gzip.Read(buffer, offset, count);
        if (bytesRead <= 0 && _readStream.Position < _readStream.Length)
        {
            _totalIn += _gzip.TotalIn + 18;
            _totalOut += _gzip.TotalOut;
            _gzip.Dispose();
            _readStream.Position = _totalIn;
            _gzip = new GZipStream(_readStream, CompressionMode.Decompress, true);
            bytesRead = _gzip.Read(buffer, offset, count);
        }
        return bytesRead;
    }
}

【讨论】:

  • 你已经解释了上面的答案是如何解决这个问题的
  • 用于 ungzip 级联 gzip 文件的库不起作用。它们只是按顺序解压缩的第一个文件。您可以在我的答案之前阅读答案和评论,并解释问题来源。简单地切换到 DotNetZip 不起作用。
  • 我在从 gzip 压缩的 nginx 日志中读取时遇到了同样的问题 - 普通库只读取了一小部分日志。我的搜索给我带来了没有答案的问题。并解决 2002 年的错误报告,并解决“这不是错误”。
  • 我试过这个例子,但得到了“Bad GZIP header”异常
【解决方案3】:

我设法通过使用“7-zip”归档程序重新打包转储来解决问题。也许对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 2012-07-09
    相关资源
    最近更新 更多