Создание случайного файла в C # - PullRequest
21 голосов
/ 13 декабря 2010

Я создаю файл указанного размера - мне все равно, какие данные в нем, хотя случайным было бы неплохо.В настоящее время я делаю это:

        var sizeInMB = 3; // Up to many Gb
        using (FileStream stream = new FileStream(fileName, FileMode.Create))
        {
            using (BinaryWriter writer = new BinaryWriter(stream))
            {
                while (writer.BaseStream.Length <= sizeInMB * 1000000)
                {
                    writer.Write("a"); //This could be random. Also, larger strings improve performance obviously
                }
                writer.Close();
            }
        }

Это не эффективный или даже неправильный способ сделать это.Какие-нибудь решения с более высокой производительностью?

Спасибо за все ответы.

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

Выполнены некоторые тесты для следующих методов для файла 2 ГБ (время в мс):

Метод 1: Джон Скит

byte[] data = new byte[sizeInMb * 1024 * 1024];
Random rng = new Random();
rng.NextBytes(data);
File.WriteAllBytes(fileName, data);

N / A - Исключение нехватки памяти для файла 2 ГБ

Метод 2: Джон Скит

byte[] data = new byte[8192];
Random rng = new Random();
using (FileStream stream = File.OpenWrite(fileName))
{
    for (int i = 0; i < sizeInMB * 128; i++)
    {
         rng.NextBytes(data);
         stream.Write(data, 0, data.Length);
    }
}

@ 1K- 45 868, 23 283, 23 346

@ 128K - 24 877, 20 585, 20 716

@ 8Kb - 30 426, 22 936, 22 936

Метод 3 - Ганс Пассант (супер быстрый, но данныене случайно)

using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
    fs.SetLength(sizeInMB * 1024 * 1024);
}

257, 287, 3, 3, 2, 3 и т. д.

Ответы [ 5 ]

36 голосов
/ 13 декабря 2010

Ну, очень простое решение:

byte[] data = new byte[sizeInMb * 1024 * 1024];
Random rng = new Random();
rng.NextBytes(data);
File.WriteAllBytes(fileName, data);

Чуть более эффективная память:)

// Note: block size must be a factor of 1MB to avoid rounding errors :)
const int blockSize = 1024 * 8;
const int blocksPerMb = (1024 * 1024) / blockSize;
byte[] data = new byte[blockSize];
Random rng = new Random();
using (FileStream stream = File.OpenWrite(fileName))
{
    // There 
    for (int i = 0; i < sizeInMb * blocksPerMb; i++)
    {
        rng.NextBytes(data);
        stream.Write(data, 0, data.Length);
    }
}

Однако, если вы сделаете это несколько раз в очень быстрой последовательности, каждый раз создавая новый экземпляр Random, вы можете получить дубликаты данных. См. Мою статью о случайности для получения дополнительной информации - вы можете избежать этого, используя System.Security.Cryptography.RandomNumberGenerator ... или повторно используя один и тот же экземпляр Random несколько раз - с оговоркой, что это не потокобезопасен.

12 голосов
/ 13 декабря 2010

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

using System;
using System.IO;

class Program {
    static void Main(string[] args) {
        using (var fs = new FileStream(@"c:\temp\onegigabyte.bin", FileMode.Create, FileAccess.Write, FileShare.None)) {
            fs.SetLength(1024 * 1024 * 1024);
        }
    }
}

При чтении файл содержит только нули.

1 голос
/ 13 декабря 2010

Вы можете использовать этот следующий класс, созданный мной для генерации случайных строк

using System;
using System.Text;

public class RandomStringGenerator
{
    readonly Random random;

    public RandomStringGenerator()
    {
        random = new Random();
    }
    public string Generate(int length)
    {
        if (length < 0)
        {
            throw new ArgumentOutOfRangeException("length");
        }
        var stringBuilder = new StringBuilder();

        for (int i = 0; i < length; i++)
        {
            char ch = (char)random.Next(0,255 );
            stringBuilder.Append(ch);
        }

        return stringBuilder.ToString();

    }

}

для использования

 int length = 10;
        string randomString = randomStringGenerator.Generate(length);
0 голосов
/ 13 декабря 2010

Эффективный способ создания большого файла:

    FileStream fs = new FileStream(@"C:\temp\out.dat", FileMode.Create);
    fs.Seek(1024 * 6, SeekOrigin.Begin);
    System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
    fs.Write(encoding.GetBytes("test"), 0, 4);
    fs.Close();

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

0 голосов
/ 13 декабря 2010

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

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