I have been trying this for hours and I don't know what to do. I'm creating a Minecraft Bukkit plugin which it's supposed to have a "restart" command, which sends some warning messages and after that I would like to close the server. I created a batch file to do it but, I want Java to do it for me when the warnings are over, something like, idk:
open("C:/Users/Blablabla/Desktop/close.bat");
And for the moment I have this:
public String document = "C:/Users/Joan-Server/Desktop/Server/closer.bat";
if (args[0].equalsIgnoreCase("restart")) {
while(x != 0) {
Bukkit.broadcastMessage(plugin.name + ChatColor.GOLD + "¡ATENCIÓN! " + ChatColor.WHITE + "Reinicio del servidor en "
+ ChatColor.RED + x + " segundos.");
//Try--
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
x = x - 1;
}
//Try--
}
You could use something like this to execute your bat file:
try{
Process p = Runtime.getRuntime().exec("C:/path/to/file.bat");
p.waitFor();
}catch( IOException ex ){
//Catch if file doesn't exist or is inaccessible
}
catch( InterruptedException ex ){
//If the p.waitFor() is interrupted
}
Use this to execute your restart script and you should be good to go! Assuming your restart script stops the server, waits, and starts the server again.
Let me know if you need anything else!
You could also do your restart directly from your plugin via
getServer().dispatchCommand(getServer().getConsoleSender(), "restart");
If you really want to run the batch file, use
Runtime.getRuntime().exec("C:\\Users\\Blablabla\\Desktop\\close.bat");
If you also want to handle the console output of the bat file, check out this answer.
My program is attempting to scan through my directory in search of the existence of .cmp or .txt files.
If fileName were to equal "test" and if neither test.cmp nor test.txt files existed, my program would still throw a FileNotFoundException despite my try-catch block under the first catch. I've tried moving the second try-catch block around, but nothing seems to work – everything I test the code out with a file that doesn't exist still ends up throwing an exception.
public int checkFileExistence() {
BufferedReader br = null;
int whichFileExists = 0;
try {//check to see if a .cmp exists
br = new BufferedReader(new FileReader(fileName + ".cmp"));
whichFileExists = 0;// a .cmp exists
}
catch (IOException e){ //runs if a .cmp file has not been found
try {//check to see if a .txt file exists
br = new BufferedReader(new FileReader(fileName + ".txt"));
whichFileExists = 1;//a .txt file exists
}
catch (IOException e2) {//if no .txt (and .cmp) file was found
e2.printStackTrace();
whichFileExists = 2; //no file exists
}
}
finally {
try {
br.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return whichFileExists;
}
I would expect the program to work, but each time I test the program, the program throws a FileNotFoundException where it says "test.txt" doesn't exist.
It is printing that exception because of this line:
e2.printStackTrace();
It's working as you are expecting, just printing the error it got. You can remove these printStackTrace() calls if you don't want to see them. Well, don't remove the one in the last catch block, otherwise you would never know if there is a problem there.
On a separate note, this design is totally based on exceptions, which is not recommended. I'm sure there are methods in the File class to check for existence of files.
This program is working as expected...
catch (IOException e2) {//if no .txt (and .cmp) file was found
e2.printStackTrace();
whichFileExists = 2; //no file exists
}
Above catch clause catches your IOException and prints it with e2.printStackTrace();
I have a executable program made on C++ (cf.exe) that takes parameters from a few text files (.txt), performs some calculations, and creates a file with the results (results.txt). This program needs no interaction. Once executed, when the calculations are done, it's automatically closed.
Then, I have other program made on Java, which contains a button that executes the cf.exe. When the button is pressed the following method is called:
public void executeExternalProgram(){
String filePath = "C++" + File.separator + "cf.exe";
try {
System.out.println("Executing C++ exe...");
Process p = Runtime.getRuntime().exec(filePath);;
} catch (Exception e) {
e.printStackTrace();
}
}
I don't get any error, but the cf.exe is not being executed when I press the button. When I execute manually the cf.exe, the results file is correctly created. Furthermore, I've tried to copy other programs, such as notepad.exe, to the same folder and execute it through Java without any problem. Can anyone see why it's not working?
I found that changing the command given to the process makes it work correctly. The change is the following:
Process p = Runtime.getRuntime().exec("cmd /c start "+ filePath);
Then, the updated code for the method called when the button is pushed:
public void executeExternalProgram(){
String filePath = "C++" + File.separator + "cf.exe";
try {
System.out.println("Executing C++ exe...");
Process p = Runtime.getRuntime().exec("cmd /c start "+ filePath);
} catch (Exception e) {
e.printStackTrace();
}
}
I am using the following code to write to a file from a servlet in Tomcat container. I don't worry if the file gets overwritten during each deploy.
BufferedWriter xml_out = null;
try {
xml_out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(getServletContext().getRealPath("/")
+ File.separator + "WEB-INF" + File.separator
+ "XML.xml"), "UTF8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
xml_out.write(xml);
xml_out.flush();
xml_out.close();
} catch (IOException e) {
e.printStackTrace();
}
However, the file writing is not successful (it doesn't get written in the hard disk). Also, there isn't any exception that gets caught! Is there some security thing in Tomcat that is preventing the file from being written ?
Your code has both "/" and the windows file separator at the start of the filename passed to getRealPath(), Java interprets slashes in filenames according to the current OS.
Not using the file separators might give a better result:
String filename = getServletContext().getRealPath("/WEB-INF/XML.xml");
log.debug("Using XML file: " + filename);
xml_out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename),"UTF8"));
Using a separate variable for the filename lets you log it so you can see unexpected results early in de development process.
I has the same issue.
this link helped me to understand where the file was in the hard disk.
Specifically for me, it put the file in the location that is returned by this line:
System.getProperty("user.dir");
In my case the location was: C:\Users\Myself\programming\eclipse for java
I'm trying to delete a file, after writing something in it, with FileOutputStream. This is the code I use for writing:
private void writeContent(File file, String fileContent) {
FileOutputStream to;
try {
to = new FileOutputStream(file);
to.write(fileContent.getBytes());
to.flush();
to.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
As it is seen, I flush and close the stream, but when I try to delete, file.delete() returns false.
I checked before deletion to see if the file exists, and: file.exists(), file.canRead(), file.canWrite(), file.canExecute() all return true. Just after calling these methods I try file.delete() and returns false.
Is there anything I've done wrong?
Another bug in Java. I seldom find them, only my second in my 10 year career. This is my solution, as others have mentioned. I have nether used System.gc(). But here, in my case, it is absolutely crucial. Weird? YES!
finally
{
try
{
in.close();
in = null;
out.flush();
out.close();
out = null;
System.gc();
}
catch (IOException e)
{
logger.error(e.getMessage());
e.printStackTrace();
}
}
It was pretty odd the trick that worked. The thing is when I have previously read the content of the file, I used BufferedReader. After reading, I closed the buffer.
Meanwhile I switched and now I'm reading the content using FileInputStream. Also after finishing reading I close the stream. And now it's working.
The problem is I don't have the explanation for this.
I don't know BufferedReader and FileOutputStream to be incompatible.
I tried this simple thing and it seems to be working.
file.setWritable(true);
file.delete();
It works for me.
If this does not work try to run your Java application with sudo if on linux and as administrator when on windows. Just to make sure Java has rights to change the file properties.
Before trying to delete/rename any file, you must ensure that all the readers or writers (for ex: BufferedReader/InputStreamReader/BufferedWriter) are properly closed.
When you try to read/write your data from/to a file, the file is held by the process and not released until the program execution completes. If you want to perform the delete/rename operations before the program ends, then you must use the close() method that comes with the java.io.* classes.
As Jon Skeet commented, you should close your file in the finally {...} block, to ensure that it's always closed. And, instead of swallowing the exceptions with the e.printStackTrace, simply don't catch and add the exception to the method signature. If you can't for any reason, at least do this:
catch(IOException ex) {
throw new RuntimeException("Error processing file XYZ", ex);
}
Now, question number #2:
What if you do this:
...
to.close();
System.out.println("Please delete the file and press <enter> afterwards!");
System.in.read();
...
Would you be able to delete the file?
Also, files are flushed when they're closed. I use IOUtils.closeQuietly(...), so I use the flush method to ensure that the contents of the file are there before I try to close it (IOUtils.closeQuietly doesn't throw exceptions). Something like this:
...
try {
...
to.flush();
} catch(IOException ex) {
throw new CannotProcessFileException("whatever", ex);
} finally {
IOUtils.closeQuietly(to);
}
So I know that the contents of the file are in there. As it usually matters to me that the contents of the file are written and not if the file could be closed or not, it really doesn't matter if the file was closed or not. In your case, as it matters, I would recommend closing the file yourself and treating any exceptions according.
There is no reason you should not be able to delete this file. I would look to see who has a hold on this file. In unix/linux, you can use the lsof utility to check which process has a lock on the file. In windows, you can use process explorer.
for lsof, it's as simple as saying:
lsof /path/and/name/of/the/file
for process explorer you can use the find menu and enter the file name to show you the handle which will point you to the process locking the file.
here is some code that does what I think you need to do:
FileOutputStream to;
try {
String file = "/tmp/will_delete.txt";
to = new FileOutputStream(file );
to.write(new String("blah blah").getBytes());
to.flush();
to.close();
File f = new File(file);
System.out.print(f.delete());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
It works fine on OS X. I haven't tested it on windows but I suspect it should work on Windows too. I will also admit seeing some unexpected behavior on Windows w.r.t. file handling.
If you are working in Eclipse IDE, that could mean that you haven't close the file in the previous launch of the application. When I had the same error message at trying to delete a file, that was the reason. It seems, Eclipse IDE doesn't close all files after termination of an application.
Hopefully this will help. I came across similar problem where i couldn't delete my file after my java code made a copy of the content to the other folder. After extensive googling, i explicitly declared every single file operation related variables and called the close() method of each file operation object, and set them to NULL. Then, there is a function called System.gc(), which will clear up the file i/o mapping (i'm not sure, i just tell what is given on the web sites).
Here is my example code:
public void start() {
File f = new File(this.archivePath + "\\" + this.currentFile.getName());
this.Copy(this.currentFile, f);
if(!this.currentFile.canWrite()){
System.out.println("Write protected file " +
this.currentFile.getAbsolutePath());
return;
}
boolean ok = this.currentFile.delete();
if(ok == false){
System.out.println("Failed to remove " + this.currentFile.getAbsolutePath());
return;
}
}
private void Copy(File source, File dest) throws IOException {
FileInputStream fin;
FileOutputStream fout;
FileChannel cin = null, cout = null;
try {
fin = new FileInputStream(source);
cin = fin.getChannel();
fout = new FileOutputStream(dest);
cout = fout.getChannel();
long size = cin.size();
MappedByteBuffer buf = cin.map(FileChannel.MapMode.READ_ONLY, 0, size);
cout.write(buf);
buf.clear();
buf = null;
cin.close();
cin = null;
fin.close();
fin = null;
cout.close();
cout = null;
fout.close();
fout = null;
System.gc();
} catch (Exception e){
this.message = e.getMessage();
e.printStackTrace();
}
}
the answer is when you load the file, you need apply the "close" method, in any line of code, works to me
There was a problem once in ruby where files in windows needed an "fsync" to actually be able to turn around and re-read the file after writing it and closing it. Maybe this is a similar manifestation (and if so, I think a windows bug, really).
None of the solutions listed here worked in my situation. My solution was to use a while loop, attempting to delete the file, with a 5 second (configurable) limit for safety.
File f = new File("/path/to/file");
int limit = 20; //Only try for 5 seconds, for safety
while(!f.delete() && limit > 0){
synchronized(this){
try {
this.wait(250); //Wait for 250 milliseconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
limit--;
}
Using the above loop worked without having to do any manual garbage collecting or setting the stream to null, etc.
The problem could be that the file is still seen as opened and locked by a program; or maybe it is a component from your program that it had been opened in, so you have to ensure you use the dispose() method to solve that problem.
i.e. JFrame frame;
....
frame.dispose();
You have to close all of the streams or use try-with-resource block
static public String head(File file) throws FileNotFoundException, UnsupportedEncodingException, IOException
{
final String readLine;
try (FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
LineNumberReader lnr = new LineNumberReader(isr))
{
readLine = lnr.readLine();
}
return readLine;
}
if file.delete() is sending false then in most of the cases your Bufferedreader handle will not be closed. Just close and it seems to work for me normally.
I had the same problem on Windows. I used to read the file in scala line by line with
Source.fromFile(path).getLines()
Now I read it as a whole with
import org.apache.commons.io.FileUtils._
// encoding is null for platform default
val content=readFileToString(new File(path),null.asInstanceOf[String])
which closes the file properly after reading and now
new File(path).delete
works.
FOR Eclipse/NetBeans
Restart your IDE and run your code again this is only trick work for me after one hour long struggle.
Here is my code:
File file = new File("file-path");
if(file.exists()){
if(file.delete()){
System.out.println("Delete");
}
else{
System.out.println("not delete");
}
}
Output:
Delete
Another corner case that this could happen: if you read/write a JAR file through a URL and later try to delete the same file within the same JVM session.
File f = new File("/tmp/foo.jar");
URL j = f.toURI().toURL();
URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF");
URLConnection c = u.openConnection();
// open a Jar entry in auto-closing manner
try (InputStream i = c.getInputStream()) {
// just read some stuff; for demonstration purposes only
byte[] first16 = new byte[16];
i.read(first16);
System.out.println(new String(first16));
}
// ...
// i is now closed, so we should be good to delete the jar; but...
System.out.println(f.delete()); // says false!
Reason is that the internal JAR file handling logic of Java, tends to cache JarFile entries:
// inner class of `JarURLConnection` that wraps the actual stream returned by `getInputStream()`
class JarURLInputStream extends FilterInputStream {
JarURLInputStream(InputStream var2) {
super(var2);
}
public void close() throws IOException {
try {
super.close();
} finally {
// if `getUseCaches()` is set, `jarFile` won't get closed!
if (!JarURLConnection.this.getUseCaches()) {
JarURLConnection.this.jarFile.close();
}
}
}
}
And each JarFile (rather, the underlying ZipFile structure) would hold a handle to the file, right from the time of construction up until close() is invoked:
public ZipFile(File file, int mode, Charset charset) throws IOException {
// ...
jzfile = open(name, mode, file.lastModified(), usemmap);
// ...
}
// ...
private static native long open(String name, int mode, long lastModified,
boolean usemmap) throws IOException;
There's a good explanation on this NetBeans issue.
Apparently there are two ways to "fix" this:
You can disable the JAR file caching - for the current URLConnection, or for all future URLConnections (globally) in the current JVM session:
URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF");
URLConnection c = u.openConnection();
// for only c
c.setUseCaches(false);
// globally; for some reason this method is not static,
// so we still need to access it through a URLConnection instance :(
c.setDefaultUseCaches(false);
[HACK WARNING!] You can manually purge the JarFile from the cache when you are done with it. The cache manager sun.net.www.protocol.jar.JarFileFactory is package-private, but some reflection magic can get the job done for you:
class JarBridge {
static void closeJar(URL url) throws Exception {
// JarFileFactory jarFactory = JarFileFactory.getInstance();
Class<?> jarFactoryClazz = Class.forName("sun.net.www.protocol.jar.JarFileFactory");
Method getInstance = jarFactoryClazz.getMethod("getInstance");
getInstance.setAccessible(true);
Object jarFactory = getInstance.invoke(jarFactoryClazz);
// JarFile jarFile = jarFactory.get(url);
Method get = jarFactoryClazz.getMethod("get", URL.class);
get.setAccessible(true);
Object jarFile = get.invoke(jarFactory, url);
// jarFactory.close(jarFile);
Method close = jarFactoryClazz.getMethod("close", JarFile.class);
close.setAccessible(true);
//noinspection JavaReflectionInvocation
close.invoke(jarFactory, jarFile);
// jarFile.close();
((JarFile) jarFile).close();
}
}
// and in your code:
// i is now closed, so we should be good to delete the jar
JarBridge.closeJar(j);
System.out.println(f.delete()); // says true, phew.
Please note: All this is based on Java 8 codebase (1.8.0_144); they may not work with other / later versions.