问题
I am trying to filter hidden files using the NIO classes.
When I run the attached code on Windows 10 I get the following output:
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
The list displayed under Files (using the old File.listFiles(FileFilter)
method) is the list I see in Windows File Explorer and is what I am expecting to see (except for the Document and Setting and I know how to fix that)
- Why is the NIO approach not filtering hidden files the same way?
- How do I get NIO filtering to be the same?
Here is the test code:
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 );
}
}
}
Note: when I run the code without the filter, in both cases 18 files are displayed. So the first approach is filtering 12 hidden files and the second approach is only filtering 3 files.
回答1:
It's not a bug but a feature(!) known since jdk7, Windows hidden directory are not detected as hidden, see this bug and this one (fix jdk13).
As a workaround, you can do this :
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();
}
};
回答2:
I ended up using:
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();
}
};
As I mentioned in my question, I also want the Documents and Settings
to be hidden.
The Documents and Settings
is a link to C:\Users
.
The default implementation for the Files.readAttributes(…)
method is to follow links. So I guess because the c:\Users
directory is not hidden, the Documents and Settings
is also considered not hidden.
By using LinkOption.NOFOLLOW_LINKS
it is considered hidden, which is what I want.
来源:https://stackoverflow.com/questions/61785056/how-do-you-filter-hidden-files-using-directorystream-filter