質問
指定されたサイズのファイルを作成しています - ランダムがいいのですが、どのデータが含まれているかは気にしません。現在、私はこれをやっています:
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ファイルの次の方法でいくつかのテストを実行しました(MSでの時間):
方法1:Jon Skeet
byte[] data = new byte[sizeInMb * 1024 * 1024];
Random rng = new Random();
rng.NextBytes(data);
File.WriteAllBytes(fileName, data);
n/a-2GBファイルのメモリからの例外
方法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
方法3 -Hans Passant(超高速ですが、データはランダムではありません)
using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
fs.SetLength(sizeInMB * 1024 * 1024);
}
257、287、3、3、2、3など
解決
まあ、a 非常に 簡単な解決策:
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
複数回 - スレッドセーフではないという警告があります。
他のヒント
ハードディスクで使用されるWindowsのファイルシステムであるNTFSに組み込まれたスパースファイルサポートを利用して、より速い方法はありません。このコードは、1秒間に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);
}
}
}
読み取ると、ファイルにはゼロのみが含まれます。
私が作成した次のクラスを使用することができます。
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);
大きなファイルを作成する効率的な方法:
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のランダムバイトを使用することです。
改善は、目的のサイズのバッファーをデータに埋めて一度に洗い流すことです。