2013-01-17 1 views
2

디렉토리에 일부 파일이 있습니다. 나는 FindFirst에와 FindNext 이러한 파일을 얻을하려고하지만 난 파일을받을 수 있습니다 어떻게 FindFirst, FindNext (Delphi Xe, Win7) 순위가 올바르지 않습니다.

SampleFile.0.png 
SampleFile.1.png 
SampleFile.10.png 
SampleFile.11.png 
SampleFile.12.png 
SampleFile.13.png 
SampleFile.14.png 
SampleFile.15.png 
SampleFile.16.png 
SampleFile.17.png 
SampleFile.18.png 
SampleFile.19.png 
SampleFile.2.png 
SampleFile.20.png 
SampleFile.21.png 
. 
. 
. 

있어 내 코드를 사용하려고 할 때

C:\Test 
SampleFile.0.png 
SampleFile.1.png 
SampleFile.2.png 
SampleFile.3.png 
SampleFile.4.png 
SampleFile.5.png 
SampleFile.6.png 
SampleFile.7.png 
SampleFile.8.png 
SampleFile.9.png 
SampleFile.10.png 
SampleFile.11.png 
SampleFile.12.png 
SampleFile.13.png 
SampleFile.14.png 
SampleFile.15.png 
SampleFile.16.png 
SampleFile.17.png 
SampleFile.18.png 
SampleFile.19.png 
SampleFile.20.png 
SampleFile.21.png 
SampleFile.22.png 

윈도우 7에 같은 순서를 얻을 수 없다 올바른 순위 순서에 나열 하시겠습니까?

Procedure Test; 
var 
sr : TSearchRec; 
i : integer; 
ListFiles : TStringList; 
begin 
ListFiles := TStringList.Create; 
i := FindFirst('c:\test\*.png', faDirectory, sr); 
while i = 0 do begin 
ListFiles.Add(ExtractFileName(sr.FindData.cFileName)); 
i := FindNext(sr); 
end; 
FindClose(sr); 
end; 

참고 : 나는 함수를 생성, 나는 해결책을했습니다 생각


진정한 ListFiles.Sorted =를 사용할 수있는 경우 결과는 여전히 잘못된 것입니다.

function SortFilesByName(List: TStringList; Index1, Index2: Integer): integer; 
var 
FileName1, FileName2: String; 
i, FileNumber1, FileNumber2: Integer; 
begin 
    FileName1 := ChangeFileExt(ExtractFileName(List[Index1]), ''); 
    FileName2 := ChangeFileExt(ExtractFileName(List[Index2]), ''); 
    i := POS('.', FileName1)+1; 
    FileNumber1 := StrToInt(Copy(FileName1, i, MaxInt)); 
    i := POS('.', FileName2)+1; 
    FileNumber2 := StrToInt(Copy(FileName2, i, MaxInt)); 
    Result := (FileNumber1 - FileNumber2); 
end; 

나는 다른 라인 ListFiles.CustomSort (SortFilesByName)을 추가했습니다; // (ListFiles, 1,2) : 정수); before FindClose (sr);

답변

0

"순위"란 정렬 순서를 의미합니다.

파일이 적절한 순서로 정렬됩니다 (문자의 ASCII 값을 기반으로 함). 219 다음에옵니다. 왜냐하면 비교는 두 이름에서 모두 같은 수의 문자로 이루어지기 때문에 '2'는 1 뒤에옵니다.

숫자를 올바르게 정렬하려면 숫자가 모두 같은 너비 (예 : SampleFile.2.png 대신 SampleFile.02.png이 아닌)로 숫자가 왼쪽으로 채워져 있어야합니다. 그러면 '02'이 19 앞에 올 수있게되므로 숫자가 올바르게 정렬됩니다.

당신은 같은 것을 사용하여 번호 문제를 해결할 수 있습니다 : 파일 시스템에 Explorer.exe에서와하지 구현되는 Windows 탐색기에서 볼

PngFileName := Format('SampleFile.%.2d.png', [Counter]); 
0

서로 다른 주문을.

