How to write to a locked file in Java? - java

I'm writting in a file that has the .csv extension . The function that writes in the file is called from a timer that checks continuosly some conditions and updates the file. However, if the user decides to open that file while the timer is running I will obviously get an exception.
Is there a possibility to avoid this and update the file so that the user will see the updated file when reopens the file ?
EDIT:
Timer=new Timer(5000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
Display.getDefault().asyncExec(new Runnable(){
#Override
public void run()
{
//Here I check the conditions
checkConditions();
if(checkConditions())
{
writeInFile();
}
}
}
}
EDIT(2):
public void writeInFile()
{
File firstFile=new File("file location");
BufferedWriter out_firstFile = null;
FileWriter firstFileStream;
firstFileStream= new FileWriter(firstFile, false);
out_firstFile = new BufferedWriter(firstFileStream);
out_firstFile.write("Here I write something :) ");
out_firstFile.close();
}

First of all your statement "However, if the user decides to open that file while the timer is running I will obviously get a FileNotFound exception." is absolutely not obvious.
What do you call "open the file". If user opens file using text editor or one of the viewing tools it depends on the tool. For example either less of Unix or Notepad from MS Windows just read the file and do not even lock it. Howerver other tools can lock the file, so you indeed will not be able to write to it, but I think that the exception will be different.
So, I'd change your question to the following "How to write to locked file?".
And the short answer is "you cannot write to the locked file."
The solution that I can suggest is to implement re-try mechanism. If for example you cannot write to file because it is locked at the moment, write your content to temporary file and try again, and again ... and again until you succeed.

Related

When reading an external PDF with an Android App it always shows the same version, even after updating the PDF

Please donĀ“t be too harsh to me concerning any mistakes with this question since thats my first one here.
So basically what i want to do is reading/showing a PDF document in my Android App after pressing a button. The PDF is located on a Raspberry Pi 3 and i found a code example on this thread how to read it.
Before accessing it however, i call a python script on the Raspi which is (re)creating the PDF based on a database.
So the user presses the button in the App and sees a PDF which presents the current state of a database table.
Now i got the following code in my Activity to call the script and read the PDF:
new AsyncTask<Integer, Void, Void>(){
#Override
protected Void doInBackground(Integer... params) {
try {
executeRemoteCommand("user","pw","ip", port, "command to execute the python script");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}.execute(1);
//waiting for the PDF to be created
handler.postDelayed(new Runnable() {
#Override
public void run() {
String url = "http://IP/path/file.pdf";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
}, 5000);
With this code connecting to the Raspberry, executing the python script, thus updating the database and reading the PDF file works just fine.
But i have the following problem:
When i close the PDF view in my App, add something to the database and press the executing button again the PDF file itself is being updated (i checked that on the Raspberry) but then the App still shows the old version of it. Even when i restart the App and execute this again it still shows the first version of the PDF...
Does anyone have an idea why and how to fix this?
Is there any kind of cache which stores the PDF and just shows the same every time i read from the Raspberry?

Check for existing file with a loop

I'd like to check for an existing file using a while loop. Now the problem is, that if use something like this:
while (file.exists()) {
text.setText("Some text appears");
text.setTextColor(Color.RED);
}
my program always seem to not to respond at all. Is it because my loop is somehow an infinite loop? Or why is is not working correctly.
Right now, i am using a simple if statement but i don't like it that way, because it is not updated right away when the file exists.
EDIT:
What i want is:
I offer a file to download. In my app, there is a text which says "Not Available yet". I want to change the text right after the file exists to something like "File is Available".
If you want to check periodically if a file exists, you have to do this with an asynchronous task or a timer.
TTimerTask task = new TimerTask() {
#Override
public void run() {
// Here you do whatever you want
}
};
Timer timer = new Timer();
timer.schedule(task, 0,30000);
This will check the file every thirty seconds.
You can find more info on http://www.mkyong.com/java/jdk-timer-scheduler-example/
Your program goes in an infinite loop as the condition inside while loop will always be true if the file is present..
You need to check like this:
File file = new File(subDir.getPath() + "somefile.txt");
boolean exists = file.exists();
if (!exists) {
// It returns false if File or directory does not exist
}
else
{
//Update here
}
And if you want to check it inside the loop then try like this:
while (true)
{
File file = new File(subDir.getPath() + "somefile.txt");
boolean exists = file.exists();
if (!exists) {
// It returns false if File or directory does not exist
return;
}
else
{
//Update here
}
}
If the file exists, then it'll pop into the while loop and will keep on looping because the file exists, you'll have to make the file non-existable within the while loop...
Best thing for you to do, is get your program working without the while loop... as you mentioned with an IF function, then slowly over time implement (Test) a new function (while loop) into the equation.
What you need to fix in the while loop is... What happens to the file when it enters the loop and how does it get out of the loop. Current standing is, it doesn't as the file still exists.
Ok so whenever the other person is checking for the file does the program exit if the file doesn't exist? I mean you can't just have it checking for the file forever. I suppose you could put it in a Thread and run it with a slight wait inside the while loop but the overhead... sheesh!
Is this a specific screen inside your program? Is the person suppose to be able to exit this "file found/not found" page? I could probably write a snippet but I need more info. :)

JFileChooser in LibGDX

I'm trying to use Javas JFileChooser in my LibGDX scene2d project, but as soon as I launch JFileChooser my program freezes.
Here is the code I use to launch file chooser:
private String getPath(){
String path = "";
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = fc.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
try {
path = file.getAbsolutePath();
} catch (Exception ex) {
System.out.println("problem accessing file" + file.getAbsolutePath() + "\n" + ex.getMessage());
}
} else {
System.out.println("File access cancelled by user.");
}
return path;
}
is it swing and libgdx compability problem or is there something I am missing? Same code works perfectly with nativa java projects.
Except instead of: fc.showOpenDialog(null);
I use: fc.showOpenDialog(button); // button is the JButton that triggers the event.
any idea what am I doing wrong?
EDIT: I don't really mind if it wont work on other platforms than Windows.
BUT if I choose to go with cross platform solution, and use LibGDX's method, do I have to create file chooser class with UI from scratch all by myself?
Ok based on your comments from the answer above I get a sense that what you are trying to do is invoke a swing window INSIDE your LibGDX game window, which is an open GL rendering scene.
Let me stop you right there. The swing toolkit invokes its own rendering engine, because it's not intended for this purpose at all - it's intended for desktop applications. So when you instantiate the dialogue, all sorts of other oracle java stuff gets instantiated along with it, like the Graphics2D class. You can't just add this class to a scene2D stage and expect that it draws. They don't implement the same interfaces or inherit from the same base classes. The draw(Graphics2D graphics) method that your JFileChooser implements is not the same as whatever draw(SomeClass foo) method that your libGDX classes implement.
So if you want to make a file chooser window, you need to start looking at the libGDX widget libraries. There might be something that someone has put together already, but my approach for my next libGDX project is going to be to extend these classes for my own UI libraries. I don't know what your project is, or what your timeline is like, but it's certainly a better approach then trying to adapt the swing toolkit to render in an OpenGL rendering scene.
edit
After some quick reading, I'm going to go one further and hazard a guess that the way the swing toolkit gets rendered is entirely dependent on the implementation of the JVM for a specific platform. Now this is where my CS knowledge starts to be a little limited, but I would hazard another guess that this is way way different than the LWJGL implementation of OpenGl by way of using Java wrappers for C libraries.
Personally I dislike the existing FileChooser UIs inside LibGDX. So I created a solution which works using the JFileChooser. Here is some quick and dirty code:
new Thread(new Runnable() {
#Override
public void run() {
JFileChooser chooser = new JFileChooser();
JFrame f = new JFrame();
f.setVisible(true);
f.toFront();
f.setVisible(false);
int res = chooser.showSaveDialog(f);
f.dispose();
if (res == JFileChooser.APPROVE_OPTION) {
//Do some stuff
}
}
}).start();
This will open the FileChooser in front of the LibGDX window without blocking the main Thread. Just tested this on Windows 7, 8, 10 and it only works in window mode ofc.
Coming late to the party but if the point of the question is to invoke a "native" ie. non-gdx file chooser from a libgdx project I made a library to do so here: https://github.com/spookygames/gdx-nativefilechooser.
Example from the readme:
// Configure
NativeFileChooserConfiguration conf = new NativeFileChooserConfiguration();
// Starting from user's dir
conf.directory = Gdx.files.absolute(System.getProperty("user.home"));
// Filter out all files which do not have the .ogg extension and are not of an audio MIME type - belt and braces
conf.mimeFilter = "audio/*";
conf.nameFilter = new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return name.endsWith("ogg");
}
};
// Add a nice title
conf.title = "Choose audio file";
fileChooser.chooseFile(conf, new NativeFileChooserCallback() {
#Override
public void onFileChosen(FileHandle file) {
// Do stuff with file, yay!
}
#Override
public void onCancellation() {
// Warn user how rude it can be to cancel developer's effort
}
#Override
public void onError(Exception exception) {
// Handle error (hint: use exception type)
}
});
On the desktop, this example will currently launch an AWT FileDialog (not exactly what is asked) yet a Swing version is currently on the master branch and should be incorporated to the next version of the lib.

