Encoding issues on Java 7 file names in OS X - java

I have the following code:
public static void main( String[] args ) {
System.out.println(Locale.getDefault());
File f = new File("/Users/johngoering/Documents");
File[] fs = f.listFiles();
for (File ff : fs) {
System.out.println(ff.getName());
System.out.println(ff.exists());
}
}
In my Documents folder I have a file called "öß.pdf". Here is the output under Java 6:
en_US
(...)
öß.pdf
true
(...)
But here is the output under Java 7:
en_US
(...)
o����.pdf
false
(...)
Note especially that file.exists returns false for a file returned by listFiles!!
What gives? Is there any way to fix this? This seems like quite the Java 7 bug...

With some help from Oracle, we discovered a workaround: the environment variable LC_CTYPE was not set to UTF-8 within Eclipse (and when starting from a JNLP or wherever else).
This explains why the code worked on the terminal, since the OS X terminal by default "sets the locale environment variables" (an option which can be turned off and then you get the same issue as above even in the terminal).
Setting this environment variable in the launcher worked around the problem.
I still consider this a bug for Java 7 because Java 6 still worked even WITHOUT this variable.

Related

Is this a bug in java jdk?

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.

Can't find symbol even though class is in the same folder

I have looked at all the other stuff, mine is a compatibility issue I think, or PATH maybe. I have a bunch of classes I've been using since about 2008 and now the java command and the javac command can't find the classes even though they are in the same directory/folder. I have C:\Program Files\Java\jdk1.6.0_25\bin in the Path variable, but nothing in the Classpath. I normally have the compiled classes in the same folder with the java I'm compiling. I've been doing the same thing for 5 years! I have recompiled the lowest level class which is called WotifCat01. The compiler comes back with
WotifCat00.java:27:cannot find symbol
Symbol : WotifCat01
import java.io.*;
/** Find/replace program **/
class WotifCat00
{
private static int cnt;
private static String[][] filnamStrg={ {"Data/reftfile.txt","Data/AccumData/allreftfile.txt","","",""},
{"Data/reft1file.txt","Data/AccumData/allreft1file.txt","","",""},
{"Data/reft2file.txt","Data/AccumData/allreft2file.txt","","",""},
{"Data/reft3file.txt","Data/AccumData/allreft3file.txt","","",""},
{"Data/reft4file.txt","Data/AccumData/allreft4file.txt","","",""},
{"Data/work1file.txt","Data/AccumData/alltextsrc.txt","","",""},
{"","","","",""} };
private static String[] args1={"","","","",""};
public static void main(String[] args) {
while (filnamStrg[cnt][0] != "") {
args1[0] = filnamStrg[cnt][0];
args1[1] = filnamStrg[cnt][1];
WotifCat01 wotifCat01 = new WotifCat01();
wotifCat01.main(args1);
cnt++;
}
}
}
I've used this setup for a while and it worked fine on my laptop till now with Windows 7. I suspect something I've installed has overwritten something. This has to be really simple but I can't see it. I've removed jdk1.7.0_25 back to 1.6 but no change.
I backed up the classpath and deleted it. Now works fine. It contained IBM DB2 paths. DB2 I had installed in 2011 so discounted it, but it did have java paths in it so it must have overrode the path. I am not sure how DB2 managed to do so 2 years after install, I may have inadvertently activated something. Thanks for your input.
Neil Mc

File with International characters doesn't exist with Java 7 and old I/O methods [duplicate]

I have the following code:
public static void main( String[] args ) {
System.out.println(Locale.getDefault());
File f = new File("/Users/johngoering/Documents");
File[] fs = f.listFiles();
for (File ff : fs) {
System.out.println(ff.getName());
System.out.println(ff.exists());
}
}
In my Documents folder I have a file called "öß.pdf". Here is the output under Java 6:
en_US
(...)
öß.pdf
true
(...)
But here is the output under Java 7:
en_US
(...)
o����.pdf
false
(...)
Note especially that file.exists returns false for a file returned by listFiles!!
What gives? Is there any way to fix this? This seems like quite the Java 7 bug...
With some help from Oracle, we discovered a workaround: the environment variable LC_CTYPE was not set to UTF-8 within Eclipse (and when starting from a JNLP or wherever else).
This explains why the code worked on the terminal, since the OS X terminal by default "sets the locale environment variables" (an option which can be turned off and then you get the same issue as above even in the terminal).
Setting this environment variable in the launcher worked around the problem.
I still consider this a bug for Java 7 because Java 6 still worked even WITHOUT this variable.

