2

I am trying to identify if a print job or a .prn file has been completed being written to the computer. Steps to create : Click print on a file -> and select (print to file) The file will be attempted to save on a location on your computer and a window to enter the file name and save the location will be opened. Enter the name of the file and click save.

The file will then start writing to the specified folder as a .prn file. I am trying to accomplish identifying if this writing has been complete and if the file is available for further processing. How to identify if the file is complete and ready in java ? I tried the file lock (nio) and also the random file access. The latter worked, when trying to save/move/copy from one location on the computer to the other, but when I tried to save using .prn, this failed.

Please suggest on identifying if a .prn file writing is complete in java.

Below is the code I have tried to achieve to find out if the .prn file has completed writing to folder. I have tried this, from this link here.

public void uploadFiles(final File folder) {
    if (folder.list().length > 0) {
         upload.setEnabled(true);
        for (final File fileEntry : folder.listFiles()) {
            try {
                if(isFileCompletelyWritten(fileEntry)){
                if (onSendData(fileEntry.getAbsolutePath())) {
                    deleteFile(fileEntry);
                }
            }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    } else {
             upload.setEnabled(false);
    }
}

private boolean isFileCompletelyWritten(File file) {
    RandomAccessFile stream = null;
    try {
        stream = new RandomAccessFile(file, "rwd");  
        return true;
    } catch (Exception e) {
       System.out.println("Skipping file " + file.getName() + " for this iteration as it's not completely written");
    } finally {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                 System.out.println("Exception during closing file " + file.getName());
            }
        }
    }
    return false;
}

The

isFileCompletelyWritten(File file)

method is what I added to find if the file writing is complete. This did not work whenI tried to save the print file, but it did work while copying, moving, saving the files from one folder on the computer to the other. The .prn file was available to my program as and when the byte stream came in. Rather than skip the file, the RandomfileAccess was not able to detect if the writing was complete or not. When the byte stream wrote the file sequentially chunk by chunk, my program, proceeded further with its next steps, thinking the file is complete and available. When I ran the same code while copying a file on the local from one location to the other, the Randomfileaccess was able to check and see that more data is being written, and my program was able to skip the process for that iteration. This is how my program failed.

Community
  • 1
  • 1
eros
  • 103
  • 1
  • 11

3 Answers3

0

While I wait for you to update your Question with a decent explanation of what you tried and how it failed ...

AFAIK the only approaches that are guaranteed to work reliable AND portably involve the program that is writing the print file telling the other program when it is done.

  • If you control the program that is writing the print file, you can modify it to do stuff when it is finished.

  • If the program is (or could be) launched via a wrapper, you could modify the wrapper.

  • If it is an external program that you exec from Java, you could use Process.waitFor() to test when it exits.

Solutions involving locking and checking file update timestamps run into various portability and reliability concerns.


Re: your current solution. Your "is completely written" test is actually testing whether you can open the file.

  • If the file does not exist (because the printing hasn't even started yet!), this will create an empty file and say it is completed. WRONG!

  • If the file does exist, the open attempt may attempt to lock the file, but that is operating system specific. (And on Linux, there is no locking unless all programs involved use locking explicitly.)

So basically, this won't work on Linux at all. (On Windows, it will work provided that you don't test the file before it has been created ... and that is a "race condition" that makes the solution unreliable, at least in theory.)


So what are the other alternatives?

  • You could poll the file's last modification date or it size, to see when it / they stop changing. After a suitable (heuristic!) period of inactivity, assume that the file is completed.

  • You could implement the above using a FileWatcherService. (Complete with a heuristic inactivity period, etcetera)

  • You could try to use Lock ... except that the chances are that the program that is writing the files isn't using locks (on Linux). (The Lock API is for discretionary locking, and it relies on all applications involved using locking, either implicitly or explicitly. On Linux / Unix, locking doesn't happen implicitly or by default.)

I should stress once again that NONE of these alternatives is portable and entirely reliable.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • The print file is a user action, so I do not see a possibility to have control over that. The option I am left with is, somehow monitor the file that is being written ( the folder location that is being written to is fixed), and once it is complete, I can proceed further with the file. Since .prn is a sequential file, I am not sure of a way to find out a way to determine if the file is completely written. Also, I totally agree with you about the file locks not being a fine option. Please throw more insight if possible. Random file access way did not look possible here. – eros Feb 02 '14 at 00:50
  • I'm still waiting for you to complete the Question ... with an explanation of HOW your current attempted solution failed. – Stephen C Feb 02 '14 at 01:00
  • The .prn file was available to my program as and when the byte stream came in. Rather thank skip the file, the RandomfileAccess did not detect if the writing was complete or not. When the byte stream wrote the file sequentially chunk by chunk, my program, proceeded further with its next steps, thinking the file is complete and available. But when I tried copying a file on the local from one location to the other, the Randomfileaccess was able to check and see that more data is being written, and my program was able to skip the process for that iteration. This is how my program failed. – eros Feb 02 '14 at 01:08
  • Thank you for your response. I am running the code on Windows platform. Here, if the file does not exist, the code works as expected to be. It doesn't create a new empty file. The isFileCompletelyWritten, is able to identify no file is exists in the folder and works well. Yeah, I am attempting to open the file here, expecting the file to not open when it is not completely written. So, I felt it as a reliable logic to test if a file writing is complete. However, this did not work for print to file. – eros Feb 02 '14 at 12:27
  • I just attempted the Watcher service, and it does well, listening listening for new files. However, I ran into the same issue, where I was not able to find a way to see if the print to file is complete. Watcher is able to identify if a new file has arrived in the folder or not. – eros Feb 02 '14 at 12:34
  • public void watchFolder(){ WatchService watchService; boolean valid = true; do { try { watchService = FileSystems.getDefault().newWatchService(); monitorUploads.register(watchService, StandardWatchEventKinds.ENTRY_CREATE); WatchKey watchKey = watchService.take(); for (WatchEvent> event : watchKey.pollEvents()) { WatchEvent.Kind kind = event.kind(); if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) { } } } while (valid); } }).start(); } – eros Feb 02 '14 at 12:38
  • @eros - Yes that is correct. There is no event to say that the file has been closed in the current watcher API. You have to rely on some heuristic based on seeing no events for a period. – Stephen C Feb 02 '14 at 13:03
0

Apparently, I ended up choosing the print API in Java and I tried the code from - this link to see if the print job is complete. The sample does intiate a print job and monitors to report if it is complete or not. However, this is not suitable to my requirement, because, I do not want the program to create the print job. Instead, monitor a user initiated print, which is currently on the printer. There doesn't seem to be a work around, that I could encounter, in the Java Print API to achieve this task. Any further comments, suggestions or solutions are much appreciated.

eros
  • 103
  • 1
  • 11
0

Depending on which Page Description Language (PDL) your printer driver is writing you might be able to check the file for an End of Job marker.

If it's PCL then you would look for "\x1b%-12345X@PJL EOJ\n%-12345X".

For Postscript either look for "%%EOF" or "\x04" (ascii end of text, might also occur at start of job).

hwilcox
  • 138
  • 7