How do I write exceptions to a text file? (JAVA) - java

I am supposed to Use Scanner to read int values from a file “input.txt”, Read until end of file is reached, Write all program output to a file “output.txt”, Write all exceptions to a file “error.txt”, and Output each number read.
I understand exceptions for the most part, but I do not understand how to write all exceptions to a text file in Java...

Like I wrote in my comment, write a try ... catch block where you write the exception to File error.txt using Printwriter.
For instance:
PrintWriter writer = new PrintWriter("error.txt");
try {
//Code to try goes here
} catch (Exception e) {
//You've got an exception. Now print it to error.txt
writer.write(e.toString());
}
You could test with something simple like:
PrintWriter writer = new PrintWriter("error.txt");
int[] i = new int[1];
try {
i[10] = 2;
} catch (Exception e) {
writer.write(e.toString());
}
This results in error.txt being populated with:
java.lang.ArrayIndexOutOfBoundsException: 10
You can print the entire Stack Trace by doing
e.printStackTrace(writer);
Very important that you don't forget to close the PrintWriter or your file won't get printed to. Once you are done writing to the file, close with:
writer.close();

use log4j for logging purpose,
Also , configure it at Error level for printing error into different
file.
from your java code, write below line will print whole stack-track to
the log file.
commons-logging, it's use likewise:
log.error("Message", exception);

All exceptions have a method: getMessage() that will return the exception as a string. In addition, toString(), which all Java classes should have, gives a little bit more information, since it also calls getMessage().

Related

Cannot access file because being used

