如何快速创建具有“自然”内容的大型(> 1gb)文本+二进制文件? (C#)

时间:2009-06-24 11:13:41

标签: c# .net windows testing filesystems

为了测试压缩,我需要能够创建大文件,理想情况下是文本,二进制和混合格式。

  • 文件内容既不是完全随机也不是统一的 一个全零的二进制文件是不好的。具有完全随机数据的二进制文件也不好。对于文本,具有完全随机的ASCII序列的文件不好 - 文本文件应具有模拟自然语言或源代码(XML,C#等)的模式和频率。伪真实文本。
  • 每个文件的大小并不重要,但对于文件集,我需要的总数大约为8GB。
  • 我想将文件数量保持在可管理的水平,让我们说o(10)。

为了创建二进制文件,我可以创建一个大缓冲区并在循环中执行System.Random.NextBytes后跟FileStream.Write,如下所示:

Int64 bytesRemaining = size;
byte[] buffer = new byte[sz];
using (Stream fileStream = new FileStream(Filename, FileMode.Create, FileAccess.Write))
{
    while (bytesRemaining > 0)
    {
        int sizeOfChunkToWrite = (bytesRemaining > buffer.Length) ? buffer.Length : (int)bytesRemaining;
        if (!zeroes) _rnd.NextBytes(buffer);
        fileStream.Write(buffer, 0, sizeOfChunkToWrite);
        bytesRemaining -= sizeOfChunkToWrite;
    }
    fileStream.Close();
}

使用足够大的缓冲区,比方说512k,这相对较快,即使对于超过2或3gb的文件也是如此。但内容完全是随机的,这不是我想要的。

对于文本文件,我采用的方法是使用Lorem Ipsum,并通过StreamWriter将其重复发送到文本文件中。内容是非随机且不均匀的,但它确实有许多相同的重复块,这是不自然的。而且,因为Lorem Ispum块很小(<1k),所以它需要很多循环并且非常非常长。

这些对我来说都不是很令人满意。

我已经看到了Quickly create large file on a windows system?的答案。这些方法非常快,但我认为它们只是用零或随机数据填充文件,这两者都不是我想要的。如果有必要,我可以运行像contig或fsutil这样的外部进程。

测试在Windows上运行 而不是创建新文件,仅使用文件系统中已存在的文件更有意义吗?我不知道任何足够大的东西。

如何从单个现有文件开始(对于文本文件可能是c:\ windows \ Microsoft.NET \ Framework \ v2.0.50727 \ Config \ enterprisesec.config.cch)并多次复制其内容?这适用于文本或二进制文件。

目前我有一种方法可行,但运行时间太长。

有没有其他人解决过这个问题?

编写文本文件比使用StreamWriter要快得多吗?

建议?

编辑:我喜欢马尔可夫链的想法,以产生更自然的文本。但仍需要面对速度问题。

8 个答案:

答案 0 :(得分:14)

对于文本,您可以使用stack overflow community dump,那里有300megs的数据。使用我编写的应用程序加载到数据库只需要大约6分钟,并且可能大约在同一时间将所有帖子转储到文本文件,这可以轻松地为您提供200,000到100万个文本文件,具体取决于您的方法(还有将源和xml混合在一起的额外好处。)

你也可以使用wikipedia dump这样的东西,它似乎以MySQL格式发布,这使得它非常容易使用。

如果您正在寻找可以拆分的大文件,出于二进制目的,您可以使用VM vmdk或本地翻录的DVD。

修改

Mark提到项目gutenberg下载,这也是download via bittorrent可用的文本(和音频)的一个非常好的来源。

答案 1 :(得分:10)

您可以随时为自己编写一个小型网页抓取工具......

<强>更新 冷静下来,这个是一个很好的答案,如果他没有说他已经有一个“需要太长时间”的解决方案。

快速检查here似乎表明下载8GB的内容需要相当长的时间。

答案 2 :(得分:4)

我认为您可能正在寻找类似Markov chain进程的内容来生成此数据。它既是随机的(随机的),也是结构化的,因为它基于finite state machine运作。

事实上,马尔可夫链已被用于在人类语言中生成半现实的文本。一般来说,要正确分析它们并不是一件容易的事,但它们具有某些特性的事实对你来说应该足够好。 (再次,请参阅页面的Properties of Markov chains部分。)希望你应该看到如何设计一个,但是 - 实现它实际上是一个非常简单的概念。您最好的选择可能是创建一个通用马尔可夫过程的框架,然后分析自然语言或源代码(无论您希望随机数据模拟),以便“训练”您的马尔可夫过程。最后,这可以根据您的要求为您提供高质量的数据。如果您需要这些巨大的测试数据,那么值得去努力。

答案 3 :(得分:3)

我认为Windows目录可能足以满足您的需求。如果你是在文本之后,我将通过每个目录查找.txt文件并循环遍历它们,根据需要将它们复制到输出文件,以获得正确大小的文件。

然后,您可以通过查找.exes或.dll对二进制文件使用类似的方法。

答案 4 :(得分:1)

对于文本文件,您可能会成功获取english word list并随意从中提取单词。这不会产生真正的英文文本,但我猜它会产生类似于你在英语中发现的字母频率。

对于更结构化的方法,您可以使用Markov chain对一些大型免费英语文本进行培训。

答案 5 :(得分:1)

为什么不直接使用Lorem Ipsum并在输出之前在内存中创建一个长字符串。如果您每次加倍文本量,文本应以O(log n)的速率扩展。您甚至可以预先计算数据的总长度,从而不必将内容复制到新的字符串/数组中。

由于您的缓冲区仅为512k或您设置的任何内容,因此您只需在编写之前生成那么多数据,因为这只是您可以一次推送到文件的数量。您将一遍又一遍地编写相同的文本,所以只需使用您第一次创建的原始512k。

答案 6 :(得分:1)

Wikipedia非常适合混合文本和二进制文件的压缩测试。如果你需要基准比较,Hutter Prize site可以为维基百科的前100mb提供高水位线。目前的记录是6.26比率,16 mb。

答案 7 :(得分:0)

感谢所有快速输入。 我决定分别考虑速度和“自然”的问题。为了生成自然文本,我结合了几个想法。

  • 为了生成文本,我从Mark {{{}}目录中的一些文本文件开始,正如Mark Rushakoff所建议的那样。
  • 我随机选择并下载该子集的一个文档。
  • 然后我使用下载的文本作为输入应用马尔可夫过程,project gutenberg
  • 我使用suggested by Noldorin作为示例在C#中编写了一个新的马尔可夫链。它一次生成一个单词。
  • 为了提高效率,而不是使用纯马尔可夫链一次生成一个单词的1gb文本,代码生成~1mb的随机文本,然后重复获取其中的随机段并将它们拼接在一起。

更新:至于第二个问题,速度 - 我采用了消除尽可能多的IO的方法,这是在我的可怜笔记本电脑上使用5400rpm迷你主轴完成的。这导致我完全重新定义问题 - 而不是使用随机内容生成 FILE ,我真正想要的是随机内容。使用围绕马尔可夫链的流,我可以在内存中生成文本并将其流式传输到压缩器,从而消除8g写入和8g读取。对于此特定测试,我不需要验证压缩/解压缩往返,因此我不需要保留原始内容。因此,流媒体方法可以很好地加快速度。它减少了80%的时间。

我还没有弄清楚如何进行二进制生成,但它可能是类似的东西。

再次感谢所有有用的想法。