Почему я должен закрыть() файл в C#?

Я знаю, это может показаться глупым, но почему следующий код работает только если я рядом() файла? Если я не закрою файл, весь поток не будет записан.

действия:

  1. запустить этот код при загрузке формы.
  2. закрыть форму с помощью мыши, как только он появится.
  3. программа завершается.

не должен ли объект file быть сброшен или закрыт автоматически, когда он выходит за рамки? Я новичок в C#, но я привык добавлять вызовы Close () в деструкторах C++.

// Notes: complete output is about 87KB. Without Close(), it's missing about 2KB at the end.

// Convert to png and then convert that into a base64 encoded string.
string b64img = ImageToBase64(img, ImageFormat.Png);
// Save the base64 image to a text file for more testing and external validation.
StreamWriter outfile = new StreamWriter("../../file.txt");
outfile.Write(b64img);
// If we don't close the file, windows will not write it all to disk. No idea why
// that would be.
outfile.Close();

6 ответов


C# не имеет автоматической детерминированной очистки. Вы должны обязательно вызвать функцию очистки, Если хотите управлять ее запуском. The using блок является самым распространенным способом сделать это.

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

using (StreamWriter outfile = new StreamWriter("../../file.txt")) {
    outfile.Write(b64img);
} // everything is ok, the using block calls Dispose which closes the file

EDIT: как указывает Харви, в то время как очистка будет предпринята когда объект собирается, это не является гарантией успеха. Чтобы избежать проблем с циклическими ссылками, среда выполнения не пытается завершить объекты в" правильном " порядке, поэтому FileStream на самом деле уже может быть мертв к тому времени StreamWriter finalizer запускается и пытается сбросить буферизованный вывод.

если вы имеете дело с объектами, которые нуждаются в очистке, сделайте это явно, либо с using (для использования в локальной области) или путем вызова IDisposable.Dispose (для долгоживущих объектов, таких как референты из член класса.)


потому что Write () буферизуется, и буфер явно сбрасывается Close ().


потоки-это объекты, которые "управляют" или "обрабатывают" ресурсы, собранные без мусора. Поэтому они (потоки) реализуют интерфейс IDisposable, который при использовании с "использованием" гарантирует, что ресурсы, собранные без мусора, будут очищены. попробуйте это:

using ( StreamWriter outfile = new StreamWriter("../../file.txt") )
{
   outfile.Write(b64img);
}

без #Close вы не можете быть уверены, когда базовый дескриптор файла будет правильно закрыт. Иногда это может быть при выключении приложения.


потому что вы используете streamwriter, и он не очищает буфер, пока вы Close() писатель. Вы можете указать, что вы хотите, чтобы писатель смывал каждый раз, когда вы вызываете запись, установив AutoFlush свойство streamwriter для true.

проверить документы. http://msdn.microsoft.com/en-us/library/system.io.streamwriter.aspx

Если вы хотите записать в файл без "закрытия", я бы использовал:

System.IO.File

кэш операционной системы запись в блок устройств, чтобы позволить ОС иметь лучшую производительность. Вы заставляете запись путем промывки буфера после записи установки streamwriter для автозапуска.


потому что дизайнеры C# клонировали Java, а не c++, несмотря на имя.

по-моему, они действительно пропустили лодку. Разрушение стиля C++ при выходе из области было бы намного лучше.

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