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);
/