Simple java Process for opening files ends inexplicably - java

Part of my program needs to open files and documents, wait until user manually closes them and then deletes them. So I have a separate thread that just opens the file with Process class and waits for the Process to end, than it deletes the file. Here is the code:
#Override
public void run() {
try {
ProcessBuilder ps=new ProcessBuilder("cmd.exe","/C",path);
Process p=ps.start();
p.waitFor();
ps=new ProcessBuilder("cmd.exe","/C","del",path);
p=ps.start();
p.waitFor();
}catch(IOException | InterruptedException e) {
e.printStackTrace();
}
}
This works with pdf, txt or docx documents, but it doesn't work with images, the png or jpg files. In case of an image, thread opens the image with Windows Photos program but doesn't wait for process to end, instead it acts like the process is already dead and proceedes to delete it right after opening it, so instead of an image I see this:
My question is why does it act like the Process is immediately dead when I open PNG or JPG files, but it works normally when I open PDF, TXT, DOCX files? Is the problem in Windows Photos viewer maybe?
I managed to open image files adding
Thread.sleep(5000);
right after opening an image, but it still deletes the image after 5 seconds, it just somehow still stays open in Windows Photos viewer even if it has been deleted. Clearly this is not the solution, I want to properly solve this situation.

You can delete the file when your program exits. Why do you want that the File is delete right after the file is closed?
File file = new File("path");
file.deleteOnExit();

Related

How to resolve java.nio.file.FileSystemException The process cannot access the file because it is being used by another process

I am getting the exception (java.nio.file.FileSystemException) while I run the this code
public String getScreenShotAsBase64() throws IOException {
File source = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
String path = System.getProperty("user.dir") + "/Screenshots/image.png";
FileUtils.copyFile(source, new File(path));
byte[] imageBytes = IOUtils.toByteArray(new FileInputStream(path));
return Base64.getEncoder().encodeToString(imageBytes);
}
when I try to run the method it is not working throws exception.
The cause of your problem is that Windows won't let your application open the "Screenshots/image.png" file for writing because something else already has it open. It just won't. See File Locking for an overview of Windows file locks and their purpose.
This SuperUser Q&A gives a number of ways to figure out which other application holds the file lock:
Find out which process is locking a file or folder in Windows
Your use of Selenium in this instance is (probably) not apropos.
You will most likely need to do one of the following to resolve this.
Change your application to write the screenshot to another file if the first target file it chooses is locked.
Tell the user that your application can't write the file. The user message could suggest that they need to close whatever other application it is that has the image file open at the moment.
If the other application is Windows itself (for some reason) you will probably need to rethink what you trying to do.

JavaFX-8 FileChooser Image (backend copy-paste)

This is only the second question I have ever posted here on Stack Overflow, so hey guys! (please be gentle).
The next step in the project I'm doing involves files and the FileChooser library. Say I got the FileChooser to work, and that on a button click, the FileChooser opens and you can select the image you want.
Now say that the image comes from a flash drive plugged in to the computer. After taking the image, the filepath is stored into the database for later retrieval. But the problem, is that the filepath will be rendered useless when the flashdrive is plugged out.
Is there any way that to do a behind the scenes copy-paste of the image to the program's directory, so that I only need to take the filename, and append that to the default varchar value (proper directory minus filename) of the filepath column in the database?
I may be wording this wrong. This is in JavaFX-8 by the way. Any help would be appreciated.
Use Files.copy
Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);
Note: source and destination are references of Path. Also, Files is located in the package java.nio.file
File source = new File("path//myimage.jpg");
File dest = new File("myimage.jpg");
try {
FileUtils.copyFile(source, dest);
} catch (IOException e) {
throw new IOException("DP Report Template File is not there");
}
This will copy the file to your program directory.

From java, how to be notified when excel spreadsheet is closed given multi spreadsheets in one instance

