Java 想要了解这些文件的信息吗

Java 想要了解这些文件的信息吗,java,file,nio,Java,File,Nio,我写了一个递归遍历目录的程序;也就是说,它有一个遍历目录中所有文件的方法;如果这些文件中有任何一个是(子)目录,它也会遍历子目录的文件等。一旦我的程序确定某个文件不是目录,它就会为它创建一个文件对象,并从中获取某些信息,例如它占用了多少空间等 我想知道NIO路径对象是否能更快地完成这项工作;我不需要文件数据本身,好吧,我不需要打开文件。我需要姓名、分机号和长度。因此,我开始编写一个新方法,该方法采用字符串并创建路径而不是文件 我遇到了一组让我困惑的文件。在c:\Users\AppData\Loc

我写了一个递归遍历目录的程序;也就是说,它有一个遍历目录中所有文件的方法;如果这些文件中有任何一个是(子)目录,它也会遍历子目录的文件等。一旦我的程序确定某个文件不是目录,它就会为它创建一个文件对象,并从中获取某些信息,例如它占用了多少空间等

我想知道NIO路径对象是否能更快地完成这项工作;我不需要文件数据本身,好吧,我不需要打开文件。我需要姓名、分机号和长度。因此,我开始编写一个新方法,该方法采用字符串并创建路径而不是文件

我遇到了一组让我困惑的文件。在c:\Users\AppData\Local\Microsoft\WindowsApps\中有5个文件;它们都是EXE文件,长度都是0。执行DOS目录列表(包括带有/AL限定符的目录)不会将它们显示为连接或符号链接。但如果我使用其中一个创建路径对象,然后尝试读取文件的基本属性:

    Path path = Paths.get(folderPath.toString(), fileName);
    BasicFileAttributes bfa = null;
    try {  bfa = Files.readAttributes(path, BasicFileAttributes.class); }
    catch (IOException ioe)
    {
      File testFile = new File(String.format("%s%s%s", folderPath.toString(), File.separator, fileName));
      System.out.println(String.format("Got %s even though IOException thrown: %s", testFile.getName(), ioe.getMessage()));
    }
我得到:

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.WindowsFileAttributeViews$Basic.readAttributes(WindowsFileAttributeViews.java:53)
  at sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(WindowsFileAttributeViews.java:38)
  at sun.nio.fs.WindowsFileSystemProvider.readAttributes(WindowsFileSystemProvider.java:193)
  at java.nio.file.Files.readAttributes(Files.java:1737)
  at rcutil.file.FolderWalker.walkTree(FolderWalker.java:80)
  at rcutil.file.FolderWalker.walkTree(FolderWalker.java:89)
  at rcutil.file.FolderWalker.walkTree(FolderWalker.java:89)
  at rcutil.file.FolderWalker.walkTree(FolderWalker.java:89)
  at rcutil.file.FolderWalker.walkFolder(FolderWalker.java:60)
  at rcutil.file.FolderWalker.main(FolderWalker.java:178)
(我将在下面提供完整代码)

我创建了一个0长度的文件,扩展名为EXE;它显示在dir列表中,但如果我执行dir/al,则不会显示。attrib命令适用于我自己创建的测试文件,但不适用于这些文件。我的程序对此文件没有问题

那么这些动物是什么?如果我对连接和符号链接执行dir/al,它们通常会显示为符号链接和连接。我找到了一个叫做硬链接的文档,它似乎类似于符号链接;似乎没有DOS(或其他)命令在目录文件夹中显示这些内容

有人有更多的信息吗?我总是可以回到使用java.io.File;不知道java.nio.file.Path是否会更快。但现在我很好奇这些野兽到底是什么

package rcutil.file;

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

import rcutil.system.OperatingSystemUtil;

/**
 * Provides the walking of all files in a folder, recursively; instantiation requires
 * a parameter class implementing a callback to receive a method call for each file 
 * and directory encountered in the tree walk.
 * <P>The walkFolder() method in this class walks an entire directory subtree recursively,
 * making a call to the given callback class for each file and directory giving information
 * about the file or directory found. 
 * 
 * <P> TODO: convert this to the java.nio version, which I didn't know existed when
 * I wrote this.
 * @author rcook
 *
 */
public class FolderWalker
{
  FolderWalkerUser user;
  
  /**
   * Instantiate the folder walker to call back the given user for each file and directory encountered.
   * 
   * @param user
   */
  public FolderWalker(FolderWalkerUser user)
  {
    this.user = user;
  }
  
