Как открыть уже открытый файл с помощью .net StreamReader?
-
23-08-2019 - |
Вопрос
У меня есть несколько файлов .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» в нашей интрасети.