2009-12-10 16 views
34

Saniyeler içinde 1 ~ 2 GBs demek büyük bir kukla dosya oluşturmak istiyorum. Burada C# yazdık budur:C# saniye içinde büyük bir kukla dosyası oluşturma #

long FSS = din.TotalFreeSpace; 
long segments = FSS/10000; 
long last_seg = FSS % 10000; 
BinaryWriter br = new BinaryWriter(fs); 

for (long i = 0; i < segments; i++) 
{ 
    br.Write(new byte[10000]); 

    this.label2.Text = "segments write :" + i.ToString() + "\r\n" + "segments remain :" + ((segments-i)+1).ToString(); 
    Application.DoEvents(); 
} 
br.Write(new byte[last_seg]); 
this.label2.Text += "\r\nDone!"; 
br.Close(); 
din Disk Bilgisi olan

Bunlarla iyi

nesne:

file.writeallbytes("filename",new byte[a huge number]); 

ve durumunu gösteren başka bir yolu, aşağıdaki gibiydi iki yaklaşım, böyle büyük ama kukla bir dosya yazmak için 2 veya daha fazla dakika gibi bir şey alır. Bunu yapmak için başka daha hızlı bir yolu var mı?

+3

BinaryWriter, POCO'ları bir dosyanın .NET tarafından okunabileceği bir biçimde yazmak içindir, adından beklediğiniz şey bu değildir. Şaşırtıcı derecede basit bir çözüm için –

cevap

67

Basitçe, bir dosya oluşturmak ofset uygun bir şekilde büyük etmeye ve yazma tek bir bayt:

FileStream fs = new FileStream(@"c:\tmp\huge_dummy_file", FileMode.CreateNew); 
fs.Seek(2048L * 1024 * 1024, SeekOrigin.Begin); 
fs.WriteByte(0); 
fs.Close(); 

Bu amaçlar için iyi olmalı temelde öngörülemeyen içerikleri, bir 2GB dosya verecektir.

+1

+1 (kukla içeriğin tamam olduğunu varsayarak). – Abel

+0

, kukla dosyasını serin/flash/ram diskine yazmak için aynı süreyi alacak (neredeyse çıkarılabilir depolama alanını kullandığımı söylemeyi unutuyorum). –

+6

İçerikler tahmin edilemez: yazma işlemini yaptığınızda dosya sıfırlarla doldurulur. Bu yapılmadıysa, bir güvenlik sorunu olurdu. – RickNZ

0

Yanlış olabilirdim, ancak muhtemelen I/O yazma işleminde bir darboğaz olacağı için bu kadar büyük bir dosya oluşturmanın imkansız olduğunu göreceksiniz. Ancak, kodunuzda, Applciation.DoEvents üstündeki şeyler yavaşlayacak. Ayrıca, screenthis.label2.Text ='un yeniden boyanması, hafif bir yavaşlamaya neden olacaktır.

4

FileStream'a ihtiyacınız varsa, FileStream.SetLength'u kullanabilirsiniz. Bu size 2 GB uzunluğunda bir akış sağlayacaktır. Ardından, son baytı istediğiniz bir rastgele pozisyona yazabilirsiniz. Ancak içerik tanımsız olacaktır.

Aslında diskte bir dosya oluşturmaya çalışıyorsanız, evet, aslında içeriğini yazmanız gerekir. Ve evet, sabit diskler yavaş olacak; 1 GB/dk yazma hızı gibi bir şey tamamen saçma değildir. Üzgünüm - bu fizik!

60

sen benim bildiğim kadar hızlı arada ardından, içeriği önemli değilse bu - pratikte anlık geçerli:

private void CreateDummyFile(string fileName, long length) 
{ 
    using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) 
    { 
     fileStream.SetLength(length); 
    } 
} 
+0

+1 boyutunda bir dosya oluşturur. – Abel

+9

Merak etme, 'SetLength' ve 'Seek' +' WriteByte 'yaklaşımlarını test etti. * Seek * ile 512MB için 15 saniye sürdü, sadece * SetLength * ile yaklaşık 1 saniye sürdü. Her iki durumda da, birçok testten sonra bile dosyalar NULL ile doldurulmuştur (keyfi verilere karşılık olarak). Bu, temiz bir disk ya da kaputun altında bazı optimize edilmiş sıfır doldurulmuş oluşturma olup olmadığından emin değil. – Abel

+0

İyi nokta - çok ilginç. Bende aynı şeyi onaylayabilirim; Benim durumumda temiz bir disk olma ihtimalinin yüksek olduğunu tahmin ediyorum (dağınık ve tam sabit disk!) –

2

Neden bunu başarmak için BackgroundWorker sınıfını kullanın vermedi Durum raporunu belirtmek için ReportProgress yöntemine herhangi bir şey iletebilirsiniz. Bu yardımcı olur

 
     private BackgroundWorker bgWorker; 
     public Form1() 
     { 
      InitializeComponent(); 
      bgWorker = new BackgroundWorker(); 
      bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork); 
      bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged); 
      bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); 
      bgWorker.RunWorkerAsync(); 
     } 

     void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      this.label2.Text = "Done"; 
     } 

     void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      MyStatus myProgressStatus = (MyStatus)e.UserState; 
      this.label2.Text = string.Format("segments write : {0}" + Environment.Newline + "Segments Remain: {1}", myProgressStatus.iWritten, myProgressStatus.iRemaining); 
     } 

     void bgWorker_DoWork(object sender, DoWorkEventArgs e) 
     { 
      long FSS = din.TotalFreeSpace; 
       long segments = FSS/10000; 
       long last_seg = FSS % 10000; 
       BinaryWriter br = new BinaryWriter(fs); 

       for (long i = 0; i < segments; i++) 
       { 
        br.Write(new byte[10000]); 
bgWorker.ReportProgress(i.ToString(), new MyStatus(i, ((segments-i) + 1))); 

       } 
       br.Write(new byte[last_seg]); 
       br.Close(); 
     } 

public class MyStatus{ 
    public int iWritten; 
    public int iRemaining; 
    public MyStatus(int iWrit, int iRem){ 
    this.iWritten = iWrit; 
    this.iRemaining = iRem; 
    } 
} 
} 

Bu kaba bir taslak olduğunu ... Umut, Saygılarımızla, Tom: Aşağıdaki örneğe bakın.

İlgili konular