2010-12-04 3 views
12

이것은 길쌈이지만 여러 파일에 대해 크기, 최종 액세스 시간, 최종 생성 된 시간 등을 얻는 더 빠른 방법이 있습니까?여러 FileInfo를보다 빠르게 얻을 수 있습니까?

파일 경로가 길기 때문에 (열거 할 필요가 없음) 가능한 한 빨리 해당 정보를 조회해야합니다. 병목 현상이 디스크 여야하기 때문에 FileInfo를 병렬로 만들면 도움이되지 않을 것입니다.

NTFS 저널은 파일 이름을 불행히도 유지합니다. 그렇지 않으면 OS가 해당 메타 정보를 어딘가에 저장하지 않는다고 생각합니다.

정적 또는 Win32에서 호출 (파일 방법 나만 한 번에 불구하고 정보의 한 조각을 얻을 수 있습니다)에서는 FileInfo의 무리를 만드는 것은

오브젝트하는 정보를 오히려 가져 오는 방법이 있다면 할 수있는 또 하나의 최적화

어쨌든 도움이 될만한 사람이 있으면 기쁘게 생각합니다. 불행히도 여기서 마이크로 최적화를 수행해야하며 "데이터베이스 사용"이 가능한 대답이 아닙니다.

+0

NuGet을 통해 FluentPath를 이용할 수 있습니다. http://weblogs.asp.net/bleroy/archive/2010/11/19/fluentpath-1-0.aspx – jvanrhyn

+0

나는 그것을 이해하기 때문에 파일 경로 및 linq 스타일 작업과 함께 작업하기에 더 좋은 라이브러리이며 그렇지 않습니다. 후드 아래에서 파일 메타 데이터와 관련된 많은 작업 – Homde

+0

그렇지 않은 경우 응용 프로그램 수명주기의 시작 부분에 정보를 캐시 할 수 있습니까? 그러면 정보가 RAM에 저장되지만 오래 실행되는 응용 프로그램을 사용하는 경우에는 최신이 아닙니다. – Patrick

답변

8

System.IO.File에는 정적 방법이있어서 원하는 것을 얻을 수 있습니다. 마이크로 최적화이지만, 필요한 것일 수도 있습니다 : GetLastAccessTime, GetCreationTime.

특별히 정적 메소드를 요구하기 때문에 위의 텍스트를 떠날거야

편집. 그러나, 나는 당신이 FileInfo을 사용하는 것이 더 나을 것이라고 생각합니다 (단지 측정해야합니다). File과 FileInfo는 모두 의 내부 메서드를 사용하여 FillAttributeInfo이라는 데이터를 가져옵니다. 필요한 속성의 경우 FileInfo에서이 메서드를 한 번 호출해야합니다. File은 메서드 호출이 끝날 때 (정적이기 때문에) 속성 정보 객체가 버려지기 때문에 각 호출에서 호출해야합니다.

여러 가지 특성이 필요할 때 각 파일에 대해 FileInfo이 빠릅니다. 그러나 성능 상황에서는 항상 측정해야합니다! 이 문제에 직면하여 위에서 설명한대로 두 가지 관리 옵션을 모두 시도해보고 직렬 및 병렬로 실행하는 경우 모두 벤치 마크를 작성합니다. 그럼 충분히 빠르지 결정하십시오.

충분히 빠르지 않으면 Win32 API를 직접 호출해야합니다. 참조 소스에서 File.FileAttributeInfo을보고 비슷한 것을 생각해내는 것은 그리 어렵지 않을 것입니다. 당신이 정말로 필요하면

2 편집

는 사실이 직접 File의 내부 코드와 동일한 접근 방식을 않는 사용은 Win32 API를 호출하는 데 필요한 코드이지만, 모든 얻기 위해 하나의 OS 호출을 사용하여 속성 나는 그것이 정말로 필요한 경우에만 사용해야한다고 생각합니다. FILETIME에서 사용할 수있는 datetime까지 구문 분석해야하므로 수동으로 수행 할 작업이 더 많아집니다.

static class FastFile 
{ 
    private const int MAX_PATH = 260; 
    private const int MAX_ALTERNATE = 14; 

    public static WIN32_FIND_DATA GetFileData(string fileName) 
    { 
     WIN32_FIND_DATA data; 
     IntPtr handle = FindFirstFile(fileName, out data); 
     if (handle == IntPtr.Zero) 
      throw new IOException("FindFirstFile failed"); 
     FindClose(handle); 
     return data; 
    } 

    [DllImport("kernel32")] 
    private static extern IntPtr FindFirstFile(string fileName, out WIN32_FIND_DATA data); 

