Question

Je crée un fichier d'une taille spécifiée - Je ne me soucie pas de ce que les données est, bien au hasard serait bien. Actuellement, je fais ceci:

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

Ce n'est pas efficace ou même la bonne façon de s'y prendre. Toutes les solutions de performance supérieure?

Merci pour toutes les réponses.

Modifier

Ran quelques tests sur les méthodes suivantes pour un fichier 2Gb (temps en ms):

Méthode 1: Jon Skeet

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

N / A - Hors Exception mémoire pour le fichier 2Gb

Méthode 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

@ 128K - 24877, 20585, 20716

@ 8Kb - 30426, 22936, 22936

Méthode 3 - Hans Passant (Super rapide, mais les données ne sont pas aléatoires)

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

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

Était-ce utile?

La solution

Eh bien, très solution simple:

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

Un peu plus de mémoire Version efficace:)

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

Cependant, si vous faites cela plusieurs fois dans très succession rapide de créer une nouvelle instance de Random à chaque fois, vous pouvez obtenir des données en double. Voir mon aléatoire pour plus d'informations - vous pouvez éviter cela en utilisant System.Security.Cryptography.RandomNumberGenerator ... ou en réutilisant la même instance de Random plusieurs fois -. avec la mise en garde qu'il est thread-safe

Autres conseils

Il n'y a pas moyen plus rapide prenant alors l'avantage du support de fichiers fractionnés intégré dans NTFS, le système de fichiers pour Windows utilisé sur les disques durs. Ce code crée un fichier de gigaoctet en une fraction de seconde:

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

lecture, le fichier ne contient que des zéros.

Vous pouvez utiliser cette classe suivante créée par moi pour générer des chaînes aléatoires

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

    }

}

pour l'utilisation

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

La façon efficace de créer un grand fichier:

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

Toutefois, ce fichier sera vide (sauf pour le « test » à la fin). Pas clair ce qui est ce que vous exactement essaie de faire - gros fichier avec les données, ou tout simplement grand fichier. Vous pouvez modifier cela pour écrire peu certaines données dans le fichier aussi, mais sans le remplir complètement. Si vous ne voulez le fichier entier rempli de données aléatoires, la seule façon que je peux penser utilise des octets aléatoires de Jon ci-dessus.

Une amélioration serait de remplir un tampon de la taille souhaitée avec les données et le rinçage tout à la fois.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top