숫자 정렬 순서는 윈도우 7의 새로운 기능입니다, 그래서 당신은 일종의 이름으로하고 숫자 뒤에 접두사를 가진 파일의 무리가있는 경우, 탐색기는 패턴을 "확인"과 존재하지 않습니다 전통적인 방식으로 이름별로 정렬 된 목록이지만 접두사로 정렬 된 다음 숫자로 정렬됩니다 (문자열이 Integer 숫자 인 것처럼). 델파이에서 동일한 작업을 수행하려면

, 당신은 TSlist로하여 FindFirst/FindNext에 의해 반환 된 모든 파일 이름을 추가하여 작업을 수행 한 다음이 기능 비교를 사용하여 문자열 목록을 정렬 할 수 있습니다

var 
    FileNames: TList<string>; 
begin 
    FileNames := TList<string>.Create; 
    try 
    SearchForFiles(FileNames); //here you add all the file names 
    //sort file names a la windows 7 explorer 
    FileNames.Sort(System.Generics.Defaults.TComparer<string>.Construct(
     function (const s1, s2: string): Integer 
     procedure ProcessPrefix(const fn: string; var prefix, number: string); 
     var 
      I: Integer; 
     begin 
      for I := length(fn) downto 1 do 
      if not TCharacter.IsDigit(fn[I]) then 
      begin 
       Prefix := Copy(fn, 1, I); 
       number := Copy(fn, I+1, MaxInt); 
       Break; 
      end; 
     end; 
     var 
     prefix1, prefix2: string; 
     number1, number2: string; 
     fn1, fn2: string; 
     begin 
     //compare filenames a la windows 7 explorer 
     fn1 := TPath.GetFileNameWithoutExtension(s1); 
     fn2 := TPath.GetFileNameWithoutExtension(s2); 
     ProcessPrefix(fn1, prefix1, number1); 
     ProcessPrefix(fn2, prefix2, number2); 
     if (Number1 <> '') and (Number2 <> '') then 
     begin 
      Result := CompareText(prefix1, prefix2); 
      if Result = 0 then 
      Result := CompareValue(StrToInt(number1), StrToInt(Number2)); 
     end 
     else 
      Result := CompareText(s1, s2); 
     end 
    )); 
    UseYourSortedFileNames(FileNames); 
    finally 
    FileNames.Free; 
    end; 
end; 
7

을 jachguate가 말했듯이 파일 시스템이 아닌 Explorer.exe가 정렬 작업을 수행합니다. FindFirst/FindNext는 평범한 ASCII 기반을 포함하여 특정 정렬을 보장하지 않으므로 의존하지 않아야합니다. 그러나 델파이에서 숫자 정렬을 다시 구현하지 않아도됩니다. Windows는 사용하는 컴퓨터를 StrCmpLogicalW으로 노출합니다 (shlwapi.dll). 가져 오기는 다음과 같습니다

function StrCmpLogicalW(psz1, psz2: PWideChar): Integer; stdcall; 
    external 'shlwapi.dll' 

윈도우에서 해당 동작을 비활성화 할 수 있습니다.Windows에서 사용하는 주문을 따르려면 으로 전화하여 REST_NOSTRCMPLOGICAL 값을 입력해야합니다. true를 반환하면 대신 AnsiCompareStr을 사용해야합니다.

const 
    // Use default CompareString instead of StrCmpLogical 
    REST_NOSTRCMPLOGICAL = $4000007E; 

function SHRestricted(rest: DWORD): LongBool; stdcall; external 'shell32.dll'; 

그래서 최종 정렬 기능은 다음과 같이해야한다 : 당신은 SHRestricted 호출의 결과를 캐시 할 수

function CompareFilenames(const AFilename1, AFilename2: string): Integer; 
begin 
    if SHRestricted(REST_NOSTRCMPLOGICAL) then 
    Result := AnsiCompareStr(AFilename1, AFilename2) 
    else 
    Result := StrCmpLogicalW(PWideChar(AFilename1), PWideChar(AFilename2)); 
end; 

, 그러나 당신이 경우에 당신은 WM_SETTINGSCHANGE 방송 메시지를 다시 주시 할 필요가 네가 하나를 얻을 때 읽으 라.

+0

+1 잘 알고 있습니다. :) – jachguate