How to close external programs (Powerpoint) running on the native desktop using Java?

I have to create an application that will automatically open a powerpoint file, let it play through, and then close it. Not only do I need to figure out HOW to close it, but I also must detect when it closes or stops.
First option:
I know how long each powerpoint will play for, so I can hardcode when to close the file. I just need to know how to do that. There are no methods in the desktop class (that I could find) for closing.
Second option:
If someone knows a microsoft powerpoint api that lets me open powerpoints and use java to progress through the slideshow and get the state or something, that'd be great. I wouldn't have to go into each presentation and count the number of slides and the transition timer on each slide.
The opening, letting it play, and closing it is a small part of the app I need to create. But here is what I have so far with regards to THIS problem:
File myfile = new File("PowerPoint.ppsx");
try {
Desktop.getDesktop().open(myfile);
} catch (IOException ex) {
Logger.getLogger(Sc.class.getName()).log(Level.SEVERE, null, ex);
}
Probably this is the solution how to close external program:
http://www.java-forums.org/new-java/59691-close-another-program.html#post285956
If you want to detect when program has stopped running then you can start new thread with loop which from time to time will check if the program process is still running, using the same method as mentioned in link.
This is solution only for one (Windows) platform, Java is not the best choice for such tasks.
Here a solution using JNA. First we get the handle, we search using the "class name" of the window. You can determine the class name for a specific program (in this case Powerpoint) with a special utility like Spy++ (included with Visual Studio). It's possible to make the search more precise using the class name and the window caption (but here I use only the class name) so if you have more than one presentation running ... you may not close the good one!.
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinDef.HWND;
// https://github.com/twall/jna#readme
// you need 2 jars : jna-3.5.1.jar and platform-3.5.1.jar
public class KillMyPP {
public static void main(String[] args) {
HWND hwnd = User32.INSTANCE.FindWindow("screenClass", null);
if (hwnd == null) {
System.out.println("PPSX is not running");
}
else {
User32.INSTANCE.PostMessage(hwnd, WinUser.WM_QUIT, null, null);
}
}
}

