#c#-3.0
#c #-3.0
Вопрос:
У меня есть следующий код для чтения и записи одной строки в текстовый файл. Можем ли мы присвоить null объектам reader и writer в конце обработки? или я должен вызвать метод Close ()? Спасибо.
FileInfo JFile = new FileInfo(@"C:test.txt");
using (FileStream JStream = JFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
{
StreamReader reader = null;
StreamWriter writer = null;
try
{
int n;
reader = new StreamReader(JStream);
string line = reader.ReadLine();
int.TryParse(line, out n);
n = n 1;
writer = new StreamWriter(JStream);
JStream.Seek(0, SeekOrigin.Begin);
writer.WriteLine(n);
writer.Flush();
}
catch (Exception x)
{
string message = string.Format("Error while processing the file. {0}", x.Message);
System.Windows.Forms.MessageBox.Show(message);
}
reader = null;
writer = null;
}
Комментарии:
1. Спасибо всем за замечательные объяснения. Я использую один и тот же объект FileStream для создания StreamReader и StreamWriter. Если я вызываю метод Close () как для объектов reader, так и для объектов writer, я получаю сообщение об ошибке «Не удается получить доступ к закрытому файлу», когда оно достигает writer. Закрыть(). Я думаю, потому что reader. Close() уже закрывает поток чтения и базовый поток файлов. Я не могу создавать разные потоки для reader и writer, так как мне приходится блокировать файл до тех пор, пока он не завершит запись в file.
2. есть идеи, что делать в этом случае? Спасибо.
Ответ №1:
При закрытии файла должны произойти определенные вещи. Например, когда ваша программа обращается к файлу и создает для него дескриптор. .Close()
-редактирование потока позволяет платформе немедленно освободить дескриптор и другие подобные ресурсы.
Когда вы устанавливаете для него значение null
, вы полагаетесь на сборщик мусора, который выполняет эту важную функциональность за вас. GC может очистить все это сейчас, а может и нет. Вы не знаете, когда это произойдет. Если ваша программа выйдет из строя, она может вообще никогда не освободить дескриптор.
Всегда полезно .Close()
запустить поток самостоятельно, как только вы закончите.
Комментарии:
1. Отличное объяснение того, что происходит.
Ответ №2:
Вы должны вызывать метод Close, чтобы освободить все базовые неуправляемые ресурсы. Присвоение объекту значения null не освобождает ресурсы. Подробности см. http://msdn.microsoft.com/en-us/library/system.io.stream.close.aspx
Обновление: Поскольку ваш код находится внутри инструкции using, метод Dispose будет автоматически вызван после завершения выполнения внутри инструкции using .
Ответ №3:
Когда вы присваиваете объекту значение null, вы сообщаете среде CLR, что он вам больше не нужен и запланирован для сборки мусора. Проблема, с которой вы столкнетесь, заключается в том, что перехваты среды CLR в файл, который вы открыли, не освобождаются до тех пор, пока ваша программа не завершится и среда CLR не будет закрыта. Когда вы вызываете метод Close(), файловые ресурсы очищаются, а затем все фрагменты должным образом планируются для сборки мусора.
если вы откроете streamreader в блоке using, он позаботится и об этом за вас, но вы потеряете часть мелкозернистой обработки ошибок, которую вы получаете с помощью блока try / catch / finally.
Ответ №4:
Как StreamReader
, так и StreamWriter
implementate IDisposable
, что является их способом сказать
«Когда вы закончите со мной, пожалуйста, вызовите этот метод (
Dispose()
), чтобы я знал, что вы закончили со мной, и я мог привести себя в порядок».
(Это также называется детерминированным завершением)
Итак, вам нужно вызвать Dispose
для них или обернуть их в using
инструкцию, которая просто делает то же самое для вас. В случае этих двух классов Dispose
будет выполнен внутренний вызов Close
, если он еще не закрыт.
Ответ №5:
На самом деле вы хотите вызвать Close() или, еще лучше, Dispose(), чтобы убедиться, что все содержимое удалено. Вы рискуете не записать буфер, если явно не закроете / не утилизируете средство записи.
Ответ №6:
Я думаю, лучшим решением будет использовать using
statment (как вы сделали в FileStream
). Он позаботится обо всей очистке.