Подтвердить что ты не робот

Какой наименее инвазивный способ чтения заблокированного файла на С# (возможно, в небезопасном режиме)?

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

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

Хотя это не мой точный пример использования, рассмотрите, как читать журнал SQL/Exchange или файл базы данных во время использования и установки. Я не хочу вызывать коррупцию, но я все же хочу видеть внутренности файла и читать его.

4b9b3361

Ответ 1

Принятый ответ не верен. Если файл действительно заблокирован, вы не можете просто изменить общий доступ к файлам. Это будет работать, если блокировка была установлена с этой опцией файлового обмена, но это не означает, что это так. Фактически, вы можете довольно легко протестировать решение @CaffGeek, открыв файл без FileShare.ReadWrite и затем попытавшись открыть его с этим флагом в ReadWrite. Вы поймете, что файл используется другим процессом.

Код:

string content;
var filePath = "e:\\test.txt";

//Lock Exclusively the file
var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);

//CaffGeek solution
using (FileStream fileStream = new FileStream(
        filePath,
        FileMode.Open,
        FileAccess.Read,
        FileShare.ReadWrite))
{
    using (StreamReader streamReader = new StreamReader(fileStream))
    {
        content = streamReader.ReadToEnd();
    }
}

Как видите, он падает. Этот результат аналогичен любому методу FileStream, например, File.Open. Он потерпит крах из-за того, что вы положили для FileShare на открытой сцене.

//OPEN FOR WRITE with exclusive
var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);


//OPEN FOR READ with file share that allow read and write
var x = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); //Crash

Копирование файла также не вариант. Вы можете попробовать сами, открыв файл исключительно и попытаться скопировать файл в проводнике Windows или с помощью кода:

var filePath = "e:\\test.txt";
var filePathCopy = "e:\\test.txt.bck";

//Lock the file
var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);

File.Copy(filePath, filePathCopy);
var x = File.Open(filePathCopy, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (var reader = new StreamReader(x))
{
    content = reader.ReadToEnd();
}

r.Close();
File.Delete(filePathCopy);

Этот код вылетает при попадании в строку File.Copy. Исключение такое же, как и раньше: файл используется другим процессом.

Вам нужно завершить процесс, который имеет блокировку файла, если вы хотите прочитать его ИЛИ, если у вас есть исходный код файла, который блокирует файл, чтобы изменить этот код на использование FileShare.ReadWrite вместо простого FileShare.Write.

Ответ 2

Вы можете сделать это без копирования файла, см. эту статью:

Хитрость заключается в использовании FileShare.ReadWrite(из статьи):

private void LoadFile()
{
    try
    {
        using(FileStream fileStream = new FileStream(
            "logs/myapp.log",
            FileMode.Open,
            FileAccess.Read,
            FileShare.ReadWrite))
        {
            using(StreamReader streamReader = new StreamReader(fileStream))
            {
                this.textBoxLogs.Text = streamReader.ReadToEnd();
            }
        }
    }
    catch(Exception ex)
    {
        MessageBox.Show("Error loading log file: " + ex.Message);
    }
} 

Ответ 3

Возможно, вы можете создать копию и прочитать ее, даже если файл заблокирован.

Или, может быть, StreamReader в FileStream в зависимости от того, как SQL открыл файл?

new FileStream("c:\myfile.ext", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);