Is this a bug in java jdk? - java

When I got a java.lang.File class with the code File file = new File("e:/");, of course I got a File class represented the e:\ directory.
But if I got a File class with code File file = new File("e:"); and I just in the drive E:, then I got a File class represented current directory.
Assume I'm in directory E:\dir\, And this directory have a file named Test.java.
It's content is:
import java.io.File;
public class Test {
public static void main(String[] args) {
File file = new File("e:");
File[] files = file.listFiles();
for(File f: files){
System.out.println(f + " " + f.exists());
}
}
}
Open the cmd tool and navigate to the directory e:\dir, execute the following command in it:
E:\dir> javac Test.java
E:\dir> java Test
I got:
e:\Test.class false
e:\Test.java false
Is this a java jdk bug?
Additional information from #JimGarrison:
I ran this code
public class Foo3
{
public static void main(String[] args) throws Exception
{
File f = new File("D:");
System.out.println(f.getCanonicalPath());
for (File x : f.listFiles())
System.out.println(x + " " + x.getCanonicalPath() + " " + x.getAbsolutePath() + " " + x.exists() + " " + x.getAbsoluteFile().exists());
}
}
in Eclipse (which lives on my D: drive) and got the following output:
D:\dev\src\pdxep
D:\.classpath D:\dev\src\pdxep\.classpath D:\dev\src\pdxep\.classpath false true
D:\.project D:\dev\src\pdxep\.project D:\dev\src\pdxep\.project false true
D:\.settings D:\dev\src\pdxep\.settings D:\dev\src\pdxep\.settings false true
D:\gallery D:\dev\src\pdxep\gallery D:\dev\src\pdxep\gallery false true
D:\pom.xml D:\dev\src\pdxep\pom.xml D:\dev\src\pdxep\pom.xml false true
D:\src D:\dev\src\pdxep\src D:\dev\src\pdxep\src false true
D:\target D:\dev\src\pdxep\target D:\dev\src\pdxep\target false true
Which confirms there's something funny going on.
Java Bug 8130462 seems to be related as it has to do with relative vs absolute paths specifically in Windows.

It's not a bug.
E:/ means that you specify both a drive and a directory
E: means you only specify a drive, the directory is left to the default value.
Note: Now what people think of as current directory is actually default directory. i.e. what is applied by default when none is specified.
It's just the same if you don't specify the drive at all, the default (current default) will apply.
This is the way it works on most File Systems.

The first part about getting a File representing the current working directory with code File file = new File("e:"); is not a bug. It is a Windows "drive relative path". That is, a path relative to the current working directory in the specified drive. (Yes, Windows have a different working director per drive)
The issue is that Java wrongly adds a \ after the drive-letter in the path which makes the path look like an absolute path, and wrongly returns false on file.exists() probably because of that.
However, Java correctly resolves the canonical-path and absolute-path and correctly returns true on x.getAbsoluteFile().exists(). Java also correctly returns the contents of the CWD in file.listFiles() as you noticed in your example code.
I found an old bug in the database which JDK-5066567 about this or at least very similar to this. It was created in 2004 and set to "In progress" 2013 and the current Assignee is "Inactive" so I don't think we will see any fix for this soon, if ever.
So to answer you question, I would say yes, it is a bug.
However, it seems like it is better handled in java.nio.file.Path. So if it is possible to use the java.nio.file.* package instead in your use case, it might be a acceptable workaround.

Related

Why does Files.isHidden(Path) return false for directories on Windows?

From the documentation of Files.isHidden(Path) (emphasis mine):
Tells whether or not a file is considered hidden. The exact definition of hidden is platform or provider dependent. On UNIX for example a file is considered to be hidden if its name begins with a period character ('.'). On Windows a file is considered hidden if it isn't a directory and the DOS hidden attribute is set.
Depending on the implementation this method may require to access the file system to determine if the file is considered hidden.
From this I can understand what the expected behavior is. However, why is this the expected behavior?
The reason I'm wondering is because of the difference in behavior between Files.isHidden, DosFileAttributes.isHidden, and Windows' File Explorer. For instance, I can go into File Explorer and set a directory to be hidden and it will no longer show up (unless I configure it to show hidden items). If I test if said directory is hidden with Java then Files.isHidden returns false and DosFileAttributes.isHidden returns true. You can test this with the following code:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.DosFileAttributes;
public class Main {
public static void main(String[] args) throws Exception {
final var directory = Path.of(args[0]).toAbsolutePath().normalize();
final var store = Files.getFileStore(directory);
final var dosAttrs = Files.readAttributes(directory, DosFileAttributes.class);
System.out.println("Directory : " + directory);
System.out.println("FileStore : " + store.name() + " [" + store.type() + "]");
System.out.println("Hidden (Files): " + Files.isHidden(directory));
System.out.println("Hidden (Dos) : " + dosAttrs.isHidden());
}
}
Note: I'm using Windows 10 and OpenJDK 11.0.1. My file system is NTFS.
Running this with:
java Main.java C:\path\to\hidden\directory
I get:
Directory : C:\path\to\hidden\directory
FileStore : OS [NTFS]
Hidden (Files): false
Hidden (Dos) : true
Note: This behavior appears to be part of WindowsFileSystemProvider. The method Files.isHidden(Path) simply forwards the call to the argument's FileSystem's provider. The implementation is basically:
DosFileAttributes attrs = ...; // get attributes
return !attrs.isDirectory() && attrs.isHidden();
I found this (non)-issue (JDK-8170334) where a comment says:
I don't think we have a bug here because the hidden attribute is meaningless on directories.
Yet File Explorer, which is core software on Windows, behaves like the hidden attribute is not meaningless on directories. So again, why does the Java implementation on Windows take into account whether or not the Path points to a directory? Or is Java correct and File Explorer is doing non-standard things?
I'm inclined to think File Explorer is correct because both CMD (via dir) and PowerShell (via Get-ChildItem) won't list hidden directories either; not unless the appropriate options are specified.
I checked documentation for file attributes provided by Microsoft for Windows platform. It says that if attribute FILE_ATTRIBUTE_HIDDEN = 2 (0x2) is set
The file or directory is hidden. It is not included in an ordinary directory listing.
As I can see in the class sun.nio.fs.WindowsConstants there is the same value definition used by DosFileAttributes.isHidden() method - public static final int FILE_ATTRIBUTE_HIDDEN = 0x00000002; which for my understanding should be mapped one to one with the attribute available for Windows, so in general hidden flag for a directory should be working in the same way as for a regular file.
In relation to operating system/file system integration, this behaviour seems to be incorrect.

