Эксклюзивный доступ к текстовому файлу, его чтение и перезапись - PullRequest
0 голосов
/ 21 октября 2010

Я хотел бы открыть текстовый файл и не позволять другим процессам писать в него. Я понимаю, что могу сделать это со следующим FileStream:

Dim fs As New FileStream(_FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read)

Как только у меня будет такой доступ, мне нужно прочитать все строки (я буду использовать StreamReader (fs)), а затем мне нужно будет записать в файл (я буду использовать StreamWriter (fs)).

Проблема здесь в том, что StreamWriter не позволит мне установить режим добавления на false (поэтому я могу перезаписать весь текст в файле), когда я использую файловый поток в качестве параметра вместо пути к файлу. Таким образом, весь текст, написанный с помощью StreamWriter, добавляется к тексту, который мне не нужен. Если я использую StreamWriter с путем к файлу (который позволит мне установить append в false) в качестве параметра вместо файлового потока, он будет заблокирован из-за FileStream FileShare. Как я могу по-прежнему иметь эксклюзивный доступ для чтения и записи в файл, но при этом иметь возможность перезаписывать существующий текст (режим добавления false)?

1 Ответ

1 голос
/ 21 октября 2010

Это не невозможно, вам на самом деле не нужен StreamWriter, инициализированный с Apppend = true. Все, что вам нужно сделать, это использовать FileStream.Seek (), чтобы убедиться, что «указатель файла» расположен в конце файла. Этот пример кода C # работал хорошо:

using (var fs = new FileStream(@"c:\temp\test.txt", FileMode.Open,
        FileAccess.ReadWrite, FileShare.Read)) {
    var sr = new StreamReader(fs);   // NOTE: not using using
    string txt = sr.ReadToEnd();
    fs.Seek(0, SeekOrigin.End);      // Be sure
    var sw = new StreamWriter(fs);
    sw.WriteLine("appended");
    sw.Flush();
}

Обратите внимание на значительный дискомфорт в этом коде. Я бы начал с FileShare.Read, вашего предпочтительного значения. Это означает, что вы позволите другому процессу читать файл, пока вы с ним возитесь. Есть хорошие шансы, что этот процесс немного запутается из-за байтов, отображаемых в этом файле без предварительного уведомления. Может сработать хорошо, FileShare.None гарантирует, что ваш код не может никогда вызывать какие-либо ошибки. Настоятельно рекомендуется.

Следующим флагом является // Примечание, не использующее. Это важно, потому что StreamReader возьмет на себя «ответственность» за поток, который вы передаете. Если вы выполните стандартную правую вещь в .NET-коде, класс закроет поток, когда оператор Using завершит свою область действия. Это не то, что вы хотите, вы хотите сохранить файл, чтобы вы могли писать в него.

Вызов Seek () делает то же, что и аргумент Append конструктора StreamWriter. Убедитесь, что вы добавляете файл, а не случайным образом перезаписываете части файла с самого начала. Поскольку вы хотите добавить, нет проблем с тем, чтобы убедиться, что старые данные в файле обрезаны.

Флэш-колл здесь вонючий. У вас есть , чтобы вызвать его, чтобы заставить писателя очистить свой выходной буфер. Если вы этого не сделаете, случайные биты того, что вы пишете, будут отсутствовать в файле. Обычно это не проблема, потому что вы вызываете Close () или используете оператор Using, чтобы убедиться, что средство записи закрыто. Не в этом случае FileStream вызывает выстрелы, он правильно закроет файл здесь, но он не знает, что другой писатель запрыгнул на подножку и хочет написать.

Это сработает, но сломает немало догм. Более типичным шаблоном является open-read + read + close, open-createnew + write + close. И иметь дело с возможностью, что open-createnew может потерпеть неудачу, потому что другой процесс захватил файл. Опасности многозадачной операционной системы, всегда будьте готовы справиться с этим.

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