2009-11-24 31 views
8

Nếu tôi sử dụng một FileStream để tạo StreamReader, StreamReader sẽ đóng khi tôi đóng FileStream hay tôi cũng sẽ cần đóng StreamReader không?Đóng một FileStream có đóng StreamReader không?

public void ReadFile() 
{ 
    var file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read); 
    var reader = new StreamReader(file); 

    try 
    { 
     txtFile.Text = reader.ReadToEnd(); 
    } 
    catch (Exception) 
    { 
     throw; 
    } 
    finally 
    { 
     file.Close(); 
    } 
} 
+0

bản sao có thể có của [Không xử lý luồng đóng luồng?] (Http://stackoverflow.com/questions/1065168/does-disposing-streamreader-close-the-stream) – mafu

Trả lời

7

Thực chất là có. Bạn không thực sự phải đóng một StreamReader. Nếu bạn làm thế, tất cả những gì nó làm là đóng luồng cơ bản.

@Bruno làm cho một điểm tốt về việc đóng trình bao bọc ngoài nhất. Cách tốt nhất là đóng luồng ngoài cùng nhất và để luồng gần bên dưới để đảm bảo tất cả các tài nguyên được phát hành đúng cách.

Từ Reflector ...

public class StreamReader : TextReader 
{ 
    public override void Close() 
    { 
     this.Dispose(true); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     try 
     { 
      if ((this.Closable && disposing) && (this.stream != null)) 
      { 
       this.stream.Close(); 
      } 
     } 
     finally 
     { 
      if (this.Closable && (this.stream != null)) 
      { 
       this.stream = null; 
       this.encoding = null; 
       this.decoder = null; 
       this.byteBuffer = null; 
       this.charBuffer = null; 
       this.charPos = 0; 
       this.charLen = 0; 
       base.Dispose(disposing); 
      } 
     } 
    } 
} 
+0

IMO, đây thực sự là một thực tế không tốt. Trong tương lai, các nhà thiết kế BCL có thể chọn để thêm một số cấu trúc bổ sung cần phải được xử lý ... –

+0

@bruno conde: bản thân bạn nói rằng trình bao bọc hàng đầu nên được xử lý. StreamReader là trình bao bọc hàng đầu cho FileReader. Vấn đề ở đâu? – Kamarey

+0

@Kamarey, vấn đề là OP chỉ xử lý FileStream. –

0

số Điều tốt nhất để làm là đóng chúng theo thứ tự ngược mà bạn đã mở chúng.

6

Không. Bạn nên đóng số reader. Trong thực tế, điều này có thể không trình bày bất kỳ vấn đề nào, nhưng StreamReader có thể thêm một số chi phí mà có thể cần phải được làm sạch. Vì vậy, bạn nên luôn đóng trình bao bọc hàng đầu nhất.

2

Bạn không cần đóng StreamReader vì nó không sở hữu bất kỳ tài nguyên không được quản lý nào. Đóng FileStream là đủ. Bạn có thể viết lại mã của bạn với using như thế này:

public void ReadFile() 
{ 
    using (var file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read)) 
    { 
     txtFile.Text = new StreamReader(file).ReadToEnd(); 
    } 
} 

Nói chung nếu bạn có nghi ngờ nó là tốt nhất để được an toàn và Vứt bỏ tất cả đối tượng IDisposable khi bạn đã hoàn thành việc sử dụng chúng.

public void ReadFile() 
{ 
    using (FileStream file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read)) 
    { 
     using (StreamReader streamReader = new StreamReader(file)) 
     { 
      txtFile.Text = streamReader.ReadToEnd(); 
     } 
    } 
} 
+0

"Đang sử dụng" tôi biết các mục đích của đối tượng, điều này có đảm bảo rằng kết nối gần đúng không? – norlando

+0

@norlando Có nó mặc dù nói chung nó là xuống đến từng lớp thực hiện cá nhân về những gì xảy ra trên một vứt bỏ. Trong trường hợp các luồng chuẩn, nó theo sau các bước logic của việc xóa các bộ đệm, đóng luồng và xử lý bất kỳ đối tượng được quản lý và không được quản lý nào. –

