답변:
나는 과거에이 일을 수없이 해왔고, 거의 매번 시도조차하는 것이 잘못되었습니다.
파일 권한 (파일 존재 여부 포함)은 휘발성 이며 언제든지 변경 될 수 있습니다. Murphy의 법칙 덕분에 특히 파일을 확인하고 파일을 열려고 할 때 사이의 짧은 기간 이 포함됩니다. 먼저 확인해야하는 영역에있는 경우 변경 가능성이 더 높습니다. 그러나 이상하게도 상당히 정적 인 경향이있는 테스트 또는 개발 환경에서는 절대 발생하지 않습니다. 이로 인해 나중에 문제를 추적하기가 어렵고 이러한 종류의 버그가 프로덕션에 쉽게 적용됩니다.
이것이 의미하는 바는 검사에도 불구하고 파일 권한이나 존재가 나쁜 경우 예외를 처리 할 수 있어야한다는 것입니다. 사전에 파일 권한을 확인하든 안하든 예외 처리 코드가 필요 합니다. 예외 처리 코드는 존재 또는 권한 검사의 모든 기능을 제공 합니다. 또한 이와 같은 예외 처리기는 느린 것으로 알려져 있지만 디스크 I / o가 훨씬 더 느립니다 ... 훨씬 느리고 ... .Exists () 함수를 호출하거나 권한을 확인하면 추가 트립이 발생 한다는 점을 기억하는 것이 중요합니다. 파일 시스템 밖으로.
요약하면 파일을 열기 전에 초기 검사는 중복되고 낭비입니다. 예외 처리에 대한 추가 이점은 없습니다. 실제로 성능에 도움이되지 않고 손상을 입히고 유지 관리해야하는 더 많은 코드 측면에서 비용을 추가하고 코드에 미묘한 버그를 유발할 수 있습니다. 초기 확인을 수행하는 데는 전혀 이점이 없습니다. 대신, 여기서 올바른 것은 파일을 열고 실패 할 경우 좋은 예외 처리기에 노력을 기울이는 것입니다. 파일이 존재하는지 여부를 확인하는 경우에도 마찬가지입니다. 이 추론은 모든 휘발성 자원에 적용됩니다 .
비슷한 문제로 여기에 오는 다른 사람을위한 빠른 팁 :
DropBox와 같은 웹 동기화 앱에주의하십시오. 방금 2 시간 동안 "using"문 (Dispose 패턴)이 .NET에서 손상되었다고 생각했습니다.
결국 Dropbox가 파일을 동기화하기 위해 백그라운드에서 지속적으로 파일을 읽고 쓰는 것을 깨달았습니다.
내 Visual Studio 프로젝트 폴더가 어디에 있는지 추측합니까? 물론 "내 Dropbox"폴더 안에 있습니다.
따라서 디버그 모드에서 응용 프로그램을 실행할 때 읽고 쓰는 파일도 DropBox 서버와 동기화되기 위해 계속해서 DropBox에 의해 액세스되었습니다. 이로 인해 잠금 / 액세스 충돌이 발생했습니다.
그래서 적어도 이제 더 강력한 파일 열기 함수 (예 : 여러 번 시도하는 TryOpen ())가 필요하다는 것을 알고 있습니다. 나는 그것이 이미 프레임 워크의 내장 된 부분이 아니라는 것에 놀랐다.
[최신 정보]
내 도우미 기능은 다음과 같습니다.
/// <summary>
/// Tries to open a file, with a user defined number of attempt and Sleep delay between attempts.
/// </summary>
/// <param name="filePath">The full file path to be opened</param>
/// <param name="fileMode">Required file mode enum value(see MSDN documentation)</param>
/// <param name="fileAccess">Required file access enum value(see MSDN documentation)</param>
/// <param name="fileShare">Required file share enum value(see MSDN documentation)</param>
/// <param name="maximumAttempts">The total number of attempts to make (multiply by attemptWaitMS for the maximum time the function with Try opening the file)</param>
/// <param name="attemptWaitMS">The delay in Milliseconds between each attempt.</param>
/// <returns>A valid FileStream object for the opened file, or null if the File could not be opened after the required attempts</returns>
public FileStream TryOpen(string filePath, FileMode fileMode, FileAccess fileAccess,FileShare fileShare,int maximumAttempts,int attemptWaitMS)
{
FileStream fs = null;
int attempts = 0;
// Loop allow multiple attempts
while (true)
{
try
{
fs = File.Open(filePath, fileMode, fileAccess, fileShare);
//If we get here, the File.Open succeeded, so break out of the loop and return the FileStream
break;
}
catch (IOException ioEx)
{
// IOExcception is thrown if the file is in use by another process.
// Check the numbere of attempts to ensure no infinite loop
attempts++;
if (attempts > maximumAttempts)
{
// Too many attempts,cannot Open File, break and return null
fs = null;
break;
}
else
{
// Sleep before making another attempt
Thread.Sleep(attemptWaitMS);
}
}
}
// Reutn the filestream, may be valid or null
return fs;
}
using
호출자가를 사용해야합니다 ...
using
여기서 작동하지 않습니다. 사용 블록이 끝나면 fs
강제로 닫힙니다. 호출자에게 닫힌 (너무 쓸모없는) 파일 스트림을 제공합니다!
찾고있는 솔루션은 다음과 같습니다.
var fileIOPermission = new FileIOPermission(FileIOPermissionAccess.Read,
System.Security.AccessControl.AccessControlActions.View,
MyPath);
if (fileIOPermission.AllFiles == FileIOPermissionAccess.Read)
{
// Do your thing here...
}
이것은 모든 파일의 경로에 대한보기를 기반으로 새로운 읽기 권한을 생성 한 다음 파일 액세스 읽기와 동일한 지 확인합니다.
첫째, Joel Coehoorn이 말한 것.
또한 : 꼭 필요한 경우가 아니라면 try / catch를 사용하지 않으려는 기본 가정을 조사해야합니다. 예외에 의존하는 논리를 피하는 일반적인 이유 ( Exception
객체 생성 성능이 좋지 않음)는 파일을 여는 코드와 관련이 없을 것입니다.
List<FileStream>
디렉토리 하위 트리의 모든 파일을 열어서 a를 채우는 메서드를 작성하고 있고 많은 수의 파일에 액세스 할 수 없을 것으로 예상했다면 파일을 열기 전에 파일 권한을 확인하여 너무 많은 예외가 발생합니다. 그러나 여전히 예외를 처리합니다. 또한이 작업을 수행하는 메서드를 작성하는 경우 프로그램 디자인에 심각한 문제가있을 수 있습니다.
public static FileStream GetFileStream(String filePath, FileMode fileMode, FileAccess fileAccess, FileShare fileShare, ref int attempts, int attemptWaitInMilliseconds)
{
try
{
return File.Open(filePath, fileMode, fileAccess, fileShare);
}
catch (UnauthorizedAccessException unauthorizedAccessException)
{
if (attempts <= 0)
{
throw unauthorizedAccessException;
}
else
{
Thread.Sleep(attemptWaitInMilliseconds);
attempts--;
return GetFileStream(filePath, fileMode, fileAccess, fileShare, ref attempts, attemptWaitInMilliseconds);
}
}
}
attempts
심판에 의해 전달됩니까? 말이 안 돼. <=
대신에 대한 테스트도 수행하지 않습니다 ==
.
throw ex
실제로 해야 할 일이 옳다고 생각 합니다.