2016-04-11 21 views
2

Bir veri okuyucu akışı oluşturdum ve sonuçları bir dosyaya yazmaya çalışıyorum. Bu tablo potansiyel olarak milyonlarca kayıt döndürebileceğinden, birden fazla dosyaya yazmak istedim, böylece sorunları olmadan bir metin düzenleyicide açabildim. Dosya çok büyük olduğu için metin editörü çöküyor. İşte kabaca benim şu an sahip olduğum şey.SqlDataReader'dan Birden Çok Dosya Yazma

using (var connection = new SqlConnection(connectionString)) 
using (var stream = new FileStream("directoryLocation", FileMode.Create)) 
{ 
    SqlCommand command = connection.CreateCommand(); 
    command.CommandText = "Select * from tblTemp"; 
    connection.Open(); 

    using(SqlDataReader reader = command.ExecuteReader()) 
    { 
     var tableName = "tblTemp"; 
     var fileName = tableName + ".txt"; 
     var recordCount = 0; 
     var fileCount = 0; 

     using (StreamWriter writer = new StreamWriter(stream.Open())) 
     { 
      while(reader.Read()) 
      { 
       if(recordCount == 500000) 
       { 
        // Right here. Need to figure out how to close old file start new 
        recordCount = 0; 
        writer.Close(); 

        fileName = tableName + "_" + (++fileCount).ToString() + ".txt"; 
        writer = new StreamWriter(fileName); // I know this doesn't work. Just sudo code 
       } 

       recordCount++; 
       writer.WriterLine(recordInfo); // recordInfo is sudo code as well 
      } 
     } 
    } 
} 

Bunu açıp her kayıt için dosyaya bağlantıyı kapatmak çünkü okuyucu döngüye kullanarak yazar deyimi taşımak istemiyoruz. Konumumu okuyucuda nasıl tutacağımı ve sadece gerektiğinde dosyaları açıp kapatacağınıza dair herhangi bir fikir var mı?

+0

Bunu yaptığım gibi bir fikrim vardı. Yazan yazar bloğu yerine StreamWriter'i kendim yönetebilir miyim? StreamWriter writer = new StreamWriter (stream.Open()) 'gibi, daha sonra bağlantıyı yönetmek için son olarak blokları denediniz. – adam

+0

Neden bir FileSteam ve bir StreamWriter'e ihtiyacınız var. Yeni bir StreamWriter içinde bir stream.Open() koymak size aynı anda iki açılır verir ve sonra kapatmaya ve yeniden açmaya çalıştığınızda sorunlara neden olur. – jdweng

cevap

2

Siz varsınız. Ayrı FileStream'e ihtiyacınız yok. Bir öncekini gerektiği gibi attığınız sürece, döngünüzün ortasında yeni bir StreamWriter oluşturmak tamamdır.

using (var connection = new SqlConnection(connectionString)) 
{ 
    SqlCommand command = connection.CreateCommand(); 
    command.CommandText = "Select * from tblTemp"; 
    connection.Open(); 

    using(SqlDataReader reader = command.ExecuteReader()) 
    { 
     var tableName = "tblTemp"; 
     var fileName = tableName + ".txt"; 
     var recordCount = 0; 
     var fileCount = 0; 

     StreamWriter writer = null; 
     try 
     { 
      while (reader.Read()) 
      { 
       if (writer == null || recordCount == 500000) 
       { 
        recordCount = 0; 

        // Close the previous file if it is open... 
        if (writer != null) 
        { 
         writer.Close(); 
         writer.Dispose(); 
        } 

        fileName = tableName + "_" + (++fileCount).ToString() + ".txt"; 

        // Open the new file... 
        writer = new StreamWriter(fileName); 
       } 

       recordCount++; 
       writer.WriterLine(recordInfo); // recordInfo is sudo code as well 
      } 
     } 
     finally 
     { 
      // Make sure the file gets closed... 
      if (writer != null) 
      { 
       writer.Dispose(); 
      } 
     } 
    } 
} 
+0

Teşekkürler bayım. Şu anda kodumu önerilerinizle yeniden onaylıyorum ve nasıl olduğunu bilmenizi sağlayacağım. – adam

0

Şahsen, TextWriter özel bir geçersiz kılma kullanarak kod dışına dosya adları haddeleme mantığını-ikiliye de olacaktır.

public class RollingFileWriter : TextWriter 
{ 
    private readonly string _filenamePrefix; 
    private readonly string _fileNameSuffix; 
    private readonly int _maxRecordCount; 
    private Stream _innerStream; 
    private int _recordCount = 0; 
    private int _fileCounter = 0; 

    public RollingFileWriter(string filenamePrefix, string fileNameSuffix = ".txt", int maxRecordCount = 500000) 
    { 
     _filenamePrefix = filenamePrefix; 
     _fileNameSuffix = fileNameSuffix; 
     _maxRecordCount = maxRecordCount; 

     _innerStream = new FileStream(
      _filenamePrefix + "_" + _fileCounter.ToString() + _fileNameSuffix, 
      FileMode.Create); 
    } 

    public override Encoding Encoding 
    { 
     get { return Encoding.UTF8; } 
    } 

    public override void Write(char value) 
    { 
     _innerStream.Write(Encoding.GetBytes(new[] { value }), 0, 1); 
    } 

    public override void WriteLine(string value) 
    { 
     if (++_recordCount == _maxRecordCount) 
     { 
      SwitchStreams(); 
     } 
     base.WriteLine(value); 
    } 

    private void SwitchStreams() 
    { 
     _innerStream.Close(); 
     _innerStream.Dispose(); 

     _innerStream = new FileStream(
      _filenamePrefix + "_" + (++_fileCounter).ToString() + _fileNameSuffix, 
      FileMode.Create); 
     _recordCount = 0; 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      _innerStream.Dispose(); 
     } 
    } 
} 
Sonra

Eğer dış FileStream kurtulabilirsiniz ve: tamamen denenmemiş Böyle bir şey, muhtemelen güvenli, (! Şu anda sadece bir kerede bir karakter yazacağım) verimsiz ve muhtemel arabası kodunu iplik değil İç StreamWriter'u RollingFileWriter ile değiştirin ve tüm diğer mantığı döngüden kaldırın.