(Java) How do you do full paths in the File class when you are using Textmate in a macbook?

I have a macbook and our school told us to use TextMate if we don't have a pc. I can do this in a pc, but I'm having trouble with the syntax in a mac OS since they are different. This is what I'm using and even though I created a file named Data.txt, the prompt that pops up says it doesn't exist.
import java.io.File;
class FileClassTutorial
{
public static void main(String[]args)
{
File x= new File("MacintoshHD/Users/Alexis/Desktop/Data.txt");
if(x.exists())
System.out.println(x.getName() + " exists!!!");
else
System.out.println("This file doesn't exist");
}
}
new File("something/other") is assumed to be "./something/other" where '.' is the current working directory where jvm is started. It's what you need ?
Otherwise, you can start a path by '/' to have an absolute path from super-root of your file disk

Java - String.contains() behaves oddly

this snippet of code works fine on my development machine (Windows 7 installed on VirtualBox jre 8 using Netbeans IDE), but on another machine (Windows 7 jre 8) always returns true.
It should only find files with a name like "town_house.html" instead it always returns true for every file in the folder.Running the jar file from prompt I don't get any exceptions.
Maybe it's just a trivial error I usually program in C/C++ ... any idea?
for(File f : files)
{
if(f.toString().contains("_") &&
f.toString().contains(".html")){
System.out.print("Processing file: " + f.getName()+ "\n");
String[] fileSplit = f.getName().split("_");
towns.add(fileSplit[0]);
}
}
Thanks in advance
You are checking toString() instead of getName() - maybe the directory path contains an underscore.
Try this instead (note also simplified test):
for(File f : files) {
if (f.getName().matches(".*_.*\\.html")) {
System.out.print("Processing file: " + f.getName()+ "\n");
String[] fileSplit = f.getName().split("_");
towns.add(fileSplit[0]);
}
}

Logic.class.getResource("effects\\newball.wav"); returns null

I've got the problem that the following code snip returns null:
System.out.println(Logic.class.getResource("effects\\newball.wav"));
I have a source folder in my project called effects. in this folder there's the referred file. I think there's a syntax error... Because THE FILE IS THERE. I must refer in this way (means with getResource) to my file because I will export it as jar later.
Thank you
Your effect directory should be a direct child of the src dir. Also in which case, you need a / to start the string path. So you would need this
System.out.println(Logic.class.getResource("/effects/newball.wav"));
ProjectRoot
src
effect
newball.wav
What I normally do using an IDE is just create a new package and name it whatever I want the file to be - in your case "effect". It's easier that way.
UPDATE
"I did it exatly so, but it still returns null"
It works fine for me
package stackoverflow;
public class Test {
public static void main(String[] args) {
System.out.println(Test.class.getResource("/effects/stack_reverse.png"));
}
}
Output: file:/C:/Android/workspace/StackOverflow/bin/effects/stack_reverse.png
Resource paths should use forward slashes, regardless of the filesystem on the machine you are using: try "effects/newball.wav"
See http://docs.oracle.com/javase/7/docs/technotes/guides/lang/resources.html (Under "resources, Names, and Contexts -- "The name of a resource is independent of the Java implementation; in particular, the path separator is always a slash (/).")

java code to search a file entire system, works fine on windows but infinite in linux ubuntu

Developing search utility to search a file entire computer system, works fine on windows platform but becomes an infinite process in ubuntu linux. Please help to overcome this flaw. The following is the main part of the code.
public static void fun(File f){ // root directory is passed as argument
try{
if(f.isDirectory()){
File [] fi=f.listFiles();
for(int i=0;i<fi.length;i++){
if(fileFound==true) break; // fileFound is boolean data type used as flag to indicate whether the file is found or not
System.out.println(fi[i].getName());
fun(fi[i]);
}
}
else{
if(f.getName().equalsIgnoreCase(txtFile.getText()) ||
(f.getName().toLowerCase().startsWith(txtFile.getText().toLowerCase())) ||
(f.getName().toLowerCase().endsWith(txtFile.getText().toLowerCase()))){
l.setText("file found " + f.getAbsolutePath()); // l is JLabel that indicated prints the info like file found and its path
fileFound=true;
}
}
}
catch(Exception e){
}
}
The error you are observing may be due to nested symbolic links.
The most effective approach to solve this problem would be to instead use FileUtils#iterateFiles from the excellent Apache Commons IO library.
There is something like "." (current directory) and ".." (above directory) in each dir in linux. Maybe thats your problem.
In unix like systems the first folder is "." (current folder)
and the second folder is ".." (the root folder)
you should skip the first 2 folders to avoid getting to the same folder over and over again.
try:
if(fi[i].getName() == "." || fi[i].getName() == "..")
continue;

Categories