I have java program that starts excel spreadsheet for them command line and wait for it to be closed to take next action as below. (btw my excel runs macro so I close the spreadsheet automatically when my macro finish executing to indicate it is done)
p = Runtime.getRuntime().exec("cmd /c start /wait C:\\"+excelSheet);
p.waitFor();
System.out.print("finished "+count + " "+ excelSheet);
However I want my java program to starts 2 excel spreadsheets and each time one sheet closes, I want to take action. The problem that excel 2010 starts both spreadsheets using one instance of Excel. Therefore my java program only detects when the instance of the Excel is closed which means both spreadsheets has to close.
How can I solve it ? Whether it is Java code, Excel code, some other innovative method? Please help
Thank you
PS: I am using apache poi to write to excel before starting and read from it after closing
You can periodically open the file for writing (just open a normal FileOutputStream on it in append mode - if this raises an IOException then the file is still open)
public boolean isStillOpenOnWindows(File file) {
try {
FileOutputStream out = new FileOutputStream(file, true);
out.close();
// Not open anymore
return false;
} catch (IOException e) {
// Still open
return true;
}
}
As the name of the method implies, this is not cross-platform, it only works on Windows because Windows doesn't allow to processes to have a file open for writing at the same time.
Since you're talking about Excel, it's likely that you mean Windows, but there is Office for Mac and this trick wouldn't work on Mac OS.

Check if a file is open before reading it?

I'm trying to make an applet that reads a file on the local file system (the users computer) at a very frequent interval (several times a second), then makes the contents of the file available to the web page via javascript.
The file the applet needs to read is updated at a high frequency by a program on the user's computer. What I'm concerned about is what might happen if the applet reads data from the file when the file is in the middle of being updated.
I don't know how likely this is, but if it is a valid concern is there a way to make sure the file is not currently being written to before reading it?
I'm not positive about this, but you could try java.io.FileInputStream, or some other option from that package.
Also, this question may be a duplicate. This might answer your question:
How do I use Java to read from a file that is actively being written?
reading a file while it's being written
Read a file while it's being written
Reading data from a File while it is being written to
its very monster to make such a disk access, any way try Sockets if you can or if again you sits back try to lock file in both ends if the one of the locking fails then make sure that other is locking ,make up this to your use
File file = new File(fileName);
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
// Get an exclusive lock on the whole file
FileLock lock = channel.lock();
try {
lock = channel.tryLock();
// Ok. You get the lock
} catch (OverlappingFileLockException e) {
// File is open by other end
} finally {
lock.release();
}

How to open multiple files with Runtime Object in Java?

I open office files (docx, xlsx) by using Runtime.getRuntime().exec(String cmd) function. Simultaneously I store meta data of these files in a database. In order to keep integrity I lock the file with a flag in the meta data so that no other user concurrently can modify the file. This implies that the flag must be automatically resetted after the user closes the file (e.g. closes the external process).
Here's the snippet that opens the file:
File file = new File("c:/test.docx");
Process process = null;
if(file.getName().endsWith("docx")) {
process = Runtime.getRuntime().exec("c:/msoffice/WINWORD.EXE "+file.getAbsolutePath());
} else if(file.getName().endsWith("xlsx")) {
process = Runtime.getRuntime().exec("c:/msoffice/EXCEL.EXE "+file.getAbsolutePath());
}
if(process!=null) {
new ProcessExitListener(file, process);
}
Here's my listener that waits until the user closes the file (and finally unlocks the file by setting the flag in the meta data):
private class ProcessExitListener extends Thread {
private File file;
private Process process;
public ProcessExitListener(File file, Process process) throws IOException {
this.setName("File-Thread ["+process.toString()+"]");
this.file = file;
this.process = process;
this.start();
}
#Override
public void run() {
try {
process.waitFor();
database.unlock(file);
} catch (InterruptedException ex) {
// print exception
}
}
}
This works fine for different file types, e.g. if I open 1 docx and 1 xlsx file simultaneously. But when opening 2 docx files, one of the process exits right after it has been initialized.
Any ideas why ?
Thanks for your help in advance!
But when opening 2 docx files, one of the process exists right after it has been initialized.
Probably because winword.exe process finds out that there is already one instance of it running, so instead of keeping two instances in memory, it just asks the first instance to open the second document. Don't know how it looks from GUI perspective, but looking at the task manager, try opening two Word documents from Windows Explorer. The second file won't cause second winword.exe process to start.
I can reproduce the exact same behaviour on Ubuntu Linux. When I ran:
$ geany foo.txt
and the geany editor wasn't yet running, the console hangs until I close the editor. But if instead I open another terminal and call:
$ geany bar.txt
this returns immediately and bar.txt is simply opened as another tab in already existing process.

Categories