Problem with java.awt.Desktop

I have a button in my program that, when pressed, is supposed to take you to my wiki page about the program. I used the following line to do so:
java.awt.Desktop.getDesktop().browse(new java.net.URI("http://supuh.wikia.com/wiki/BHT"));
The problem is that, no matter what environment in which the program is run, I always get the following error:
java.security.AccessControlException: access denied (java.awt.AWTPermission showWindowWithoutWarningBanner)
does anyone know how I can fix this? Note that this only works in the one program. Any other program I make can use the same method with no problem.
Exit hook
At the start of my program, this hook is added. The program runs fine without it...
System.setSecurityManager(new SecurityManager()
{
#Override
public void checkExit(int status)
{
closeFile(status);
}
});
this hook is needed, but the browse(URI uri) method in question won't work with it. Solutions?
This means you are running with a security manager:
SecurityException - if a security manager exists and it denies the AWTPermission("showWindowWithoutWarningBanner") permission, or the calling thread is not allowed to create a subprocess; and not invoked from within an applet or Java Web Started application
If this is an applet, or a Java Web Start app - sign your jar.
Update Adding a security manager to detect program exit is wrong. There are multiple ways to do this properly. In your case I guess this would be most appropriate:
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
closeFile();
}
));
Swing-specific solutions are:
if you don't have to perform extra actions, use frame.setDefaultCloseAction(Frame.EXIT_ON_CLOSE)
use addWindowStateListener and check for WindowEvent.WINDOW_CLOSED
That said, two notes:
you must not hold files open for a long time. Use try/catch/finally to open and close them whenever they are needed.
if you really need a security manager at some point, make sure you override the appropriate method of the SecurityManager that checks whether you can open the link. (won't tell you which one, so that you are not tempted to jump onto this solution, which is wrong)
To summarize, I'd go for setDefaultActionOnClose, and close each file right after I finish reading/writing it.
Update 2: After you linked to your original question describing what exactly are you trying to achieve, things change a bit. You are trying to prevent exit, so you do need a SecurityManager. This makes it so that you should override the checkPermission method and do nothing there (i.e. don't throw exceptions), at least when these permissions are checked (they are checked when browse is called):
new AWTPermission("showWindowWithoutWarningBanner")
new FilePermission("<<ALL FILES>>", SecurityConstants.FILE_EXECUTE_ACTION)
Update 3 Here's how exactly to override the method:
#Override
public void checkPermission(Permission permission) {
if (permission instanceof AWTPermission) {
if (permission.getName().equals("showWindowWithoutWarningBanner")) {
return;
}
}
if (permission instanceof FilePermission) {
if (permission.getActions().equalsIgnoreCase("execute")) {
return;
}
}
java.security.AccessController.checkPermission(permission);
}
(you can go without the outer if-s)
Update 4 The above method will work only if you have given permissions to your program. Otherwise it is a not-well documented behaviour of the JVM that overriding security managers are not allowed to be unprivileged. Take a look at this report - the comments say how to work it around.
To make your life simpler, you can simply #Override public void checkPermission(..) with an empty method body.
Instead of using your own SecurityManager, install a shutdown hook instead:
Runnable runnable = new Runnable() {
closeFile(status);
}
Runtime.getRuntime().addShutdownHook(new Thread (runnable, "Close file"));

Categories