Pregunta

Estoy creando un archivo de un tamaño especificado - No me importa qué datos hay en él, aunque al azar sería bueno. Actualmente estoy haciendo esto:

        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();
            }
        }

Esto no es eficiente o incluso la manera correcta de hacerlo. Cualquier solución de mayor rendimiento?

Gracias por todas las respuestas.

Editar

Ran algunas pruebas en los siguientes métodos para un archivo de 2 GB (tiempo en ms):

Método 1: Jon Skeet

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

N / A - Fuera de excepción de memoria de 2 Gb de archivos

Método 2: Jon Skeet

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 - 45868, 23283, 23346

@ 128 K - 24877, 20585, 20716

@ 8 Kb - 30426, 22936, 22936

Método 3 - Hans Passant (súper rápido pero los datos no es al azar)

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

257, 287, 3, 3, 2, 3 etc.

¿Fue útil?

Solución

Bueno, un muy solución simple:

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

Un poco más de memoria versión eficiente:)

// 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);
    }
}

Sin embargo, si haces esto varias veces en muy sucesión rápida creación de una nueva instancia de Random cada vez, se pueden obtener los datos por duplicado. Véase el artículo de mi en la aleatoriedad para más información - se puede evitar esto usando noreferrer System.Security.Cryptography.RandomNumberGenerator ... o mediante la reutilización de la misma instancia de Random varias veces -., con la advertencia de que no es seguro para subprocesos

Otros consejos

Hay no más rápido su camino a continuación, aprovechando el soporte de archivos escasa integrado en NTFS, el sistema de archivos para Windows utiliza en los discos duros. Este código crea un archivo de un gigabyte en una fracción de segundo:

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);
        }
    }
}

Cuando se lee, el archivo contiene sólo ceros.

Se puede utilizar esta clase siguiente creado por mí para generar cadenas aleatorias

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();

    }

}

para usar

 int length = 10;
        string randomString = randomStringGenerator.Generate(length);

La forma más eficiente de crear un archivo de gran tamaño:

    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();

Sin embargo, este archivo estará vacío (a excepción de la "prueba" al final). No es claro qué es exactamente lo que está tratando de hacer - archivo de gran tamaño con datos o archivo que acaba grande. Usted puede modificar esto para escribir escasamente algunos datos en el archivo también, pero sin llenarla por completo. Si usted quiere todo el archivo lleno de datos aleatorios, entonces la única forma en que puede pensar es aleatoria usando bytes de Jon anteriormente.

Una mejora sería llenar una memoria intermedia del tamaño deseado con los datos y el lavado de todo a la vez.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top