Как быстро создать большие (>1 ГБ) текстовые + двоичные файлы с "естественным" контентом? (С#)

для тестирования сжатия мне нужно иметь возможность создавать большие файлы, в идеале в текстовом, двоичном и смешанном форматах.

  • содержимое файлов не должно быть ни полностью случайным, ни однородным.
    Двоичный файл со всеми нулями не годится. Двоичный файл с полностью случайными данными также не хорош. Для текста файл с полностью случайными последовательностями ASCII не годится - текстовые файлы должны иметь шаблоны и частоты, имитирующие естественный язык, или исходный код (XML, C# и т. д.). Псевдо-реальный текст.
  • размер каждого отдельного файла не критичен, но для набора файлов мне нужно, чтобы общая сумма была ~8 ГБ.
  • Я хотел бы сохранить количество файлов на управляемом уровне, скажем, o (10).

для создания двоичных файлов я могу создать большой буфер и сделать систему.Случайность.NextBytes последующим файлового потока.Напишите в цикле, вот так:

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 настолько мал (

ни то, ни другое меня не удовлетворяет.

Я видел ответы быстро создать большой файл в системе Windows?. Эти подходы очень быстры, но я думаю, что они просто заполняют файл нулями или случайными данными, ни один из которых я не хочу. У меня нет проблем с запуском внешнего процесса, такого как contig или fsutil, если это необходимо.

тесты выполняются в Windows.
Вместо того, чтобы создавать новые файлы, делает ли это больше смысл просто использовать файлы, которые уже существуют в файловой системе? Я не знаю ни одного достаточно большого.

Как насчет запуска с одного существующего файла (возможно c:windowsMicrosoft.NETFrameworkv2.0.50727Configenterprisesec.config.cch для текстового файла) и многократно тиражировать его содержимое? Это будет работать с текстовым или двоичным файлом.

В настоящее время у меня есть подход, который работает, но он занимает слишком много времени.

кто-нибудь другой решил это?

есть ли гораздо более быстрый способ написать текстовый файл, чем через StreamWriter?

предложения?

редактировать: мне нравится идея Марковской цепи для создания более естественного текста. Тем не менее, все еще нужно решить проблему скорости.

8 ответов


Я думаю, вы, возможно, ищете что-то вроде цепи Маркова процесс для генерации этих данных. Это как стохастический (рандомизированный), но и структурированный, поскольку он работает на основе конечный автомат.

действительно, Марковские цепи были использованы для создания полу-реалистичного просмотр текста в человеческих языках. В общем, это не тривиальные вещи для правильного анализа, но тот факт, что они проявляют определенные свойства, должен быть достаточно хорош для вы. (Опять же, смотрите свойства марковских цепей страницы.) Надеюсь, вы должны увидеть, как проектировать один, однако-реализовать, это на самом деле довольно простая концепция. Лучше всего, вероятно, создать структуру для общего Марковского процесса, а затем проанализировать естественный язык или исходный код (в зависимости от того, что вы хотите, чтобы ваши случайные данные эмулировать), чтобы "обучить" ваш Марковский процесс. В конце концов, это должно дать вам очень высококачественные данные с точки зрения вашего требования. Ну стоит усилий, если вам нужны эти огромные длины тестовых данных.


для текста, вы можете использовать общий переполнением стека, там 300megs данных. Это займет всего около 6 минут, чтобы загрузить в БД с приложением, которое я написал, и, вероятно, примерно в то же время, чтобы сбросить все сообщения в текстовые файлы, что легко даст вам от 200K до 1 миллиона текстовых файлов, в зависимости от вашего подхода (с дополнительным бонусом наличия источника и xml смешивается).

вы также можете использовать что-то вроде Википедия свалка, похоже, поставляется в формате MySQL, что сделало бы его очень простым в работе.

Если вы ищете большой файл, который вы можете разделить, для двоичных целей, вы можете использовать VM vmdk или DVD, разорванный локально.

редактировать

Марк упоминает проект Gutenberg download, это также очень хороший источник для текста (и аудио), который доступен для скачать через bittorrent.


вы всегда можете закодировать себе небольшой веб-искатель...

обновление Успокойтесь, ребята, это б хороший ответ, Если он не сказал, что у него уже есть решение, что "слишком долго".

быстрая проверка здесь будет означать, что загрузка 8GB чего-либо займет относительно долгое время.


Я думаю, что каталог Windows, вероятно, будет достаточно хорошим источником для ваших нужд. Если вы после текста, я бы рекурсивно через каждый из каталогов, которые ищут .txt файлы и цикл через них копирование их в выходной файл столько раз, сколько необходимо, чтобы получить файл нужного размера.

затем вы можете использовать аналогичный подход для двоичных файлов, ища .exes или .файл DLL.


для текстовых файлов у вас может быть некоторый успех, принимая английский список слов и просто вытаскивая слова из него наугад. Это не приведет к реальному английскому тексту, но я бы предположил, что это произведет частоту букв, подобную тому, что вы можете найти на английском языке.

для более структурированного подхода вы можете использовать цепи Маркова обучение на каком-то большом свободном английском тексте.


Почему бы вам просто не взять Lorem Ipsum и создать длинную строку в памяти перед выходом. Текст должен расширяться со скоростью O (log n), если вы удваиваете объем текста каждый раз. Вы даже можете рассчитать общую длину данных перед рукой, позволяя вам не страдать от необходимости копировать содержимое в новую строку / массив.

Так как ваш буфер составляет всего 512k или что бы вы ни установили, вам нужно только генерировать столько данных, прежде чем писать его, так как это это только сумма, которую вы можете нажать, чтобы файл за один раз. Вы будете писать один и тот же текст снова и снова, поэтому просто используйте оригинальный 512k, который вы создали в первый раз.


Википедия отлично подходит для тестирования сжатия для смешанного текста и двоичного файла. Если вам нужны сравнения, то сайт премии Хаттера может обеспечить высокую отметку воды для первых 100 МБ Википедии. Текущая запись имеет коэффициент 6.26, 16 МБ.


Спасибо за быстрый ввод. Я решил рассмотреть проблемы скорости и "естественности" отдельно. Для генерации естественного текста я объединил несколько идей.

  • чтобы создать текст, я начинаю с нескольких текстовых файлов из Проект Гутенберг каталог, как предложил Марк Rushakoff.
  • я случайным образом выбираю и загружаю один документ из этого подмножества.
  • затем я применяю Марковский процесс, как предложено Нолдорин!--5-->, используя этот загруженный текст в качестве ввода.
  • Я написал новую цепочку Маркова на C#, используя экономичная реализация Perl пайка в качестве примера. Он генерирует текст по одному слову за раз.
  • для эффективности, вместо того, чтобы использовать чистую цепочку Маркова для генерации 1 ГБ текста по одному слову за раз, код генерирует случайный текст ~1 Мб, а затем повторно берет случайные сегменты этого и глобирует их вместе.

обновление: что касается второй проблемы, скорость - я взял подход, чтобы устранить как можно больше ввода-вывода, это делается на моем плохом ноутбуке с мини-шпинделем 5400rpm. Что привело меня к полному пересмотру проблемы-вместо того, чтобы генерировать со случайным контентом, то, что я действительно хочу, это случайный контент. Используя поток, обернутый вокруг цепи Маркова, я могу генерировать текст в памяти и передавать его в компрессор, исключая 8g писать и 8g читать. Для этого конкретного теста мне не нужно проверять сжатие / декомпрессию туда и обратно, поэтому мне не нужно сохранять исходное содержимое. Таким образом, потоковый подход хорошо работал, чтобы значительно ускорить процесс. Он отрезал 80% из требуемого времени.

Я еще не понял, как сделать двоичное поколение, но это, вероятно, будет что-то аналогичное.

еще раз спасибо всем за полезные идеи.