  /**
   * Start a treewalk at the given folder. Cannot be a non-directory file or a symbolic link.
   * @param givenFolderName
   * @throws Exception
   */
  public void walkFolder(String givenFolderName) throws Exception
  {
    try
    {
      if (isStringEmpty(givenFolderName)) { throwIOException((givenFolderName == null ? "Null" : "Empty") + " folderPath given to FolderWalker"); }
      
      Path path = Paths.get(givenFolderName);
      File topFile = path.toFile(); // new File(givenFolderName);
      
      if (!(topFile.exists()))  { throwIOException("File <" + givenFolderName + "> given to FolderWalker does not exist"); }
      
      BasicFileAttributes bfa = Files.readAttributes(path, BasicFileAttributes.class);
      if (!bfa.isDirectory()) { throwIllegalArgumentException("Folder path <" + givenFolderName + "> given to FolderWalker is not a directory"); }
      if (bfa.isSymbolicLink()) { throwIllegalArgumentException("Folder path <" + givenFolderName + "> given to FolderWalker is a symbolic link"); }

//      walkTree(topFile);
      walkTree(path);
      user.afterFolderWalk(givenFolderName);
      
    } catch (IOException e)
    {
      throw new IOException("Exception during FolderWalker.walkFolder() for <" + givenFolderName + ">", e);
    }
  }
  
  private void walkTree(Path folderPath) throws Exception
  {
    File folderFile = folderPath.toFile();
    user.foundFile(folderFile, true);
    String[] fileNameList = folderFile.list();
    if (fileNameList != null && fileNameList.length > 0)
    {
      for (String fileName : fileNameList)
      {
        Path path = Paths.get(folderPath.toString(), fileName);
        BasicFileAttributes bfa = null;
        try {  bfa = Files.readAttributes(path, BasicFileAttributes.class); }
        catch (IOException ioe)
        {
          File testFile = new File(String.format("%s%s%s", folderPath.toString(), File.separator, fileName));
          System.out.println(String.format("Got %s even though IOException thrown: %s", testFile.getName(), ioe.getMessage()));
//          ioe.printStackTrace();
        }
        if (bfa != null)
        {
          if (bfa.isDirectory()) { walkTree(path);               }
          else                   { user.foundFile(null, false);  }      
            // BIG TODO: passing null; if we switch to Paths, do we need to change the 
            // FolderWalkerUser interface to use paths?
            // trying to avoid File when possible, on theory that doing so saves runtime
        }
      }
    }
  }
  
  private void walkTree(File folder) throws Exception
  {
//    System.out.println("walkTree thread name: " + Thread.currentThread().getName());
    user.foundFile(folder, true);               // users are notified of folders at the top of their subtree 
    String[] fileNameList = folder.list();
    if (fileNameList != null && fileNameList.length > 0)
    {
      for (String fileName : fileNameList)
      {
        File currentFile = new File(folder, fileName);
//        if (isSymbolicLink(currentFile)) { System.out.printf("Symbolic link: %s%n"); }
        if (currentFile.isDirectory())
        {
          walkTree(currentFile);
        }
        else
        {
          user.foundFile(currentFile, false);     // user notified of non-folder files in sequence, after their containing folder
        }
      }
    }
  }
  
  private boolean isStringEmpty(String givenFolderName)
  {
    return (givenFolderName == null || givenFolderName.length() <= 0);
  }
  
  private void throwIOException(String msg) throws IOException
  {
    throw new IOException(msg);
  }

  private void throwIllegalArgumentException(String msg) throws IOException
  {
    throw new IllegalArgumentException(msg);
  }

  private boolean isSymbolicLink(File file) throws IOException
  {
    String absolutePath = file.getAbsolutePath();
    String canonicalPath = file.getCanonicalPath();
    if (OperatingSystemUtil.isWindows()) 
    {
      absolutePath = absolutePath.toLowerCase();
      canonicalPath = canonicalPath.toLowerCase();
    }
    return (!(absolutePath.equals(canonicalPath)));
  }
  
