Java文件列表的顺序与Windows资源管理器相同

Java文件列表的顺序与Windows资源管理器相同,java,explorer,natural-sort,Java,Explorer,Natural Sort,我正在使用下面的代码来获取文件列表排序:(如窗口资源管理器) package com.codnix.quickpdfgenerator.testing; 导入java.io.File; 导入java.util.ArrayList; 导入java.util.array; 导入java.util.Collections; 导入java.util.Comparator; 导入java.util.Iterator; 导入java.util.List; 导入java.util.regex.Matcher;

我正在使用下面的代码来获取文件列表排序:(如窗口资源管理器)

package com.codnix.quickpdfgenerator.testing;
导入java.io.File;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Collections;
导入java.util.Comparator;
导入java.util.Iterator;
导入java.util.List;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
公共类FileListOrder{
公共静态void main(字符串参数[]){
//庞大的测试数据集;)
文件夹=新文件(“C:\\Users\\Codnix\\Desktop\\Test Sequence”);
File[]listOfFiles=folder.listFiles();
列表文件名=Arrays.asList(listOfFiles);
//用于比较文件的适配器
Collections.sort(文件名,新的Comparator(){
private final Comparator NATURAL_SORT=新WindowsExplorerComparator();
@凌驾
公共int比较(文件o1,文件o2){;
返回自然排序.compare(o1.getName(),o2.getName());
}
});
用于(文件f:文件名){
系统输出打印ln(f);
}
}
公共静态类WindowsExplorerComparator实现Comparator{
private static final Pattern splitPattern=Pattern.compile(“\\d+\\\.\\s”);
@凌驾
公共整数比较(字符串str1、字符串str2){
迭代器i1=splitStringPreserveDelimiter(str1.Iterator();
迭代器i2=splitStringPreserveDelimiter(str2.Iterator();
while(true){
//直到这里,一切都是平等的。
如果(!i1.hasNext()&&!i2.hasNext()){
返回0;
}
//第一个没有更多的部件->第一个
如果(!i1.hasNext()&&i2.hasNext()){
返回-1;
}
//first的部件比i2多->后面是
if(i1.hasNext()&&!i2.hasNext()){
返回1;
}
字符串data1=i1.next();
字符串data2=i2.next();
int结果;
试一试{
//如果两个数据都是数字,则比较数字
结果=Long.compare(Long.valueOf(数据1),Long.valueOf(数据2));
//如果数字等于或大于,则优先考虑
如果(结果==0){
结果=-Integer.compare(data1.length(),data2.length());
}
}捕获(NumberFormatException ex){
//比较不区分大小写的文本
结果=数据1。比较信号案例(数据2);
}
如果(结果!=0){
返回结果;
}
}
}
私有列表splitStringPreserveDelimiter(字符串str){
Matcher Matcher=splitPattern.Matcher(str);
列表=新的ArrayList();
int pos=0;
while(matcher.find()){
添加(str.substring(pos,matcher.start());
添加(matcher.group());
pos=matcher.end();
}
列表.添加(str.substring(pos));
退货清单;
}
} 
}
但是,运行程序时输出:

C:\Users\Codnix\Desktop\Test Sequence\1 test -12.jpg
C:\Users\Codnix\Desktop\Test Sequence\1 test --11.jpg
C:\Users\Codnix\Desktop\Test Sequence\1 test ---10.jpg
预期输出(如窗口资源管理器):

如何获得这样的文件列表

已更新

由@jannis提供的实施解决方案

And here its output

before

1 test ---10.jpg
1 test --11.jpg
1 test -12.jpg
1.jpg
10.jpg
2.jpg

After (output)

1.jpg
1 test ---10.jpg
1 test --11.jpg
1 test -12.jpg
2.jpg
10.jpg
预期的


在Windows中按名称排序很棘手,而且比您的实现复杂得多。它也是可配置的,并且依赖于版本

注意:我为本文后面的内容创建了一个演示

使用 根据一些(例如)Windows用于按名称对文件进行排序

您可以尝试通过使用JNA调用此系统函数来实现比较器(别忘了在项目中包括):

比较国:

public class StrCmpLogicalWComparator implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        return Shlwapi.INSTANCE.StrCmpLogicalW(
            new WString(o1), new WString(o2));
    }
}
public class CompareStringExNumericComparator implements Comparator<String> {

    private static int SORT_DIGITSASNUMBERS = 0x00000008;

    @Override
    public int compare(String o1, String o2) {
        int compareStringExComparisonResult =
            Kernel32.INSTANCE.CompareStringEx(SORT_DIGITSASNUMBERS, o1, o2);

        // CompareStringEx returns 1, 2, 3 respectively instead of -1, 0, 1
        return compareStringExComparisonResult - 2;
    }
}
public class CompareStringExNonNumericComparator implements Comparator<String> {

    private static String INVARIANT_LOCALE = "";
    private static int NO_OPTIONS = 0;

    @Override
    public int compare(String o1, String o2) {
        int compareStringExComparisonResult =
            Kernel32.INSTANCE.CompareStringEx(NO_OPTIONS, o1, o2);

        // CompareStringEx returns 1, 2, 3 respectively instead of -1, 0, 1
        return compareStringExComparisonResult - 2;
    }
}
处理包含数字的文件名 我前面提到,Windows资源管理器对文件进行排序的方式是可配置的。您可以更改文件名中数字的处理方式,并切换所谓的“数字排序”。您可以阅读如何配置它。文件中说明的数字排序:

排序时将数字视为数字,例如,在“10”之前排序“2”

--

启用数字排序后,结果为:

如果禁用了数字排序,则如下所示:

这让我觉得Windows资源管理器实际上使用了排序功能,可以通过参数化来启用此功能。

使用 JNA部分:

import com.sun.jna.WString;
import com.sun.jna.win32.StdCallLibrary;

public interface Shlwapi extends StdCallLibrary {

    Shlwapi INSTANCE = Native.load("Shlwapi", Shlwapi.class);

    int StrCmpLogicalW(WString psz1, WString psz2);
}
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.win32.StdCallLibrary;

public interface Kernel32 extends StdCallLibrary {

    Kernel32 INSTANCE = Native.load("Kernel32", Kernel32.class);
    WString INVARIANT_LOCALE = new WString("");

    int CompareStringEx(WString lpLocaleName,
                        int dwCmpFlags,
                        WString lpString1,
                        int cchCount1,
                        WString lpString2,
                        int cchCount2,
                        Pointer lpVersionInformation,
                        Pointer lpReserved,
                        int lParam);

    default int CompareStringEx(int dwCmpFlags,
                                String str1,
                                String str2) {
        return Kernel32.INSTANCE
            .CompareStringEx(
                INVARIANT_LOCALE,
                dwCmpFlags,
                new WString(str1),
                str1.length(),
                new WString(str2),
                str2.length(),
                Pointer.NULL,
                Pointer.NULL,
                0);
    }
}
数字排序比较器:

public class StrCmpLogicalWComparator implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        return Shlwapi.INSTANCE.StrCmpLogicalW(
            new WString(o1), new WString(o2));
    }
}
public class CompareStringExNumericComparator implements Comparator<String> {

