首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Java中创建一个isReadable(路径)返回false的路径?

如何在Java中创建一个isReadable(路径)返回false的路径?
EN

Stack Overflow用户
提问于 2022-08-01 21:52:48
回答 2查看 84关注 0票数 1

本论坛中的其他问题询问如何使Java中的文件不可读。这个问题是不同的。我发现的其他问题指出了如何锁定被读取的文件,但是Files.isReadable(Path)仍然返回true

在Windows 10上使用Java17,我有一个方法,如果Files.isReadable()返回某个路径的false,它有一个契约要做(或不做)某些事情。我需要测试该方法,因此我需要人为地创建一个Files.isReadable()返回false的文件或目录(最好是每个文件或目录中的一个)。

我尝试在文件上创建一个独占锁:

代码语言:javascript
复制
Path lockedFile = writeString(directory.resolve("locked.txt"), "locked");
try (final FileChannel channel = FileChannel.open(lockedFile, StandardOpenOption.APPEND);
    FileLock lock = channel.lock()) {
  System.out.println("is locked file readable? " + isReadable(lockedFile));
}

然而,isReadable()仍然返回true

我试过使用File.setReadable()

代码语言:javascript
复制
Path lockedFile = writeString(directory.resolve("locked.txt"), "locked");
lockedFile.toFile().setReadable(false);
System.out.println("is locked file readable? " + isReadable(lockedFile));

Files.isReadable()仍然返回true

对于一个文件,我可以做些什么来使isReadable() 返回 false**?** (特定于Windows的东西是可以接受的,因为我可以设置我的单元测试,只在上运行,但至少我可以测试这个方法)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-02 02:02:32

在Windows 10中,这对我起了作用:

代码语言:javascript
复制
AclFileAttributeView view =
    Files.getFileAttributeView(path, AclFileAttributeView.class);
view.setAcl(Collections.emptyList());

为了实现跨操作系统的完整性,您可以使用适当的检查来保护它,并为(大多数) Unix文件系统添加类似的内容:

代码语言:javascript
复制
FileStore store = Files.getFileStore(path);
if (store.supportsFileAttributeView(AclFileAttributeView.class)) {
    AclFileAttributeView view =
        Files.getFileAttributeView(path, AclFileAttributeView.class);
    view.setAcl(Collections.emptyList());
} else if (store.supportsFileAttributeView(PosixFileAttributeView.class)) {
    Files.setPosixFilePermissions(path,
        EnumSet.noneOf(PosixFilePermission.class));
}
票数 1
EN

Stack Overflow用户

发布于 2022-08-01 22:58:58

可以说,在测试任何与任何类型的文件系统相关的文件系统时,“覆盖字段”的解决方案是来编写您自己的文件系统。好的,好的。清除蚊子可能有点像火箭筒,但是,这个原则几乎扩展到了所有您想要做的事情,并使用文件系统进行测试。

例如,希望有一些代码来写出一个文件,并且您想要检查它是否确实写入了正确的数据?您可以直接创建该文件,但现在您确实需要担心在测试期间要写入的某个目录。文件系统访问也很慢,这也意味着您需要担心测试后的清理工作。为了可并行化的目的,也很难将它们隔离开来。所有这些东西充其量都是小烦恼,但它开始感觉像死亡与一千个削减。

您所做工作的另一个主要缺点是,文件系统的本质在体系结构/操作系统之间差异很大。例如,您可以使用AclFileAttributeView view = Files.getFileAttributeView(path, AclFileAttributeView.class); view.setAcl(Collections.emptyList());,如果您在支持和设置文件系统上支持基于acl的访问系统的概念的操作系统上,这可能会导致.isReadable返回false。

这导致了一个相当糟糕的结果:每次在硬件上运行的代码都是完美的,但是在不同平台上工作的伙伴不能使用代码。如果您不想这样做,虚拟文件系统可以为您修复这个问题。

写我自己的.。什么?

“新”文件IO (java.nio.file )相对于旧的文件IO( java.io )的优点之一是,文件系统大多是抽象出来的。

“文件系统”的概念是你需要定义的东西。因此,您可以定义一个完全在内存中操作的测试--您现在不再需要担心清理,它将尽可能快,如果您想要它们,它将独立于任何其他测试。它也使嘲笑的东西(‘嘲笑’,英语单词,而不是‘嘲弄’,如JMock)容易得多。

有点像时间问题,您必须始终使用正确的调用(即,如果您习惯于在源中调用LocalDate.now(),则需要将其切换到LocalDate.now(clock),以便能够为稳定的测试设置虚拟时钟)。您不能只在任何地方使用Paths.get() -- Path对象“编码”使用的是哪个文件系统(您希望它“编码”您的测试文件系统正在使用中)。

而不是Paths.get("/path/stuff"),您必须调用:

someFileSystem.getPath("/path/stuff")中,someFileSystem可以是FileSystems.getDefault(),这会使您获得与Paths.get相同的行为,但是需要注入它,以便在测试条件下,您可以将它作为您的测试文件系统。

现在你只需要一个假的文件系统。不幸的是,FileSystem API非常复杂。做自己的事可不是件小事。幸运的是,你不必刮这头牦牛毛;有人(具体来说是谷歌的开发团队)已经帮你刮过胡子了。展示JimFS

不利方面

  • 集成JimFS仍然有点复杂。
  • Paths.get("/x/y")需要被列入你的林特禁令名单;消除这一点可能需要相当多的重写。特别是如果您不使用依赖注入框架。设置一个简单的单例文件系统是值得的;在此基础上,它可以返回FileSystems.getDefault(),然后所有代码的工作方式都是相同的。然后您可以展开它,例如添加一个全局的‘用我的虚拟文件系统覆盖’选项,或者使用ThreadLocal允许每个线程得到自己的线程,无论您需要什么。
  • 任何旧API (java.io)的使用,特别是包括使用path.toFile()的尝试,都是行不通的。据我所知,旧的API仅能与实际的文件系统交互。因此,您还需要对代码库中任何地方使用的旧j.i.File进行搜索,并将其替换为基于fileSystem.getPath的代码。

如果感觉这是一条更加艰难的道路,而不是您当前的模拟j.n.f.Files类的解决方案,这是可以理解的。你会知道的,这是你的计划。但是,我认为这包括了两个主要选项:模拟所有的东西,或者使用测试文件系统。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73199975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档