Блокировка файла - читайте и пишите, пока заблокированы - PullRequest
2 голосов
/ 27 октября 2011

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

Я пытался использовать FileStream с FileAccess.ReadWrite и FileShare.Read с Streamreader для чтения и затем StreamWriter (для того же FileStream) для записи, но это приводит к повреждению файла.Другие перестановки FileAccess и FileShare, похоже, тоже не решают мою основную проблему.

Поэтому я попытался закрыть StreamReader перед открытием StreamWriter, но это изменило CanReadи CanWrite свойства FileStream, поэтому я до сих пор не могу написать.

Очевидно, что я выбрал неправильный подход, так может кто-нибудь сказать мне, как я должен подходить к этому?Кажется, это достаточно распространенная вещь, которую нужно сделать - отредактировать файл и заблокировать доступ для записи, пока отредактированный файл не будет сохранен.

Ответы [ 3 ]

0 голосов
/ 27 октября 2011

Держите файл открытым с правами на запись. Это должно запретить все другие записи в файл.

0 голосов
/ 27 октября 2011

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

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

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

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

0 голосов
/ 27 октября 2011

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

Решением может быть что-то вроде этого:

static bool Read(FileStream fs, byte[] data, long position)
{
    fs.Seek(position, SeekOrigin.Begin);

    if (fs.ReadByte() == 0)
    {
        // Block of data not finished writing
        return false;
    }

    fs.Read(data, 0, data.Length);
    return true;
}

static bool Write(FileStream fs, byte[] data, long position)
{
    try
    {
        fs.Lock(position, data.Length + 1);
        fs.Seek(position, SeekOrigin.Begin);
        fs.WriteByte(0);
        fs.Write(data, 0, data.Length);
        fs.Seek(position, SeekOrigin.Begin);
        fs.WriteByte(1);
        fs.Unlock(position, data.Length + 1);
        return true;
    }
    catch (IOException)
    {
        return false;
    }
}

static bool Append(FileStream fs, byte[] data)
{
    return Write(fs, data, fs.Length);
}

, где вы всегда оставляете открытым FileStream как

FileStream fs1 = new FileStream("Test.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);

До data есть «защитный байт», который сообщает, записываются ли данные. Если он пишется, то чтение не удастся. Файл заблокирован "где это необходимо", используя FileStream.Lock.

Это явно лучше работает с двоичными данными фиксированной длины. Если у вас есть данные переменной длины (или вам нужно атомарно обновить больше «областей» файла), то это становится более сложным. Обычно вы используете БД по этой причине: -)

...