2012-01-22 27 views
6

Làm cách nào để đọc Luồng và đặt lại vị trí của nó về 0 ngay cả khi stream.CanSeek == false? Tôi cần một số công việc xung quanh.Cách đọc Luồng và đặt lại vị trí của nó về 0 ngay cả khi stream.CanSeek == false

+4

Nếu 'CanSeek == false', bất kỳ nỗ lực nào như vậy có thể dẫn đến ngoại lệ. – Oded

+5

@oded; tôi biết điều đó; thats lý do tại sao tôi hỏi câu hỏi – Faisal

Trả lời

9

Nếu kịch bản cho phép bạn thay thế luồng ban đầu, bạn có thể kiểm tra xem nó có hỗ trợ tìm kiếm hay không, đọc nội dung và đưa chúng vào một MemoryStream mới.

static string PeekStream(ref Stream stream) 
{ 
    string content; 
    var reader = new StreamReader(stream); 
    content = reader.ReadToEnd(); 

    if (stream.CanSeek) 
    { 
     stream.Seek(0, SeekOrigin.Begin); 
    } 
    else 
    { 
     stream.Dispose(); 
     stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); 
    } 

    return content; 
} 

Điều trên là không hiệu quả vì nó phải cấp phát bộ nhớ gấp đôi kích thước nội dung của bạn. Đề xuất của tôi sẽ là điều chỉnh các phần của mã mà bạn đang truy cập luồng (sau khi đã đọc tất cả nội dung của nó) để làm cho chúng truy cập vào bản sao nội dung được lưu trữ thay thế. Ví dụ:

string content; 
using (var reader = new StreamReader(stream)) 
    content = reader.ReadToEnd(); 

// Process content here. 

string line; 
using (var reader = new StringReader(content)) 
    while ((line = reader.ReadLine()) != null) 
     Console.WriteLine(line); 

Kể từ khi StringReader chỉ đọc từ content chuỗi của bạn, bạn sẽ không lãng phí bộ nhớ tạo bản sao dự phòng dữ liệu của bạn.

+0

Cách tiếp cận này là chính xác cho đến khi bạn có dữ liệu rất lớn. Nếu bạn có một số gigabyte thì bạn nên khởi động lại luồng của mình tốt hơn. Theo tôi, mục đích của phát trực tuyến là không lưu trữ tất cả dữ liệu bạn đang xử lý. –

+0

Bạn nói đúng về 'MemoryStream' không phù hợp với dữ liệu lớn. Việc lưu trữ hay khởi tạo lại luồng phụ thuộc vào kịch bản. Ví dụ: nếu bạn đang xử lý dữ liệu được tải xuống từ Internet và bạn cần phải đọc nhiều lần, thì tốt hơn là lưu trữ dữ liệu cục bộ (trong bộ nhớ hoặc trong tệp tạm thời) để tải xuống lại. – Douglas

5

Sử dụng triển khai Luồng khác hỗ trợ tìm kiếm. Nếu Stream.CanSeek trả về false, thì việc triển khai đó khẳng định rằng nó không hỗ trợ tìm kiếm.

Đối tượng MemoryStream không hỗ trợ tìm kiếm. Bạn có thể sao chép luồng tùy ý vào MemoryStream bằng cách sử dụng thứ gì đó như thế này và luồng kết quả sẽ hỗ trợ tìm kiếm, ví dụ: bạn có thể đặt lại vị trí thành 0 và đọc từ vị trí liên tục.

MemoryStream CopyStreamToMemory(Stream inputStream) 
{ 
    MemoryStream ret = new MemoryStream(); 
    const int BUFFER_SIZE = 1024; 
    byte[] buf = new byte[BUFFER_SIZE]; 

    int bytesread = 0; 
    while ((bytesread = inputStream.Read(buf, 0, BUFFER_SIZE)) > 0) 
     ret.Write(buf, 0, bytesread); 

    ret.Position = 0; 
    return ret; 
} 

Tất nhiên, nếu luồng của bạn đọc dữ liệu không thay đổi, bạn có thể chỉ cần bỏ luồng cũ và tạo luồng mới đọc cùng một dữ liệu.

Các vấn đề liên quan