6

Bạn cũng có thể chỉ cần sử dụng các phương pháp File.ReadAllText:

txtFile.Text = File.ReadAllText(@"c:\file.txt"); 
+0

Cách thức hoạt động? Liệu nó chỉ mở một kết nối, đọc toàn bộ tập tin, sau đó đóng tập tin? – norlando

+0

Có, nó thực hiện chính xác điều đó. –

0

Dường như với tôi rằng cách tốt nhất để làm tổng thể này sẽ có FileStream chỉ đóng chính nó. Nó không ngầm có kiến ​​thức về bất cứ điều gì tồn tại trong một lớp trên chính nó, do đó, nó có hiệu quả là một lỗi cho nó để làm bất cứ điều gì mà sẽ ảnh hưởng đến những lớp cao hơn.

Có nói rằng, các cấu trúc cấp cao không nên axiomatically giả gì về bất kỳ lớp cơ bản được cung cấp là tốt, hoặc nếu họ làm như vậy, họ nên làm như vậy một cách rõ ràng:

1) Nếu nó đã được tạo ra từ một luồng hiện tại, thì cấu trúc cấp cao hơn sẽ có thể đóng ĐỘC QUYỀN luồng cơ bản (chỉ xử lý bất kỳ tài nguyên nào được phân bổ để sử dụng riêng) hoặc đóng BAO GỒM luồng cơ bản. Đây nên là hai cuộc gọi hàm riêng biệt, ví dụ Close() và CloseSelf() (nếu điều này được thực hiện theo cách tương thích ngược với mã hiện có).

2) Nếu nó không được tạo từ luồng hiện có (nghĩa là hàm tạo phải tạo luồng cơ bản), thì đóng cấu trúc cấp cao hơn cũng buộc luồng cơ bản đóng lại, vì trong trường hợp đó luồng cơ bản là một phần ngầm của cấu trúc cấp cao hơn. Trong trường hợp này, CloseSelf() đơn giản gọi Close().

Có vẻ như lãng phí khi triển khai các lớp này theo cách thực hiện.Nếu bạn định sử dụng cùng một tệp cho đầu vào nối tiếp (ví dụ) và đầu ra nối tiếp, bạn bị hệ thống buộc phải coi nó là hai thực thể riêng biệt nếu bạn muốn truy cập vào chức năng cấp cao hơn của các lớp hậu duệ. Cách khác của bạn là gắn bó với cấu trúc mức thấp hơn và tự thực hiện chức năng cấp cao hơn - thực hiện lại hiệu quả các phiên bản đặc biệt của các lớp con cháu đã tồn tại của bạn.

Nếu nó được thực hiện như mô tả ở trên, thì chức năng điển hình sẽ đơn giản như hiện nay, nhưng đối với các ứng dụng phức tạp hơn, ứng dụng sẽ duy trì khả năng đặt một khóa trên một tệp và tái sử dụng nó yêu cầu khi được yêu cầu trái ngược với việc phải từ bỏ khóa và tất cả các tài nguyên liên quan và sau đó ngay lập tức phân bổ lại tất cả chúng - thêm chi phí và phân mảnh bộ nhớ vào hệ thống mà không có bất kỳ lý do hợp lệ nào.

Trong điều kiện hiện tại, tuy nhiên, điều đúng là rõ ràng. FileStream không thể được giả định để biết bất cứ điều gì về bất kỳ đối tượng nó trở thành một phần của, vì vậy bạn phải đóng cấu trúc bao ngoài cùng. Điều này áp dụng bất kể nó có hoạt động theo cách nào hay không, như Bruno và cộng sự đã lưu ý, và vì lý do họ đưa ra - tính tương thích. Giả định là tuyệt vời-granddy của các lỗi xấu nhất.

0

Một điều thú vị là việc đóng StreamReader hoặc trình ghi sẽ ảnh hưởng đến trạng thái đọc/ghi của FileStream đang sở hữu. Điều này có nghĩa là bạn không thể sử dụng StreamReader và sau đó là một StreamWriter sử dụng cùng một luồng.

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