views:

37

answers:

3

I'm running a windows program from within java:

            String command = "cmd /C start "+fileName+".bat";
    Runtime rt = Runtime.getRuntime();
    Process pr = rt.exec(command, null, new File(currWD));
    int exitValue = pr.waitFor();

The program completes successfully (exitValue == 0) and creates a file "fileName" in the working directory. I am trying in the same routine to find the size of this file:

    xmlFileSize = (new File(fileName)).length(); 

Java finds the file yet it appear to be empty (xmlFileSize == 0). Once Java finishes I can see, however, that the file is non-empty.

How can I resolve this? All I want is that Java can correctly assesses the size of the file created by the windows program that Java has executed.

+1  A: 

A zero-length file indicates that the file may not exist. From the docs:

The length, in bytes, of the file denoted by this abstract pathname, or 0L if the file does not exist.

Note that you use currWD as working directory for your bat-file. You could try to do:

new File(currWD, fileName).length()

to make sure you look for the file in the right directory.

aioobe
Very good comment! I changed to File temp = new File(currWD, fileName).length() and then checked temp.exists() and Java shows FALSE. Yet the files exist - as I noted in one of my earlier comments above I can open the files in notepad while introducing a pause in the Java program
Nick
You're probably looking for it in the wrong place. Do a System.out.println(new File(currWD, fileName)) to see exactly where it looks for the file.
aioobe
No, the place is correct. I checked it by outputting temp.getCanonicalPath(), copying it in the command prompt as "notepad {copied canonical path}" and seeing the content of the file in notepad while Java is pausing (and showing that the file does not exist)
Nick
So notepad can see the file and the content, but java reports that it doesn't exist? ... beats me.
aioobe
Yes, this is what happens - Java does not see the files that the external program has created. Notepad can see them. My question is, essentially, how (if possible) to make Java see them.
Nick
Yes, it beats me, too. Here is my Java code: <code> File temp = new File(currWD, fileName+".xml"); System.out.println(temp.getCanonicalPath()+" exists = "+temp.exists()); </code> I copy the canonical path, open it in Notepad while Java is pausing after having said it's not there.
Nick
You should do it the other way around: 1) Pause, 2) open in notepad, 3) Resume and check exists.
aioobe
Thanks aioobe! Very good advice! I introduced a sleep(300) between <code>int exitValue = pr.waitFor();</code>and <code>xmlFileSize = (new File(fileName)).length();</code> and Java suddenly sees the file. When I use sleep(100) it sees the file created only in about 30% of the cases. When I use sleep(50) or no sleep it does not see the file at all. It seems what John hints at is true - the process that creates the files continues for 50-300 millisec after setting the exitValue. I can now simply leave sleep(300) between these lines of code but I wonder if there is a better way to do this.
Nick
Well, there is no easy way if you spawn your other program as a separate process. What you could do is to do a while loop (with a sleep(300)) that iterates until the file exists.
aioobe
+1  A: 

It probably has to do with executing the bat file from a command shell. What does the bat file do? Is it launching a program?

I'm guessing that the script calls or executes another program and returns which allows the shell to die. This in turn let's the java process continue while the process from the script continues executing asynchronously. According to the Java API for Process, that's allowable which it most definitely should be (link java.lang.Process)

John Engelman
Nick
Actually, I don't understand how this answer applies to the question I asked (I voted for it as it was guessing correctly what the bat file does). I am repeating myself but what happens is (1) Java code runs the bat file (2) the bat file calls a program (3) the program creates files (4) the bat file exits (5) the process that has started the bat file is exiting without any error but the routine cannot see the files created in step (3) even though Notepad can see them. I am not sure how the above answer illuminates the situation but I might be missing something (apologies if this is the case!).
Nick
A: 

I credit this answer to aioobe and John. As John suggests, the external program started by the batch file spawns a process that seems to be running for a while (50-300 millisec) after the Java sub-process running the batch file has returned. I resolved the problem by introducing a pause (as suggested by aioobe) :

int exitValue = pr.waitFor();

try {Thread.currentThread().sleep(300);} catch (InterruptedException e) {e.printStackTrace();}

After the pause Java seems to be able to see the files created by the external program. Thanks again to both contributors who helped me resolve this issue!

If anyone finds a more elegant solution, please, feel welcome to post.

Nick
That's what I was trying to get at with my post above, that the file creation process is finishing after Java has already returned in the pr.waitFor(). The issue here is that your sleep value is arbitrary based on what you are seeing right now. If the native command that you're running the shell takes longer for some reason, you'll still have an issue.
John Engelman
Yes, just got a "File not found" exception. It seems doing this in a loop as suggested by aioobe will be better.
Nick