I'm writing a logger to my java program (in csv format).
The logger works fine, and I had one problem.
It sounds pretty logical that the program will crash when i tried to write to the file and at the same time open the file.
When i do that, I got that exception: "The process cannot access the file because it is being used by another process".
My question is if there is anyway to continue writing even if someone open the file?
Thanks.
UPDATE:
I think i solved the problem.
Every time after i write to the file (With bufferedWriter and FileWriter), I call to a close() function that closing the bufferedWriter and FileWriter.
I changed the close() function:
1. Added fileChannel and FileLock.
2. Igonore the line bw.close();
Its ok not to close the bufferWriter (bw)?, Can there be any problems later on?
private void close() throws IOException {
RandomAccessFile rf;
rf = new RandomAccessFile(file, "rw");
fileChannel = rf.getChannel();
lock = fileChannel.lock();
try {
if (bw != null) {
// bw.close(); The line i ignored.
bw = null;
}
if (fw != null) {
fw.close();
fw = null;
}
} catch (IOException ex) {
ex.printStackTrace();
}
lock.release();
}
UPDATE 2:
Now i found that if i change the function to that (close changed to flush), Its working:
private void close() {
try {
if (bw != null) {
bw.flush();
bw = null;
}
if (fw != null) {
fw.flush();
fw = null;
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
What is the best option ?
Reverse the problem: try to open while continuing writing:
if you want fixed datas, you can copy the file (by shell), and then read it;
if you want even future written datas, you must keep the same output: try to redirect the normal output, to something you can store and read.
Perhaps some library exists. It seems like tee and tpipe.
see for example:
Could I duplicate or intercept an output stream in Java?
for redirecting log4j to what you want, see this for example:
How do I redirect log4j output to my HttpServletResponse output stream?
Is there is anyway to continue writing even if something else has opened the file?
Not in Java.
To write a file, you must first open it. If you cannot open it because the OS won't permit it ... because something else has opened it ... then you cannot get to the point where you can write it.
In this scenario, you should consider opening a different log file.
Note that this scenario happens in Windows because Java is following normal Window practice and opening the file with an exclusive (mandatory) lock by default. Short of changing Java ... and every other Windows application that opens files like this ... you are stuck.
UPDATE
It turns out that there may be a way.
Read this Q&A: https://stackoverflow.com/a/22648514/139985
Use FileChannel.open as described, but use flags that allow you to write without forbidding other writers. For example
FileChannel.open(path, WRITE)
or
FileChannel.open(path, WRITE, APPEND)
The trick is that you don't want any of the NOSHARE_* options.
CAVEAT: I haven't tried this.
As #guillaume said, you can use a library like log4j.
But If you want to implements your solution in Java, you can use the observer pattern and write your logs async.

Copying a file from a location to another location

I am trying to read a file and write it to a specific folder.
I am using this code:
private void saveFile(File file){
try {
OutputStream out = new FileOutputStream(new File("/Users/default/Desktop/fotos/test.png"));
Files.copy(file.toPath(), out);
System.exit(0);
} catch (IOException ex) {
Logger.getLogger(GetFiles.class.getName()).log(Level.SEVERE, null, ex);
}
}
The file is a .png file. If I use this method it will create a new .png in the fotos directory, but when I double click it it says that it's empty.
How is this possible and how can I solve this?
You're not closing the output stream. Therefore any data buffered within it before being written out to disk will be lost.
You could use a try-with-resources statement to close the stream automatically - or you could just use:
// Alternatives, pass in the `File` to copy to, or make the method generally
// more flexible in other ways.
Files.copy(file.toPath(), Paths.get("/Users/default/Desktop/fotos/test.png"));
As an aside, it's unusual to call System.exit in a method like this - it's not like the method is saveFileAndTerminateApplication. Likewise your exception "handling" isn't ideal. I would basically let the exception bubble up, i.e. declare that your method throws it. Currently, there are three possibilities:
Everything works, and the app terminates
The copy works, but System.exit throws an unchecked exception
The copy fails, so the method returns - the caller could infer that something went wrong, but with no idea what
That doesn't sound like an obvious set of results to me...

PrintWriter--No Output?

EDIT: Fixed! Was overwriting file instead of appending to the file.
I seem to have a bit of a problem trying to use a PrintWriter to add a "header" to a log file before use, so that my program knows that it is not just a random text file. The field output_file refers to an argument taken by the logger initialization function to set the log file, whereas log_file is a static file field for the (global and static) logging class. After opening the log file to check for errors, there is no header. Using logging functions, also carried out by a PrintWriter, gives the correct output. Am I doing something wrong? (I know I am reinventing the wheel as a logging API already exists for Java, but I am working on a learning exercise.)
//After testing to make sure the file specified does not exist
log_file=output_file;
output_file.createNewFile();
PrintWriter pw=new PrintWriter(log_file);
pw.println("**[PROGRAM_NAME Log]**");
pw.flush();
pw.close();
isInitialized=true;
EDIT: The file is definitely writable, or the logger itself wouldn't work. Also, for those who were wondering, the code to log something is the following (Same general method as writing the header AKA new PrintWriter(log_file);)
PrintWriter pw = new PrintWriter(log_file);
pw.print("[INFO:] " + sdf.format(new Date())); //The variable sdf is a date formatter for timestamps.
pw.println(" " + message);
pw.close();
The documentation for PrintWriter says:
file - The file to use as the destination of this writer. If the file
exists then it will be truncated to zero size; otherwise, a new file
will be created. The output will be written to the file and is
buffered.
So every time you use new Printwriter(log_file), you are actually truncating the file, erasing everything in it, and starting fresh.
This means, of course, that as soon as you start logging, the header data gets erased.
If you want to append to the file, rather than erase it every time, you need to open a FileOutputStream with the append option, and open the PrintWriter on top of it.
try (
FileOutputStream os = new FileOutputStream(log_file, true);
PrintWriter pw = new PrintWriter(os);
) {
pw.println("Your log line here");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
(Note the use of try-with-resources to auto-close the file when work with it is done. Of course, you can just keep it opened until you finish logging. This is merely an example.).

How to append an exception's StackTrace into a file in java?

In java, when we catch a exception, we usually can use printStackTrace() method to print the error information, and we can also use printStackTrace(PrintStream out) to direct those information to a file.
But how can I append those information into a existing file, just like using out.append()?
You must open file in append mode:
try {
//...
} catch (Exception e) {
try(Writer w = new FileWriter("file.log", true)) {
e.printStackTrace(new PrintWriter(new BufferedWriter(w)));
}
}
If you are not using Java 7, you must remember about closing or at least flushing the Writer. Or you can have a global Writer, but then you must synchronize it between threads.
What about simply using some existing Java library like logback, log4j or even java.util.logging? Simply say:
} catch (Exception e) {
log.error("Opps!", e);
}
...and the framework will log the exception wherever you want, with lots of additional data like thread name, timestamp, additional message, etc. Logback can also show you from which library given stack frame comes from and even print the stack trace starting from root cause (most nested exception).
We can redirect the error stream to a file
System.setErr(new PrintStream(new FileOutputStream("errors.txt", true), true));
then Throwable.printStackTrace() will print to errors.txt.
"true" in FileOutputStream constructor means "append"; "true" in PrintStream condtructor means "autoflush". We do not need to worry about never closing FileOutputStream, OS will close it when the app ends.

Search and Replace a content in a file in JAVA

I have to edit the contents of a file and write the edited conted to another file.Here is the code iam using .
import java.io.*;
import java.util.*;
public class TestRef {
ArrayList<String> lines = new ArrayList<String>();
String line= null;
public void printThis(){
try{
FileReader fr = new FileReader("C:\\Users\\questions.txt");
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter("C:\\Users\\questions_out.txt");
BufferedWriter out = new BufferedWriter(fw);
while((line=br.readLine()) != null) {
if(line.contains("Javascript"))
line.replace("Javascript"," JAVA");
lines.add(line);
out.write(line);
}
}
catch(Exception e){}
}
public static void main(String [] args){
TestRef tr = new TestRef();
tr.printThis();
}
}
So this is like reading one line at a time and printing it back to the file. But when I execute this code the output file is blank.? Can you please provide me with a sample code, how to read from a file, make change in the content and write the whole file to a new file ?
Well, a few problems:
You're never closing either your input or your output. Closing will also flush - it's possible that something's just not being flushed. You should close stream-based resources in a finally block, so that they end up being closed even in the face of an exception. (Given that you should be closing, I wouldn't bother explicitly flushing as well. Just make sure you close the top-level abstraction - i.e. out (and br).
You're catching Exception and then swallowing it. It could well be that an exception is being thrown, but you're not able to tell because you've swallowed it. You should at least be logging it, and probably stopping at that point. (I'd also suggest catching IOException instead of Exception.)
You're using FileWriter and FileReader which doesn't allow you to specify the input/output encoding - not the issue here, but personally I like to take more control over the encodings I use. I'd suggest using FileInputStream and FileOutputStream wrapped in InputStreamReader and OutputStreamWriter.
You're calling String.replace() and ignoring the result. Strings are immutable - calling replace won't change the existing string. You want:
line = line.replace("Javascript"," JAVA");
You're never using your lines variable, and your line variable would be better as a local variable. It's only relevant within the method itself, so only declare it in the method.
Your code would be easier to follow if it were more appropriately indented. If you're using an IDE, it should be able to do this for you - it makes a huge difference in readability.
The first one is the most likely cause of your current problem, but the rest should help when you're past that. (The point about "replace" will probably be your next issue...)
You are missing out.flush().
BufferedWriters don't write anything until either you flush them, or their buffer fills up.
Close the print writer, outside the loop.
out.flush();
out.close();
Moreover you are writing strings to new lines, if you just want to replace javascript with Java, then you might also wanna write '\n', next line character to new file where old file contains new line.

Categories