2009-02-10 26 views
5

Tôi có danh sách tệp và tôi cần đọc từng tệp theo thứ tự cụ thể thành byte [] của một kích thước nhất định. Điều này trong chính nó không phải là một vấn đề cho một tập tin duy nhất, một đơn giản trong khi ((got = fs.Read (piece, 0, pieceLength))> 0) được công việc làm hoàn toàn tốt đẹp. Phần cuối cùng của tệp có thể nhỏ hơn mong muốn, điều đó là tốt.Có cách tích hợp để xử lý nhiều tệp dưới dạng một luồng không?

Bây giờ, có một chút phức tạp: Nếu tôi có nhiều tệp, tôi cần có một luồng liên tục, có nghĩa là nếu phần cuối cùng của tệp nhỏ hơn đoạn mảnh đó, thì tôi cần đọc (pieceLength-got) của tệp tiếp theo và sau đó tiếp tục cho đến khi kết thúc tệp cuối cùng. Vì vậy, về cơ bản, cho các tập tin X, tôi sẽ luôn luôn đọc miếng đó là chính xác mảnh dài, ngoại trừ phần cuối cùng của tập tin cuối cùng, có thể nhỏ hơn.

Tôi tự hỏi liệu đã có thứ gì đó được tích hợp trong .net (3.5 SP1) không. Cách tiếp cận hiện tại của tôi là tạo một Lớp có danh sách các tệp và sau đó hiển thị hàm Read(byte[] buffer, long index, long length), tương tự như FileStream.Read(). Điều này nên được khá thẳng về phía trước vì tôi không phải thay đổi mã gọi điện thoại của tôi mà đọc dữ liệu, nhưng trước khi tôi phát minh lại bánh xe tôi chỉ muốn kiểm tra lại rằng bánh xe chưa được xây dựng vào BCL.

Cảm ơn :)

Trả lời

6

Tôi không tin có bất cứ điều gì trong khuôn khổ, nhưng tôi khuyên bạn nên làm cho nó linh hoạt hơn một chút - lấy một IEnumerable<Stream> trong constructor của bạn, và xuất phát từ Stream mình. Sau đó, để có được file suối bạn có thể (giả sử C# 3.0) chỉ làm:

Stream combined = new CombinationStream(files.Select(file => File.Open(file)); 

Các "sở hữu" một phần là hơi khó hiểu ở đây - ở trên sẽ cho phép các dòng kết hợp để có quyền sở hữu của bất kỳ dòng nó đọc từ, nhưng bạn có thể không muốn nó phải lặp qua tất cả các phần còn lại của luồng và đóng tất cả nếu đó là đóng sớm.

+0

Đó là thực sự khá một cách tốt, tôi chỉ không chắc chắn nhưng nếu tôi muốn triển khai luồng của riêng tôi. Thay vì một số điện thoại có thể đọc được là , một cũng có thể hoạt động, bởi vì sau đó, Kết hợp của tôi có toàn quyền kiểm soát "các luồng bên trong". Tôi sẽ nghĩ về cách tiếp cận nào phù hợp nhất với tôi. –

3

Đây là những gì tôi nghĩ ra dựa trên ý tưởng của @jon skeet.

Nó chỉ thực hiện Đọc là khá đủ cho tôi. (nhưng tôi không cần trợ giúp khi triển khai phương pháp BeginRead/EndRead.) Đây là mã đầy đủ chứa cả đồng bộ hóa và không đồng bộ - Đọc và Bắt đầuRead/EndRead - https://github.com/prabirshrestha/CombinationStream/blob/master/ src/CombinationStream-Net20/CombinationStream.cs chuyển đến https://github.com/facebook-csharp-sdk/CombinationStream/blob/master/src/CombinationStream-Net20/CombinationStream.cs

internal class CombinationStream : System.IO.Stream 
{ 
    private readonly System.Collections.Generic.IList<System.IO.Stream> _streams; 
    private int _currentStreamIndex; 
    private System.IO.Stream _currentStream; 
    private long _length = -1; 
    private long _postion; 

    public CombinationStream(System.Collections.Generic.IList<System.IO.Stream> streams) 
    { 
     if (streams == null) 
     { 
      throw new System.ArgumentNullException("streams"); 
     } 

     _streams = streams; 
     if (streams.Count > 0) 
     { 
      _currentStream = streams[_currentStreamIndex++]; 
     } 
    } 

    public override void Flush() 
    { 
     if (_currentStream != null) 
     { 
      _currentStream.Flush(); 
     } 
    } 

    public override long Seek(long offset, System.IO.SeekOrigin origin) 
    { 
     throw new System.InvalidOperationException("Stream is not seekable."); 
    } 

    public override void SetLength(long value) 
    { 
     this._length = value; 
    } 

    public override int Read(byte[] buffer, int offset, int count) 
    { 
     int result = 0; 
     int buffPostion = offset; 

     while (count > 0) 
     { 
      int bytesRead = _currentStream.Read(buffer, buffPostion, count); 
      result += bytesRead; 
      buffPostion += bytesRead; 
      _postion += bytesRead; 

      if (bytesRead <= count) 
      { 
       count -= bytesRead; 
      } 

      if (count > 0) 
      { 
       if (_currentStreamIndex >= _streams.Count) 
       { 
        break; 
       } 

       _currentStream = _streams[_currentStreamIndex++]; 
      } 
     } 

     return result; 
    } 

    public override long Length 
    { 
     get 
     { 
      if (_length == -1) 
      { 
       _length = 0; 
       foreach (var stream in _streams) 
       { 
        _length += stream.Length; 
       } 
      } 

      return _length; 
     } 
    } 

    public override long Position 
    { 
     get { return this._postion; } 
     set { throw new System.NotImplementedException(); } 
    } 
    public override void Write(byte[] buffer, int offset, int count) 
    { 
     throw new System.InvalidOperationException("Stream is not writable"); 
    } 

    public override bool CanRead 
    { 
     get { return true; } 
    } 

    public override bool CanSeek 
    { 
     get { return false; } 
    } 

    public override bool CanWrite 
    { 
     get { return false; } 
    } 
} 

Cũng có sẵn như là một gói NuGet

Install-Package CombinationStream 
Các vấn đề liên quan