Setting sun.locale.formatasdefault to true in Java 7

the following code will help illustrate my problem:
import java.util.Locale;
import java.text.*;
public class LocaleTest {
public static void main(String[] args) {
System.out.println(Locale.getDefault());
System.out.println("java-version-" +System.getProperty("java.version"));
System.setProperty("sun.locale.formatasdefault","true");
System.out.println("prop:" +System.getProperty("sun.locale.formatasdefault"));
System.out.println("getLocale-" +Locale.getDefault());
}
}
As we know, there is bug in Java 7, in Locale.getDefault().However as recommended by Oracle I have set the system property 'sun.locale.formatasdefault' to true. Even though I am now getting my m/c Locale, it is always showing as en_US even though my m/c Locale is set to fr_BE.
Here is the output of above code, which is compiled and run on Java 1.7.0_09:
en_US
java-version-1.7.0_09
prop:true
getLocale-en_US
Any thoughts on what might be causing thus? Many thanks in advance.
You need to set that system property before starting up your JVM. You can do this via command line arguments:
java -Dsun.locale.formatasdefault=true TargetClass
Or in environments where you don't control the launching of the JVM, you can set it via _JAVA_OPTIONS environment variable:
*Nix
export _JAVA_OPTIONS=-Dsun.locale.formatasdefault=true
Windows
SET _JAVA_OPTIONS=-Dsun.locale.formatasdefault=true
In Windows, if you want the change to be applied not only for that CMD but systemwide, you create a Windows System Variable JAVA_TOOL_OPTIONS

Running a Java program from Adobe AIR's native process

I've use Adobe native process to run java program from my air app. Here the code and it works fine. But i should write absolute path to java runtime for that:
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java.
If user installed java runtime in diff folder, or have diff version then this code would not work. How i can detect where java were installed or maybe there is another right way to run java applications from air applications? If i run java library from terminal command line then i could just write "java -jar pdfbox-app-1.6.0.jar" etc. and it runs fine.
private function convertPdf2Txt():void{
var arg:Vector.<String> = new Vector.<String>;
arg.push("-jar");
arg.push(File.applicationDirectory.resolvePath("pdfbox-app-1.6.0.jar").nativePath);
arg.push("ExtractText");
arg.push("-force");
arg.push(File.applicationStorageDirectory.resolvePath("Data/1.pdf").nativePath);
arg.push(File.applicationStorageDirectory.resolvePath("Data/1.txt").nativePath);
var fjava:File = new File("/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java");
if (fjava.exists==false){
Alert.show("Can't find Java Runtime in default folder.","Idea Rover",mx.controls.Alert.OK, null,null,imgInfo);
return;
}
var npInfo:NativeProcessStartupInfo;
npInfo = new NativeProcessStartupInfo();
npInfo.executable = fjava;
npInfo.arguments = arg;
var nativeProcess:NativeProcess;
nativeProcess = new NativeProcess();
nativeProcess.addEventListener(NativeProcessExitEvent.EXIT,onNativeProcessExit);
nativeProcess.start(npInfo);
}
Absolute path is:
Mac OS: /usr/bin/java
Win OS: (default)
64bit : C:\Program Files\Java
32bit : C:\Program Files (x86)\Java
rather than popping up an Alert, you could open a file selection dialog, using File.browseForOpen(). then, the File you want is contained in the event passed by the Event.SELECT handler. this flow seems standard for applications i've used that need to access other applications, but aren't sure where to find their executables.
var npInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
// setup npInfo, nativeProcess...
var fjava:File = new File("/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java");
if (!fjava.exists) {
fjava.addEventListener(Event.SELECT, onFileSelected);
fjava.browseForOpen("Where is Java located?");
}
private function onFileSelected (evt:Event) :void {
npInfo.executable = evt.target;
nativeProcess.start(npInfo);
fjava.removeEventListener(Event.SELECT, onFileSelected);
}
of course, you can use the same logic to find the file java needs to launch as well.
You may be able to determine where the Java binaries are by looking at the JAVA_HOME environment variable. I'd like to do the same thing as you're doing, so I'll post more after I do more research.

Categories