我正在创建一个包含子目录列表的文件
task createNotes {
doLast {
def myFile = new File("my-notes.txt")
def file = new File("src/test/")
println myFile.exists()
myFile.delete()
println myFile.exists()
println myFile.absolutePath
println file.absolutePath
myFile.withWriter {
out ->
file.eachDir { dir ->
out.println dir.getName()
}
}
}
}
显然,排序顺序无法保证,但每次运行它时,都得到相同的排序顺序:
soft
java
calc
conc
caab
pres
如果我将“soft”dir更改为“sofp”,则输出为:
java
sofp
calc
conc
caab
pres
当我把名字改回来时,它就会回到原来的顺序。
它似乎没有按任何特定的顺序排序--这与文档中所说的顺序不能得到保证相匹配,但如果是这样,为什么它每次都给我相同的排序?
1条答案
按热度按时间t9eec4r01#
让我们先来看看
eachDir
Groovy扩展方法的实现:eachFile
的功能是什么?好的,Groovy只是在幕后调用Java的
File#listFiles
方法,然后在不干扰现有顺序的情况下迭代结果。转到OpenJDK实现,我们可以看到
Files#listFiles
通过normalizedList
方法使用FileSystem#list
。FileSystem#list
是抽象的。继续讨论两个最流行的实现,结果是UnixFileSystem#list
和Win32FileSystem#list
都有一个native
实现:窗口
深入了解Windows实现:
我们可以看到
FindFirstFileW
、FindNextFileW
和FindClose
WinAPI函数的组合用于迭代文件。搜索返回文件的顺序(如字母顺序)并不保证,它取决于文件系统。
(...)
此函数返回文件名的顺序取决于文件系统类型。对于NTFS文件系统和CDFS文件系统,通常按字母顺序返回文件名。对于FAT文件系统,通常按文件写入磁盘的顺序返回文件名,可能按字母顺序,也可能不按字母顺序。但是,如前所述,这些行为并不保证。
因此,在给定操作系统和文件系统类型约束的情况下,实现以一种最优化的方式列出文件。
* 无
那么 *nix systems呢?代码如下:
opendir
/readdir
/closedir
三人组支持这种时间迭代,POSIX documentation ofreaddir
只提到了排序:在头中定义的类型DIR<dirent.h>表示目录流,该目录流是特定目录中的所有目录条目的有序序列。
Linux documentation还有更多的内容要说:
对readdir()的连续调用读取文件名的顺序取决于文件系统实现;不太可能以任何方式对姓名进行排序。
离Windows足够近的地方,除了有一些秩序之外,没有任何秩序保证。
结论
“不保证”意味着一个特定的特性是一个实现细节,您不应该依赖它。与“保证”特性相反,由于向后兼容性,它保证了对某些对这些特性的更改称为breaking changes,通常在release notes和迁移指南中有详细的说明(例如,参见Vue 3 migration guide)。它们也会在最终确定和发布之前很久就被宣布-参见deprecation(通常会给开发人员留下一些时间来调整他们的代码,即使在它们上线之后)。
另一方面,“不保证”功能的行为可能因给定的产品/库版本、环境(例如JVM实作、操作系统、产品版本)或什至是特定的呼叫。它们有时候会显示出一些可预测的特性,但不应依赖它们。您需要确保处理好您期望代码片段拥有的保证,并自行实现它们。
总结您的问题:如果您希望文件有任何特定的顺序,请先对它们进行排序-即使这意味着顺序将保持不变。