2013-01-17 169 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 
. 
. 
. 

我怎樣才能得到文件,我不能在Windows 7

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 

得到相同的順序列表的正確順序?

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):整數); 之前 FindClose(sr);

回答

0

「排名」的意思是排序順序。

文件按正確順序排序(基於字符的ASCII值)。 2之後是19,因爲只有兩個名稱中的字符數相同,'2'在1之後。

如果您希望它們能夠以數字正確排序,您需要用零填充數字以使它們的寬度都相同(例如,而不是SampleFile.2.png,請使用SampleFile.02.png)。這將導致'02'來到19之前,因此它們在數字上正確排序。

您可以通過使用類似固定的編號問題:

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

你在Windows Explorer中看到的是實現Explorer.exe中,而不是在文件系統中的不同的訂單。

數值排序順序是在Windows 7中的一項新功能,所以如果按名稱排序和你有一堆用一個前綴後面數字的文件,資源管理器「標識」這一模式,並且不存在以傳統方式按名稱排序的列表,但按前綴和數字排序(就像字符串是整數)。

如果你想要做同樣在Delphi中,您可以通過添加所有在FindFirst/FindNext中返回到TSlist文件名做出來,然後用這個比較函數進行排序的字符串列表:

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的排序,所以你不應該依賴它。但是,您不需要在Delphi中重新實現數字排序。 Windows公開它使用的StrCmpLogicalW,它位於shlwapi.dll中。導入如下所示:

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

可以在Windows中禁用該行爲。如果您想要遵循Windows使用的順序,則需要使用REST_NOSTRCMPLOGICAL值調用SHRestricted。如果它返回true,則應該使用AnsiCompareStr。

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

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

因此,最終的排序函數應該是這樣的:

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; 

您可以緩存SHRestricted調用的結果,但如果你做你需要注意的WM_SETTINGSCHANGE廣播消息,並重新 - 當你得到一個時讀它。

+0

+1很高興知道:) – jachguate