Java 想要了解这些文件的信息吗
我写了一个递归遍历目录的程序;也就是说,它有一个遍历目录中所有文件的方法;如果这些文件中有任何一个是(子)目录,它也会遍历子目录的文件等。一旦我的程序确定某个文件不是目录,它就会为它创建一个文件对象,并从中获取某些信息,例如它占用了多少空间等 我想知道NIO路径对象是否能更快地完成这项工作;我不需要文件数据本身,好吧,我不需要打开文件。我需要姓名、分机号和长度。因此,我开始编写一个新方法,该方法采用字符串并创建路径而不是文件 我遇到了一组让我困惑的文件。在c:\Users\AppData\Local\Microsoft\WindowsApps\中有5个文件;它们都是EXE文件,长度都是0。执行DOS目录列表(包括带有/AL限定符的目录)不会将它们显示为连接或符号链接。但如果我使用其中一个创建路径对象,然后尝试读取文件的基本属性:Java 想要了解这些文件的信息吗,java,file,nio,Java,File,Nio,我写了一个递归遍历目录的程序;也就是说,它有一个遍历目录中所有文件的方法;如果这些文件中有任何一个是(子)目录,它也会遍历子目录的文件等。一旦我的程序确定某个文件不是目录,它就会为它创建一个文件对象,并从中获取某些信息,例如它占用了多少空间等 我想知道NIO路径对象是否能更快地完成这项工作;我不需要文件数据本身,好吧,我不需要打开文件。我需要姓名、分机号和长度。因此,我开始编写一个新方法,该方法采用字符串并创建路径而不是文件 我遇到了一组让我困惑的文件。在c:\Users\AppData\Loc
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()))));
}
}