  /**
   * for testing purposes -- echo the folder tree as we walk it.
   * @param arguments
   */
  public static void main(String ... arguments)
  {
    String startFolderName = "C:\\Users\\ralph\\AppData";
    if (arguments != null && arguments.length > 0)
    {
      startFolderName = arguments[0];
    }
    
    System.out.println("Starting walk...");
    long startTime = System.currentTimeMillis();
    FolderWalker walker = new FolderWalker(new FolderWalkerUser() 
                                            {
                                              int fileCount, folderCount;
                                              public void foundFile(File file, boolean isDirectory)
                                              {
//                                                System.out.println(file.getAbsolutePath());
                                                fileCount++;
                                              }
                                              public void afterFolderWalk(String folderName)
                                              {
//                                                System.out.println("all done, folder name " + folderName);
                                                folderCount++;
                                              }
                                            }
                                          );
    try { walker.walkFolder(startFolderName); }
    catch (Exception ioe) { ioe.printStackTrace(); }
    long elapsedTime = System.currentTimeMillis() - startTime;
    System.out.println(String.format("Walk done, %5.2f seconds", elapsedTime/1000f));
    
  }
}
包rcutil.file;
导入java.io.File;
导入java.io.IOException;
导入java.nio.file.Files;
导入java.nio.file.Path;
导入java.nio.file.path;
导入java.nio.file.attribute.BasicFileAttributes;
导入rcutil.system.OperatingSystemUtil;
/**
*以递归方式遍历文件夹中的所有文件;实例化需要
*实现回调以接收每个文件的方法调用的参数类
*和在树漫游中遇到的目录。
*

此类中的walkFolder()方法递归遍历整个目录子树, *为提供信息的每个文件和目录调用给定的回调类 *关于找到的文件或目录。 * *

TODO:将其转换为java.nio版本,我不知道该版本何时存在 *这是我写的。 *@author-rcook * */ 公共级FolderWalker { FolderWalkerUser用户; /** *实例化文件夹遍历器,为遇到的每个文件和目录回调给定用户。 * *@param用户 */ 公共FolderWalker(FolderWalkerUser用户) { this.user=用户; } /** *在给定文件夹中启动treewalk。不能是非目录文件或符号链接。 *@param givenFolderName *@抛出异常 */ 公用文件夹(字符串givenFolderName)引发异常 { 尝试 { 如果(IsString(givenFolderName)){throwIOException((givenFolderName==null?“null”):“空”)+“folderPath给FolderWalker”);} Path Path=Path.get(givenFolderName); File topFile=path.toFile();//新文件(givenFolderName); 如果(!(topFile.exists()){throwIOException(“提供给FolderWalker的文件不存在”);} BasicFileAttributes bfa=Files.readAttributes(路径,BasicFileAttributes.class); 如果(!bfa.isDirectory()){throwIllegalArgumentException(“指定给FolderWalker的文件夹路径不是目录”);} if(bfa.isSymbolicLink()){throwIllegalArgumentException(“给FolderWalker的文件夹路径是一个符号链接”);} //walkTree(topFile); 步行树(路径); user.afterFolderWalk(给定文件夹名称); }捕获(IOE异常) { 抛出新的IOException(“FolderWalker.walkFolder()期间的异常”,e); } } 私有void walkTree(路径folderPath)引发异常 { File folderFile=folderPath.toFile(); user.foundFile(folderFile,true); 字符串[]fileNameList=folderFile.list(); if(fileNameList!=null&&fileNameList.length>0) { 用于(字符串文件名:fileNameList) { Path Path=Path.get(folderPath.toString(),文件名); BasicFileAttributes bfa=null; 试试{bfa=Files.readAttributes(path,BasicFileAttributes.class);} 捕获(ioe异常ioe) { File testFile=新文件(String.format(“%s%s%s”,folderPath.toString(),File.separator,fileName)); System.out.println(String.format(“即使引发IOException也得到了%s”)、testFile.getName()、ioe.getMessage()); //ioe.printStackTrace(); } 如果(bfa!=null) { if(bfa.isDirectory()){walkTree(path);} else{user.foundFile(null,false);} //大任务:传递null;如果切换到路径,是否需要更改 //FolderWalkerUser接口是否使用路径? //尽可能避免使用文件,理论上这样做可以节省运行时间 } } } } 私有void walkTree(文件文件夹)引发异常 { //System.out.println(“walkTree线程名称:”+thread.currentThread().getName()); user.foundFile(folder,true);//将通知用户子树顶部的文件夹 字符串[]fileNameList=文件夹.list(); if(fileNameList!=null&&fileNameList.length>0) { 用于(字符串文件名:fileNameList) { File currentFile=新文件(文件夹,文件名); //if(isSymbolicLink(currentFile)){System.out.printf

   Settings > Apps > App execution aliases
dir c:\Users\{userid}\AppData\Local\Microsoft\WindowsApps\
public static Stream<Map.Entry<Path, BasicFileAttributes>>
find(Path dir, int maxDepth, BiPredicate<Path, BasicFileAttributes> matcher, FileVisitOption... options) throws IOException {

    HashMap <Path,BasicFileAttributes> attrs = new HashMap<>();
    BiPredicate<Path, BasicFileAttributes> predicate = (p,a) -> (matcher == null || matcher.test(p, a)) && attrs.put(p, a) == null;

    return Files.find(dir, maxDepth, predicate, options).map(p -> Map.entry(p, attrs.remove(p)));
}

public static void main(String[] args) throws IOException {
    Path dir = Path.of(args[0]);

    // replace Integer.MAX_VALUE by 1 for current dir only:
    try(var x = find(dir, Integer.MAX_VALUE, (p,a)-> p.toString().toLowerCase().endsWith(".exe"))) {
        x.forEach(entry -> System.out.println(entry.getKey().toString()+" => "
                          +(entry.getValue().isDirectory() ? "DIR" : String.valueOf(entry.getValue().size()))));
    }
}