Как открыть уже открытый файл с помощью .net StreamReader?

StackOverflow https://stackoverflow.com/questions/897796

Вопрос

У меня есть несколько файлов .csv, которые я использую как часть тестового стенда.Я могу их открыть и прочитать без проблем. пока не У меня уже есть файл, открытый в Excel, и в этом случае я получаю IOException:

System.IO.IOException:Процесс не может получить доступ к файлу TestData.csv, поскольку он используется другим процессом.

Это фрагмент тестового стенда:

using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read)), false))
{
    // Process the file
}

Это ограничение StreamReader?Я могу открыть файл в других приложениях (например, в Notepad++), так что это не может быть проблемой операционной системы.Может быть, мне нужно использовать какой-то другой класс?Если кто-нибудь знает, как я могу обойти это (кроме закрытия Excel!) Я был бы очень благодарен.

Это было полезно?

Решение

Как говорит Джаред: «Вы не сможете этого сделать, если другой объект, у которого открыт файл, не разрешит совместное чтение».Excel допускает совместное чтение даже для файлов, открытых для записи.Поэтому вы должны открыть файловый поток с помощью FileShare.ReadWrite параметр.

Параметр FileShare часто понимают неправильно.Оно указывает на то, что другой открыватели файла могут сделать.Это относится как к прошлым, так и к будущим открывателям.Думайте о FileShare не как о ретроактивном запрете на предыдущие открытия (например, Excel), а как об ограничении, которое нельзя нарушать при текущем открытии или любых будущих открытиях.

В случае текущей попытки открыть файл FileShare.Read сообщает: «Откройте этот файл для меня успешно, только если его открыли какие-либо предыдущие средства открытия». только для чтения». Если вы укажете FileShare.Read для файла, который открыт для записи в Excel, твой open не удастся, так как это нарушит ограничение, поскольку в Excel оно открыто. для записи.

Поскольку в Excel файл открыт для записи, вы должны открыть его с помощью FileShare.ReadWrite, если хотите. твой открыт для успеха.Другой способ думать о параметре FileShare:он указывает «доступ к файлу другого парня».

Теперь предположим другой сценарий, в котором вы открываете файл, который в настоящее время не открывается ни одним другим приложением.FileShare.Read говорит, что «будущие программы открытия смогут открывать файл только с доступом для чтения».

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

Ни в коем случае это не допускает нескольких авторов.FileShare аналогичен базе данных IsolationLevel.Желаемая настройка здесь зависит от требуемых вами гарантий «согласованности».

Пример:

using (Stream s = new FileStream(fullFilePath, 
                                 FileMode.Open,
                                 FileAccess.Read,
                                 FileShare.ReadWrite))
{
  ...
}

или,

using (Stream s = System.IO.File.Open(fullFilePath, 
                                      FileMode.Open, 
                                      FileAccess.Read, 
                                      FileShare.ReadWrite))
{
}

Приложение:

А документация по System.IO.FileShare немного тонкий.Если вы хотите получить прямые факты, перейдите к документация для функции Win32 CreateFile, который лучше объясняет концепцию FileShare.

Другие советы

РЕДАКТИРОВАТЬ

Я до сих пор не уверен на 100%, почему это ответ, но вы можете решить эту проблему, передав FileShare.ReadWrite конструктору FileStream.

using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)), false)
{
  ...
}

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

На самом деле лучшая документация находится в СоздатьФайл функция.Это функция, которую .Net будет вызывать под капотом, чтобы открыть файл (создать файл - это немного неправильное название).У него есть лучшая документация о том, как работает аспект совместного использования при открытии файла.Другой вариант - просто прочитать ответ Чисо.

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

Еще одна загвоздка в том, что если вы откроете FileStream с FileShare.ReadWrite, последующие открытия этого файла ТАКЖЕ должны указывать FileShare.ReadWrite, или вы получите сообщение об ошибке «Другой процесс использует этот файл».

Использование системы.Диагностика;

Вы можете просто позвонить в процесс.

Не уверен, что это поможет, но именно это я только что использовал для реализации кнопки «Просмотр PDF» в нашей интрасети.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top