如何使用 DirectoryStream.Filter 过滤隐藏文件
How do you filter hidden files using DirectoryStream.Filter
我正在尝试使用 NIO 类 过滤隐藏文件。
当我 运行 Windows 10 上的附加代码时,我得到以下输出:
Files:
c:\Documents and Settings
c:\PerfLogs
c:\Program Files
c:\Program Files (x86)
c:\Users
c:\Windows
Paths:
c:$Recycle.Bin
c:\Config.Msi
c:\Documents and Settings
c:\Intel
c:\IntelOptaneData
c:\OEM
c:\OneDriveTemp
c:\PerfLogs
c:\Program Files
c:\Program Files (x86)
c:\ProgramData
c:\Recovery
c:\System Volume Information
c:\Users
c:\Windows
文件下显示的列表(使用旧的 File.listFiles(FileFilter)
方法)是我在 Windows 文件资源管理器中看到的列表,也是我期望看到的列表(除了文档和设置以及我知道如何解决这个问题)
- 为什么 NIO 方法不能以相同的方式过滤隐藏文件?
- 如何使 NIO 过滤相同?
这里是测试代码:
import java.io.*;
import java.nio.file.*;
public class ListFilesNIO
{
public static void main(String[] args) throws Exception
{
String directory = "c:\";
// Use old File I/O
FileFilter fileFilter = new FileFilter()
{
@Override
public boolean accept(File entry)
{
if (entry.isHidden()) return false;
return true;
}
};
System.out.println("Files:");
File[] files = new File( directory ).listFiles( fileFilter );
for (File file : files)
{
System.out.println( "\t" + file );
}
// Use NIO
DirectoryStream.Filter<Path> pathFilter = new DirectoryStream.Filter<Path>()
{
@Override
public boolean accept(Path entry) throws IOException
{
if (Files.isHidden( entry )) return false;
return true;
}
};
System.out.println();
System.out.println("Paths:");
DirectoryStream<Path> paths = Files.newDirectoryStream(Paths.get( directory ), pathFilter);
for (Path path : paths)
{
System.out.println( "\t" + path );
}
}
}
注意:当我 运行 没有过滤器的代码时,在这两种情况下都会显示 18 个文件。所以第一种方法是过滤12个隐藏文件,第二种方法只过滤3个文件。
这不是错误,而是自 jdk7 以来已知的功能(!),Windows 隐藏目录未被检测为隐藏,请参阅此 bug and this one(修复 jdk13)。
作为解决方法,您可以这样做:
import java.nio.file.attribute.DosFileAttributes;
...
DirectoryStream.Filter<Path> pathFilter = new DirectoryStream.Filter<Path>()
{
@Override
public boolean accept(Path entry) throws IOException
{
DosFileAttributes attr = Files.readAttributes(entry, DosFileAttributes.class);
return !attr.isHidden();
}
};
我最终使用了:
DirectoryStream.Filter<Path> pathFilter = new DirectoryStream.Filter<Path>()
{
@Override
public boolean accept(Path entry) throws IOException
{
DosFileAttributes attr = Files.readAttributes(entry, DosFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
return !attr.isHidden();
}
};
正如我在问题中提到的,我还希望隐藏 Documents and Settings
。
Documents and Settings
是 link 到 C:\Users
。
Files.readAttributes(…)
方法的默认实现遵循 links。所以我猜因为 c:\Users
目录没有被隐藏,所以 Documents and Settings
也被认为没有被隐藏。
通过使用LinkOption.NOFOLLOW_LINKS
它被认为是隐藏的,这就是我想要的。
我正在尝试使用 NIO 类 过滤隐藏文件。
当我 运行 Windows 10 上的附加代码时,我得到以下输出:
Files:
c:\Documents and Settings
c:\PerfLogs
c:\Program Files
c:\Program Files (x86)
c:\Users
c:\Windows
Paths:
c:$Recycle.Bin
c:\Config.Msi
c:\Documents and Settings
c:\Intel
c:\IntelOptaneData
c:\OEM
c:\OneDriveTemp
c:\PerfLogs
c:\Program Files
c:\Program Files (x86)
c:\ProgramData
c:\Recovery
c:\System Volume Information
c:\Users
c:\Windows
文件下显示的列表(使用旧的 File.listFiles(FileFilter)
方法)是我在 Windows 文件资源管理器中看到的列表,也是我期望看到的列表(除了文档和设置以及我知道如何解决这个问题)
- 为什么 NIO 方法不能以相同的方式过滤隐藏文件?
- 如何使 NIO 过滤相同?
这里是测试代码:
import java.io.*;
import java.nio.file.*;
public class ListFilesNIO
{
public static void main(String[] args) throws Exception
{
String directory = "c:\";
// Use old File I/O
FileFilter fileFilter = new FileFilter()
{
@Override
public boolean accept(File entry)
{
if (entry.isHidden()) return false;
return true;
}
};
System.out.println("Files:");
File[] files = new File( directory ).listFiles( fileFilter );
for (File file : files)
{
System.out.println( "\t" + file );
}
// Use NIO
DirectoryStream.Filter<Path> pathFilter = new DirectoryStream.Filter<Path>()
{
@Override
public boolean accept(Path entry) throws IOException
{
if (Files.isHidden( entry )) return false;
return true;
}
};
System.out.println();
System.out.println("Paths:");
DirectoryStream<Path> paths = Files.newDirectoryStream(Paths.get( directory ), pathFilter);
for (Path path : paths)
{
System.out.println( "\t" + path );
}
}
}
注意:当我 运行 没有过滤器的代码时,在这两种情况下都会显示 18 个文件。所以第一种方法是过滤12个隐藏文件,第二种方法只过滤3个文件。
这不是错误,而是自 jdk7 以来已知的功能(!),Windows 隐藏目录未被检测为隐藏,请参阅此 bug and this one(修复 jdk13)。
作为解决方法,您可以这样做:
import java.nio.file.attribute.DosFileAttributes;
...
DirectoryStream.Filter<Path> pathFilter = new DirectoryStream.Filter<Path>()
{
@Override
public boolean accept(Path entry) throws IOException
{
DosFileAttributes attr = Files.readAttributes(entry, DosFileAttributes.class);
return !attr.isHidden();
}
};
我最终使用了:
DirectoryStream.Filter<Path> pathFilter = new DirectoryStream.Filter<Path>()
{
@Override
public boolean accept(Path entry) throws IOException
{
DosFileAttributes attr = Files.readAttributes(entry, DosFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
return !attr.isHidden();
}
};
正如我在问题中提到的,我还希望隐藏 Documents and Settings
。
Documents and Settings
是 link 到 C:\Users
。
Files.readAttributes(…)
方法的默认实现遵循 links。所以我猜因为 c:\Users
目录没有被隐藏,所以 Documents and Settings
也被认为没有被隐藏。
通过使用LinkOption.NOFOLLOW_LINKS
它被认为是隐藏的,这就是我想要的。