Как я могу быстро создавать большие (> 1 ГБ) текстовые + двоичные файлы с «естественным» содержимым? (С #) - PullRequest
7 голосов
/ 24 июня 2009

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

  • Содержимое файлов не должно быть ни случайным, ни однородным.
    Бинарный файл со всеми нулями не годится. Бинарный файл с абсолютно случайными данными тоже не годится. Для текста файл с совершенно случайными последовательностями ASCII не годится - текстовые файлы должны иметь шаблоны и частоты, имитирующие естественный язык, или исходный код (XML, C # и т. Д.). Псевдо-реальный текст.
  • Размер каждого отдельного файла не критичен, но для набора файлов мне нужно, чтобы общий размер был ~ 8 ГБ.
  • Я бы хотел сохранить количество файлов на управляемом уровне, скажем, 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();
}

При достаточно большом буфере, скажем, 512 КБ, это относительно быстро, даже для файлов размером более 2 или 3 ГБ. Но контент абсолютно случайный, а это не то, что я хочу.

Для текстовых файлов я выбрал подход Lorem Ipsum и многократно отправлял его через StreamWriter в текстовый файл. Содержимое неслучайно и неоднородно, но имеет много идентичных повторяющихся блоков, что неестественно. Кроме того, поскольку блок Lorem Ispum очень мал (<1k), он занимает много циклов и очень, очень много времени. </p>

Ничто из этого не является вполне удовлетворительным для меня.

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

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

Как насчет того, чтобы начать с одного существующего файла (может быть, c: \ windows \ Microsoft.NET \ Framework \ v2.0.50727 \ Config \ enterprisesec.config.cch для текстового файла) и многократно реплицировать его содержимое? Это будет работать с текстовым или двоичным файлом.

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

Кто-нибудь еще решил это?

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

Предложения

РЕДАКТИРОВАТЬ : Мне нравится идея цепочки Маркова для создания более естественного текста. Тем не менее, необходимо решить проблему скорости.

Ответы [ 8 ]

14 голосов
/ 24 июня 2009

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

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

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

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

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

10 голосов
/ 24 июня 2009

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

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

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

4 голосов
/ 24 июня 2009

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

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

3 голосов
/ 24 июня 2009

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

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

1 голос
/ 24 июня 2009

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

1 голос
/ 24 июня 2009

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

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

1 голос
/ 24 июня 2009

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

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

0 голосов
/ 24 июня 2009

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

  • Для генерации текста я начну с нескольких текстовых файлов из каталога project gutenberg , как это было предложено Марком Рушаковым.
  • Я случайно выбираю и загружаю один документ из этого подмножества.
  • Затем я применяю марковский процесс, как , предложенный Нолдорином , используя этот загруженный текст в качестве ввода.
  • Я написал новую цепочку Маркова в C #, используя экономичную реализацию Perl в Pike. Он генерирует текст по одному слову за раз.
  • Для эффективности вместо того, чтобы использовать чистую цепь Маркова для генерирования 1 ГБ текста по одному слову за раз, код генерирует случайный текст размером ~ 1 МБ, а затем многократно берет случайные сегменты этого и объединяет их вместе.

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...