2009-11-24 2 views
8

Если я использую FileStream для создания StreamReader, будет ли StreamReader закрываться, когда я закрою FileStream или мне нужно будет закрыть StreamReader?Закрытие FileStream закрывает StreamReader?

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

Возможный дубликат [Устраняет ли поток streamstreamer поток?] (Http://stackoverflow.com/questions/1065168/does-disposing-streamreader-close-the-stream) – mafu

ответ

7

По существу да. Фактически вам не нужно закрывать StreamReader. Если вы это сделаете, все, что он делает, закрывает базовый поток.

@Bruno делает хороший вывод о закрытии внешней оболочки. Хорошая практика заключается в том, чтобы закрыть самый внешний поток и позволить ему закрыть основные потоки, чтобы гарантировать, что все ресурсы будут выпущены должным образом.

С рефлектором ...

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, это действительно плохая практика. В будущем дизайнеры BCL могут предпочесть добавить некоторые дополнительные структуры, которые должны быть удалены ... –

+0

@bruno conde: вы сами сказали, что верхняя часть обертки должна быть удалена. StreamReader - это верхняя оболочка для FileReader. В чем проблема? – Kamarey

+0

@ Kamarey, проблема в том, что OP только распоряжается FileStream. –

0

No. Самое лучшее, что нужно сделать, это закрыть их в обратном порядке, что вы открыли их.

6

Нет. Вместо этого следует закрыть reader. На практике это может не представлять никаких проблем, но StreamReader может добавить некоторые накладные расходы, которые, возможно, потребуется очистить. Поэтому вы должны всегда закрывать самую верхнюю оболочку.

2

Вам не нужно закрывать StreamReader, поскольку он не владеет неуправляемыми ресурсами. Достаточно закрыть FileStream. Вы можете переписать код с using, как это:

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

В общем, если у вас есть сомнения, лучше, чтобы быть безопасным и утилизировать все IDisposable объекты после завершения их использования.

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

«Использование» Я знаю, что у него есть объект, это также гарантирует, что соединение тоже близко? – norlando

+0

@norlando Да, хотя это происходит, хотя в целом для каждого отдельного класса не существует того, что происходит на диске. В случае стандартных потоков следует, что это логические шаги по очистке буферов, закрытие потока и удаление любых управляемых и неуправляемых объектов. –

6

Вы также можете просто использовать метод File.ReadAllText:

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

Как это работает? Открывает ли он только соединение, читает весь файл и закрывает файл? – norlando

+0

Да, он делает именно это. –

0

Мне кажется, что лучший способ сделать это в общем зачете будет иметь FileStream закрывалась сама. Он не подразумевает знания о чем-либо, что существует в слое выше самого себя, поэтому для него действительно является ошибкой делать что-либо, что может повлиять на эти более высокие уровни.

Сказав, что эти конструкции более высокого уровня не должны аксиоматически предполагать что-либо о какой-либо поставки базового слоя, а также, или, если они делают это, они должны делать это в явном виде:

1) Если он был создан из существующий поток, то конструкция более высокого уровня должна быть закрыта НЕЗАВИСИМЫЙ базового потока (фактически просто распоряжающегося любыми ресурсами, выделенными для собственного использования) или закрытым ВКЛЮЧАЯ базовый поток. Это должны быть два различных вызова функций, например Close() и CloseSelf() (если это должно было быть реализовано таким образом, чтобы быть обратно совместимым с существующим кодом).

2) Если он не был создан из существующего потока (т. Е. Конструктор должен был создать базовый поток), то закрытие конструкции более высокого уровня должно также привести к тому, что основной поток закроется, поскольку в этом случае базовый поток является неявной частью конструкции более высокого уровня. В этом случае CloseSelf() просто вызовет Close().

Кажется расточительным реализовать эти классы так, как это было сделано.Если вы планируете использовать тот же файл для (в качестве примера) последовательного ввода и последовательного вывода, вы фактически вынуждены системой рассматривать его как два разных объекта, если вы хотите получить доступ к функциям более высокого уровня классов потомков. Ваша альтернатива заключается в том, чтобы придерживаться конструкции нижнего уровня и реализовывать функции более высокого уровня самостоятельно - эффективно перепрофилировать собственные специальные версии классов потомков, которые уже существуют.

Если бы это было сделано, как описано выше, типичная функциональность была бы такой же простой, как сейчас, но для более сложных приложений можно было бы сохранить единую блокировку в файле и повторно использовать ее как требуется, когда требуется, в отличие от необходимости отказаться от блокировки и всех связанных ресурсов, а затем мгновенно перераспределять их снова и снова - добавление служебных данных и фрагментации памяти в систему без уважительной причины.

В существующих условиях, однако, правильная вещь понятна. FileStream не может предполагать, что он знает что-либо о любом объекте, в котором он становится частью, поэтому вы должны закрыть самую внешнюю конструкцию. Это применимо независимо от того, работает ли он в любом случае, как отметил Бруно и другие, и по той причине, что они дали, - совместимость. Успение - правнук ужасных ошибок.

0

Интересным является то, что закрытие StreamReader или писателя повлияет на статус чтения/записи принадлежащего FileStream. Это означает, что вы не можете использовать StreamReader, а затем StreamWriter, используя тот же самый поток.

Смежные вопросы