Related to this question
Java writing to a deleted file
only in my case i'm doing the reading. And per that comment, yes, Windows block deletes and Unix doesn't. and under unix never throws any IOException
the code is a poor-man's tail -f, where i have a java thread watching each log file in a directory. my current issue is if the file is deleted, i'm not handling it. I need to abort and start a new thread or something. I didn't even realize it was an issue, as the below code throws no exceptions under Unix
the code
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
String line = null;
while (true) {
try {
line = br.readLine();
// will return null if no lines added
} catch (IOException e) {
e.printStackTrace();
}
if (line == null) {
// sleep if no new lines added to file
Thread.sleep(1000);
} else {
// line is not null, process line
}
}
Tomorrow I'll try adding this check before the sleep, maybe is sufficient
if (!f.exists()) {
// file gone, aborting this thread
return;
}
Anyone have other ideas?
When you reach the end of a file, BufferedReader should always return a null whether it has been deleted or not. Its not something you should have to check for.
Can you show us some code because its very hard to stop the BufferedReader not returning a null?
This program
public class Main {
public static void main(String... args) throws IOException {
PrintWriter pw = new PrintWriter("file.txt");
for (int i = 0; i < 1000; i++)
pw.println("Hello World");
pw.close();
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
br.readLine();
if (!new File("file.txt").delete())
throw new AssertionError("Could not delete file.");
while (br.readLine() != null) ;
br.close();
System.out.println("The end of file was reached.");
}
}
On windows prints
AssertionError: Could not delete file.
On Linux prints
The end of file was reached.
You could watch your directory using WatchService API for changes and act accordingly
Related
I wrote some code to open and read the content of a csv file:
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream(fileName)));
String line;
try {
line = bufferedReader.readLine();
while (line != null) {
line = bufferedReader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// close buffered reader
}
The code is working fine in unit tests, no exception is raised. However once I try to launch the program via cmd it throws a NPE coming from InputStreamReader:
Exception in thread "main" java.lang.NullPointerException
at exercise.FileLoader.loader(FileLoader.java:28)
at exercise.Application.main(Application.java:22)
The program takes actually the file name as parameter:
public static void main(String[] args) {
if (args.length > 1) {
System.out.println("Too many input arguments.");
System.exit(-1);
}
String fileName = args[0];
//here runs the method who reads the csv file above
}
Could you tell me what is happening ?
The following reads not a File on the file system, but a resource on the class path (principly read-only).
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(getClass().getResourceAsStream(fileName)));
Also the encoding is that of current platform, which might differ on another PC.
And I see no close() which probably got deleted on preparing the question.
For the file system:
Path path = Paths.get(filename);
try (BufferedReader bufferedReader =
Files.newBufferedReader(path, Charset.defaultCharset())) {
line = ...
...
} // Automatic close.
There has to be taken some care when the path is not absolute. Then it depends where the "working directory" points to, where the application is started.
I think your problem is related to the program being unable to find the file once you launch the program via cmd.
Have you tried putting the program in the same folder of the file? You could also ask for a user's input in the main so that you can provide the correct folder.
We are the using the following code to generate PDFs using wkhtmltopdf
public class SystemUtils{
public String executeCommand(String... command) {
Process process = null;
try {
// Using redirectErrorStream as true. Otherwise we have to read both process.getInputStream() and
// process.getErrorStream() in order to not exhaust the stream buffer.
process = new ProcessBuilder(command).redirectErrorStream(true).start();
process.waitFor();
StringBuilder outputBuilder = new StringBuilder();
try(BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = stdError.readLine()) != null) {
outputBuilder.append(line).append(StringConstants.CARRIAGE_RETURN);
}
}
return outputBuilder.toString();
} catch (IOException | InterruptedException e) {
String exceptionMsg = "Error while executing command '"+command+"' : ";
LOGGER.error(exceptionMsg, e);
throw new AppException(exceptionMsg, e);
} finally {
if(process != null){
process.destroy();
}
}
}
public static void main(String[] args){
SystemUtils systemUtils = new SystemUtils();
String[] array = {"wkhtmltopdf", "/home/pgullapalli/Desktop/testsimilar1.html", "/home/pgullapalli/Desktop/test.pdf"};
systemUtils.executeCommand(array);
}
}
This works absolutely fine for smaller size files. But when we try to process a larger file, it is indefinitely waiting without any response. I am not sure what is going wrong? Can someone please suggest?
I moved process.waitFor() before the return statement and it started working. This probably could be happening as the output buffer has filled and we are not reading from it. After moving the process.waitFor after the stream reading, things are working fine.
Well, i'm working a project to test my knowledge of java programming.
My project is a game and i'm making some kind of launcher for it that closes when the project has fully booted. I searched on the web to see how i check if a java program is running or not. I found a way to see if a program is running (here is the link to it or see code below). I tested it but it didn't work so i searched for the answer to check if a process/program is running under a "bigger" program (exemple: multiple windows in firefox). I didn't find it so i hope that you know the answer.
Here is the way to check if a program is running that i found (And here is the link again):
String line;
String pidInfo ="";
Process p =Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"tasklist.exe");
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
pidInfo+=line;
}
input.close();
if(pidInfo.contains("file.class"))
{
// do what you want
}
Instead of checking whether the game process is running (Which isn't so possible with the pid, since that's a number), you can check the contents of a file:
File f = new File("path_to_file.txt");
BufferedReader br;
String text = "";
try {
br= new BufferedReader(new FileReader(f));
String line;
while((line = br.readLine())!=null){
text+=line;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(text.equals("started")){
// we have to make sure it can work next time so we clear the file's contents
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
bw.write("");
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
//close launcher
}
And then the only thing left to do is have the game write to that file the text "started" after it has started.
I try to get my penplotter to work from within java.
I have a start but I don't know how to continue.
This is what I have:
public static void main(String[] args) {
try {
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec("chiplotle");
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
System.out.println("this prints fine");
while ((line = in.readLine()) != null) {
System.out.println(line);
}
System.out.println("it never reaches this...");
}
catch (IOException e) {
e.printStackTrace();
}
}
This is the output in the console:
I typed the 11 myself. But it doesn't do anything with it.
Also it never prints:
System.out.println("it never reaches this...");
So it looks like my program is halted for input, is that correct?
And how can I get further?
You should read from the InputStream in a bacgkround thread.
You need to get the Process's OutputStream and then write to it.
OutputStream os = process.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
PrintWriter pw = new PrintWriter(bw);
// now you can write to the Process, i.e., pw.println("11");
You will need to not just print but also to analyze the text that your InputStream sends you to decide when to write back to the process via the PrintWriter.
I have a project where program has to open notepad file and after entering text and saving that notepad file program should display number of words in that file and it should delete the entered content in the file.
iam getting this error Error not derjava.lang.NullPointerException after running the program.
though after entering some text in Mytext.txt and saving it?
my question is why BufferedReader is reading empty file even though iam saving the file with some content.
Appreciate the help..
public class Notepad_Example {
public static void main(String[] jfb) {
try {
ProcessBuilder proc = new ProcessBuilder("notepad.exe", "C:\\Java Projects\\Reverse String\\src\\Mytext.txt");
proc.start();
BufferedReader br;
String s;
br = new BufferedReader(new FileReader("C:\\Java Projects\\Reverse String\\src\\Mytext.txt"));
s = br.readLine();
char c[] = new char[s.length()];
int j = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != ' ') {
c[i] = s.charAt(i);
} else {
j++;
}
}
System.out.println("number of words are " + (j + 1));
br.close();
} catch (Exception hj) {
System.out.println("Error not der" + hj);
}
try {
FileWriter fw = new FileWriter("C:\\Java Projects\\Reverse String\\src\\Mytext.txt");
fw.close();
} catch (Exception hj) {
System.out.println("Error not der" + hj);
}
}
}
The issue you are having is here:
ProcessBuilder proc=new ProcessBuilder("notepad.exe","C:\\Java Projects\\Reverse String\\src\\Mytext.txt");
proc.start();
proc.start() is returning the freshly started process. You'll have to give the user the chance to edit and save the file and close the editor before you can read from that file. That is you have to wait for that process to finish before you can start using the results (the saved file) of that process.
So do instead something like this:
Process process = proc.start();
int result = process.waitFor();
if (result == 0) {
// Do your rest here
} else {
// give error message as the process did not finish without error.
}
Some further remarks:
The rest of your code also appears to have some issues.
You are only reading one line of that file. What if the user is using new lines?
The exception handling is not very good, at the very least print the stack trace of the exception which will give you further hints of where an exception was occuring
If you are using Java 7, read on try with resources; if you are using Java 6, add finally blocks to make sure your resources (the streams) are getting closed.
When you run proc.start(); it is not going to block and waitfor the process to end, it will continue running.
You will need to call the proc.waitFor() method, to block until it has finished.
NOTE
we have had some weird behaviour when using the process builder...
we used to start the process with a
new ProcessBuilder("notepad.exe", "C:\\Java Projects\\Reverse String\\src\\Mytext.txt");
but that started to fail wen we upgraded to Win7 and Java7 - we we not sure where this problem really originated, but we changed out Code like this:
String[] cmd = new String[]{"notepad.exe", "C:\\Java Projects\\Reverse String\\src\\Mytext.txt"};
new ProcessBuilder(cmd);
and since then it worked correct!