web-dev-qa-db-ja.com

C#でランダムファイルを作成する

指定されたサイズのファイルを作成しています。ランダムであればいいのですが、どのデータが含まれているかは関係ありません。現在私はこれを行っています:

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

これは効率的ではなく、それを実行するための正しい方法でもありません。より高性能なソリューションはありますか?

すべての答えをありがとう。

編集

2Gbファイル(ミリ秒単位の時間)に対して次のメソッドでいくつかのテストを実行しました。

方法1:ジョンスキート

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

該当なし-2Gbファイルのメモリ不足例外

方法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-HansPassant(超高速ですが、データはランダムではありません)

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

257、287、3、3、2、3など。

23
Jason

さて、veryの簡単な解決策:

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

ただし、これをveryの高速連続で数回実行して、毎回Randomの新しいインスタンスを作成すると、データが重複する可能性があります。詳細については、私の ランダム性に関する記事 を参照してください System.Security.Cryptography.RandomNumberGenerator ...またはRandomの同じインスタンスを複数回再利用することにより、スレッドセーフではないことに注意してください。

39
Jon Skeet

ハードディスクで使用されるWindows用のファイルシステムであるNTFSに組み込まれているスパースファイルのサポートを利用するよりも速い方法はありません。このコードは、1ギガバイトのファイルをほんの一瞬で作成します。

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

読み取られると、ファイルにはゼロのみが含まれます。

13
Hans Passant

私が作成した次のクラスを使用して、ランダムな文字列を生成できます

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);
1
Serghei

大きなファイルを作成する効率的な方法:

    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
MK.