    private static int SORT_DIGITSASNUMBERS = 0x00000008;

    @Override
    public int compare(String o1, String o2) {
        int compareStringExComparisonResult =
            Kernel32.INSTANCE.CompareStringEx(SORT_DIGITSASNUMBERS, o1, o2);

        // CompareStringEx returns 1, 2, 3 respectively instead of -1, 0, 1
        return compareStringExComparisonResult - 2;
    }
}
public class CompareStringExNonNumericComparator implements Comparator<String> {

    private static String INVARIANT_LOCALE = "";
    private static int NO_OPTIONS = 0;

    @Override
    public int compare(String o1, String o2) {
        int compareStringExComparisonResult =
            Kernel32.INSTANCE.CompareStringEx(NO_OPTIONS, o1, o2);

        // CompareStringEx returns 1, 2, 3 respectively instead of -1, 0, 1
        return compareStringExComparisonResult - 2;
    }
}
公共类CompareStingExNumericComparator实现Comparator{
私有静态int SORT_DIGITSASNUMBERS=0x00000008;
@凌驾
公共整数比较(字符串o1、字符串o2){
int CompareStingExComparisonResult=
cornel32.INSTANCE.CompareStringEx(排序数字,o1,o2);
//CompareStringEx分别返回1、2、3,而不是-1、0、1
返回compareStringExComparisonResult-2;
}
}
非数字排序比较器:

public class StrCmpLogicalWComparator implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        return Shlwapi.INSTANCE.StrCmpLogicalW(
            new WString(o1), new WString(o2));
    }
}
public class CompareStringExNumericComparator implements Comparator<String> {

    private static int SORT_DIGITSASNUMBERS = 0x00000008;

    @Override
    public int compare(String o1, String o2) {
        int compareStringExComparisonResult =
            Kernel32.INSTANCE.CompareStringEx(SORT_DIGITSASNUMBERS, o1, o2);

        // CompareStringEx returns 1, 2, 3 respectively instead of -1, 0, 1
        return compareStringExComparisonResult - 2;
    }
}
public class CompareStringExNonNumericComparator implements Comparator<String> {

    private static String INVARIANT_LOCALE = "";
    private static int NO_OPTIONS = 0;

    @Override
    public int compare(String o1, String o2) {
        int compareStringExComparisonResult =
            Kernel32.INSTANCE.CompareStringEx(NO_OPTIONS, o1, o2);

        // CompareStringEx returns 1, 2, 3 respectively instead of -1, 0, 1
        return compareStringExComparisonResult - 2;
    }
}
公共类CompareStingExNonNumericComparator实现Comparator{
私有静态字符串不变量_LOCALE=“”;
私有静态int NO_选项=0;
@凌驾
公共整数比较(字符串o1、字符串o2){
int CompareStingExComparisonResult=
CompareStringEx(无选项,o1,o2);
/