    [DllImport("kernel32")] 
    private static extern bool FindClose(IntPtr hFindFile); 


    [StructLayout(LayoutKind.Sequential)] 
    public struct FILETIME 
    { 
     public uint dwLowDateTime; 
     public uint dwHighDateTime; 
    } 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
    public struct WIN32_FIND_DATA 
    { 
     public FileAttributes dwFileAttributes; 
     public FILETIME ftCreationTime; 
     public FILETIME ftLastAccessTime; 
     public FILETIME ftLastWriteTime; 
     public int nFileSizeHigh; 
     public int nFileSizeLow; 
     public int dwReserved0; 
     public int dwReserved1; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] 
     public string cFileName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ALTERNATE)] 
     public string cAlternate; 
    } 
} 
+0

네,하지만 각각의 경우 디스크 io를 수행해야한다면 4 가지 별도의 호출을해야합니다. 나는 단지 추측하고있다. FileInfo가 그 일을 할 수도있다. 소스 코드 – Homde

+0

@MattiasK를 살펴보기 위해, disk-io가 필요하다고 가정한다. os는 메모리에 메타 데이터의 큰 부분을 캐싱 할 수 있으므로 디스크를 치지 않고 요청에 응답 할 수 있습니다. 당신은 마이크로 최적화를해야한다고 말했습니까? 최적화하지 않고 얼마나 오랜 시간이 걸릴지를 실제로 확인함으로써 이것을 확인 했습니까? =) – Rob

+0

실제로 ClearCase 동적보기 (네트워크 드라이브)에서 GetLastWriteTime을 사용했지만 속도가 너무 느립니다. GetLastWriteTime이 Win32 CreateFile을 호출하여 파일 정보를 가져 오는 핸들을 검색하여 바이러스 스캐너가 실행되는 것으로 보입니다. 그러나 FindFirstFile ClearCase를 사용하면 단순히 캐시 된 파일 정보가 반환되며 이는 요인 10만큼 빠릅니다. 복사 가능 코드에 감사드립니다. – schletti2000

2

DirectoryInfo 클래스를 사용할 수 있습니까? ?

DirectoryInfo d = new DirectoryInfo(@"c:\\Temp"); 
FileInfo[] f= d.GetFiles() 
+0

참조 이미 파일 경로가 있습니다. 그들을 다시 열거하는 것은 낭비처럼 보입니다. 그리고 나는 그 방법이 간단하게 fileinfo의 – Homde

+0

을 생성하는 것보다 빠르다는 것을 의심합니다. 네이티브 API API를 호출하거나 더 나은 버전으로이 기능을 요청할 수 있습니다. – TalentTuner

+0

감사합니다. 각 파일에 대해 개별적으로 수행하는 것보다 더 빠를 것 같습니다. – jreichert

4

특히 네트워크 공유와 함께 사용하는 경우 .NET의 DirectoryInfo 및 FileInfo 클래스는 매우 느립니다.

"스캔 할 파일"이 같은 디렉터리에 있으면 Win32 API의 FindFirstFile, FindNextFile 및 FindClose 기능을 사용하여 상황에 따라 훨씬 빠른 결과를 얻을 수 있습니다. 실제로 필요한 추가 정보 (예 : 디렉토리의 ".log"파일 중 75 % 만 필요로하는 모든 ".log"파일을 요구하는 경우)를 요청해야하는 경우에도 마찬가지입니다.

실제로 .NET의 정보 클래스는 이러한 Win32 API 함수를 내부적으로 사용합니다. 그러나 파일 이름 만 "remmeber"합니다. 여러 파일 (예 : LastModified)에 대한 추가 정보를 요청할 때 각 파일에 대해 별도의 (네트워크) 요청이 이루어지며 시간이 소요됩니다.

+0

흥미 롭습니다. 로컬 파일 용 디렉토리에서 findfirstfile/findnextfile을 사용하여 순차 파일을 읽는 최적화가 있는지 궁금합니다. 또한 OS가 다음과 같은 메타 데이터를 캐시하는지 알아 보는 것도 흥미로울 것입니다 – Homde

+4

DirectoryInfo.EnumerateFiles/Directories()가있는 4.0에서 수정되었습니다. –

0

나는 GetFileAttributesEx 기능 (pinvoke.net link)을 찾고 있다고 생각합니다. 그러나 FileInfo 클래스 (또는 기본 클래스)는 내부적으로이를 내부적으로 사용하므로 어떤 성능 개선이 있는지 의심 스럽습니다.

관련 문제