Как открыть уже открытый файл с помощью .net StreamReader? - PullRequest
47 голосов
/ 22 мая 2009

У меня есть несколько файлов .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 ++), чтобы не было проблем с O / S. Может быть, мне нужно использовать какой-то другой класс? Если кто-нибудь знает, как я могу обойти это (кроме закрытия Excel!), Я был бы очень благодарен.

Ответы [ 5 ]

151 голосов
/ 22 мая 2009

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

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

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

14 голосов
/ 22 мая 2009

EDIT

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

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

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

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

5 голосов
/ 22 мая 2009

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

0 голосов
/ 29 ноября 2012

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

Вы можете просто позвонить Process.Start ( «имя файла и путь»)

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

0 голосов
/ 05 октября 2012

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

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