Domanda

Io sono la creazione di un file di un formato specificato - Non mi importa quali sono i dati in esso, anche se sarebbe bello casuale. Attualmente sto facendo questo:

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

Questa non è efficiente o anche il modo giusto per andare a questo proposito. Eventuali soluzioni più elevato di prestazioni?

Grazie per tutte le risposte.

Modifica

Ran alcuni test sui seguenti metodi per un file da 2 Gb (tempo in ms):

Metodo 1: Jon Skeet

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

N / A - Memoria esaurita Eccezione per file 2Gb

Metodo 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 - 45.868, 23.283, 23.346

@ 128K - 24.877, 20.585, 20.716

@ 8Kb - 30.426, 22.936, 22.936

Metodo 3 - Hans Passant (Super Fast ma i dati non è casuale)

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

257, 287, 3, 3, 2, 3 ecc.

È stato utile?

Soluzione

Beh, un molto soluzione semplice:

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

Un po 'più di memoria versione efficiente:)

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

Tuttavia, se si esegue questa operazione più volte in molto rapida successione la creazione di una nuova istanza di Random ogni volta, è possibile ottenere dati duplicati. Vedi articolo mia sulla casualità per ulteriori informazioni - si potrebbe evitare questo utilizzando noreferrer System.Security.Cryptography.RandomNumberGenerator ... o riutilizzando la stessa istanza di Random più volte -. con l'avvertenza che non è thread-safe

Altri suggerimenti

non più veloce Non c'è modo quindi approfittando del supporto per i file sparse integrato in NTFS, il file system per Windows utilizzato sui dischi rigidi. Questo codice crea un file di un gigabyte in una frazione di secondo:

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

Quando lesse, il file contiene solo zeri.

È possibile utilizzare questa seguente classe creata da me per generare stringhe casuali

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

    }

}

per l'utilizzo

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

Il modo più efficace per creare un file di grandi dimensioni:

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

Tuttavia questo file sarà vuoto (tranne che per il "test" alla fine). Non è chiaro che cosa si tratta esattamente si sta cercando di fare - file di grandi dimensioni con i dati, o solo file di grandi dimensioni. È possibile modificare questo a dare scarsamente alcuni dati nel file anche, ma senza riempirlo completamente. Se si vuole l'intero file pieno di dati casuali, quindi l'unico modo che posso pensare è utilizzato a caso byte da Jon sopra.

Un miglioramento sarebbe di riempire un buffer di dimensione desiderata con i dati e lavando tutto in una volta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top