简体   繁体   English

Files.walkFileTree 在某些 windows 文件上引发访问异常

[英]Files.walkFileTree throws access exception on some windows files

I am using Files.walkFileTree() on a Windows 10 Pro system, and prints an exception stackTrace on some files.我在 Windows 10 Pro 系统上使用Files.walkFileTree() ,并在某些文件上打印异常 stackTrace。 I'm trying to figure out how to determine what files will throw this exception before it is thrown;我试图弄清楚如何确定哪些文件会在抛出这个异常之前抛出它; so far none of the files that cause the error are interesting to me, but I want the program to be able to detect which files would throw the error before it's thrown.到目前为止,我对导致错误的文件都不感兴趣,但我希望程序能够在错误被抛出之前检测到哪些文件会抛出错误。

code:代码:

import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;

public class WindowsFilePlay extends SimpleFileVisitor<Path>
{
  public static void say(String s) { System.out.println(s); }
  public static void main(String[] args) throws IOException
  {
    WindowsFilePlay play = new WindowsFilePlay();
    play.go();
  }
  
  private void go() throws IOException
  {
    say("For running on a Windows system.");
    String dirString = "c:\\users\\ralph\\appdata\\local\\microsoft\\windowsapps\\";
    File dirFile = new File(dirString);
    Path dirPath = dirFile.toPath();
    
    Files.walkFileTree(dirPath, this);
    say("done.");
  }
  
  public FileVisitResult visitFile(Path p, BasicFileAttributes bfa) throws IOException
  {
    say("visiting " + p.toString());
    if (bfa.isSymbolicLink()) { say("It's a link"); } else { say("It's not a link"); }
    if (p.compareTo(p.toRealPath()) != 0) { say("not a junction"); }
    return FileVisitResult.CONTINUE;
  }

}

and console:和控制台:

visiting c:\users\ralph\appdata\local\microsoft\windowsapps\GameBarElevatedFT_Alias.exe
It's not a link
Exception in thread "main" java.nio.file.FileSystemException: c:\users\ralph\appdata\local\microsoft\windowsapps\GameBarElevatedFT_Alias.exe: The file cannot be accessed by the system.

    at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
    at sun.nio.fs.WindowsLinkSupport.getFinalPath(WindowsLinkSupport.java:74)
    at sun.nio.fs.WindowsLinkSupport.getRealPath(WindowsLinkSupport.java:242)
    at sun.nio.fs.WindowsPath.toRealPath(WindowsPath.java:836)
    at sun.nio.fs.WindowsPath$WindowsPathWithAttributes.toRealPath(WindowsPath.java:138)
    at WindowsFilePlay.visitFile(WindowsFilePlay.java:32)
    at WindowsFilePlay.visitFile(WindowsFilePlay.java:1)
    at java.nio.file.Files.walkFileTree(Files.java:2670)
    at java.nio.file.Files.walkFileTree(Files.java:2742)
    at WindowsFilePlay.go(WindowsFilePlay.java:24)
    at WindowsFilePlay.main(WindowsFilePlay.java:15)

Some further information:一些进一步的信息:

  • In the debugger, the class for the file attributes is sun.nio.fs.WindowsFileAttributes , an extension of BasicFileAttributes .在调试器中,文件属性的 class 是sun.nio.fs.WindowsFileAttributesBasicFileAttributes的扩展。 I cannot just import WindowsFileAttributes;我不能只导入 WindowsFileAttributes; it's available to the runtime, but I don't know what version is used so I know what jar to put in my buildpath.它可用于运行时,但我不知道使用什么版本,所以我知道 jar 放在我的构建路径中。 So I cannot cast my BasicFileAttributes variable to WindowsFileAttributes and call its specific methods, unless I can get official assurance of which jar to use.所以我不能将我的 BasicFileAttributes 变量转换为 WindowsFileAttributes 并调用它的特定方法,除非我能得到官方保证使用哪个 jar。 I've noticed that there is a variable shown in the debugger for that class called reparseTag , which looks like a bit mask (value of 0x80000001b), but I don't know how to use it.我注意到在该 class 的调试器中显示了一个名为reparseTag的变量,它看起来像一个位掩码(值为 0x80000001b),但我不知道如何使用它。 The value is 0 for the few other files for which I've looked at it.对于我查看过的其他几个文件,该值为 0。

  • If I go to the DOS command line, these files are all there;如果我go到DOS命令行,这些文件都在那里; they have 0 length, but other files on the disk with 0 length are processed without error.它们的长度为 0,但磁盘上长度为 0 的其他文件被正确处理。 In DOS, they also appear in a list produced with dir/al , indicating (again) that they are symbolic links or reparse points or something.在 DOS 中,它们也出现在使用dir/al生成的列表中,表明(再次)它们是符号链接或重解析点或其他东西。 I'm confident this is related, but want to know how my program can detect that they cannot be treated like other files.我相信这是相关的,但想知道我的程序如何检测到它们不能像其他文件一样对待。

As stated in the document of Path#toRealPathPath#toRealPath文档中所述

Throws:抛出:
... ...
SecurityException - In the case of the default provider, and a security manager is installed, its checkRead method is invoked to check read access to the file, and where this path is not absolute, its checkPropertyAccess method is invoked to check access to the system property user.dir SecurityException - 在默认提供程序的情况下,并且安装了安全管理器,调用其 checkRead 方法来检查对文件的读取访问,并且在此路径不是绝对路径的情况下,调用其 checkPropertyAccess 方法来检查对系统属性的访问用户目录

So to "detect which files would throw the error before it's thrown", just check if we can read the file before calling toRealPath .因此,要“在抛出错误之前检测哪些文件会抛出错误”,只需在调用toRealPath之前检查我们是否可以读取该文件。

    @Override
    public FileVisitResult visitFile(Path p, BasicFileAttributes bfa) throws IOException {
        say("visiting " + p.toString());
        if (bfa.isSymbolicLink()) {
            say("It's a link");
        } else {
            say("It's not a link");
        }
        if (!Files.isReadable(p)) {
            say("No right to read");
            return FileVisitResult.CONTINUE;
        }
        if (p.compareTo(p.toRealPath()) != 0) {
            say("not a junction");
        }
        return FileVisitResult.CONTINUE;
    }

Implement this method in your class next to visitFile:在访问文件旁边的 class 中实现此方法:

            @Override
            public FileVisitResult visitFileFailed(Path file,
                    IOException exc) {
                System.err.println(exc);
                return FileVisitResult.CONTINUE;
            }

it handles the exceptions in SimpleFileVisitor.它处理 SimpleFileVisitor 中的异常。 good luck.祝你好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM