How to make System.err write in one block - java

I'd like to solve following issue: imagine that you are doing lots of outputs in System.out, and from time to time there is an Exception thrown. When you look into the console, you can see that the exception's trace text is mixed up with normal output done by System.out. I understand that these two are different streams (System.out and System.err) and I guess that the output of the exception is done internally by some other thread, that is why it is mixed up.
However, is it somehow possible for the code to stop until output for the exception is done? The only solution I can think of is to put Thread.sleep, but maybe there might be some option I am not aware of.
Just curious really :) It'd be nice for debugging (that's the reason I ask, because reading the output and exceptions mixed up in between is terrible)

If you have multiple threads and their output is getting interleaved, you should think about using a logging facility rather than trying to share the stderr and stdout-
http://download.oracle.com/javase/6/docs/api/java/util/logging/package-summary.html
Or apache's log4j:
http://logging.apache.org/log4j/1.2/

How about redirecting System.err to a file?
System.setErr( ... );

The problem needs to be solved elsewhere, in the process which merges two file streams into the output you see - by only printing out a line when it is done. Since that is most likely not an option to you if you are talking about the "java.exe" output, you need to investigate elsewhere.
I have not tested, but I would start with having a look at invoking flush() on System.out before you send output to System.err.

When java implicitly imports the lang (java.lang.*) package, the System class has 2 standard output streams.
System.err
System.out
And because these both output to the same standard output, you have to choose one and change it from standard output to file output. My recommendation would be to change the System.err output like so:
import java.io.* ......
System.setErr (new PrintWriter (new FileWriter ("Errors.txt")));
Hope this helps!
EDIT
Sorry, can't leave comments yet, but the logging idea above is very good. Depending on what you are doing, logging will be an optimal solution. But I try to avoid logging because it tends to become very memory extensive if it is used too much.

Write to a separate stream in memory to format your output, then write the single string at once. You may still end up with your single string in the middle of an exception's text, though. Fundamentally what you are doing requires synchronization, or a separate stream (think one output file per thread).
I don't see how Thread.sleep will do anything other than complicate the issue.

Create a new PrintStream to file descriptor 2 with autoflush set to false.
System.setErr(new PrintStream(new FileOutputStream(FileDescriptor.err, false, "UTF-8")));
Just make sure to call System.err.flush after important error messages.
If you want to merge stderr into stdout, you can do the above but with FileDescriptor.out.

Related

Eclipse freezes when writing to the stdout audio bytes [duplicate]

How can we redirect the eclipse console output to a file? I can:
Run Configuration->Commons->Select a file.
Use System.setOut(PrintStream) and System.setErr(PrintStream).
The problem with 1) is that I need to record console output to different files instead of one file.
The problem with 2) is that it only stores console output generated by System.out.println() or stacktrace of an exception thrown. It does not capture other kind of outputs e.g. log4j warnings etc.
How can we redirect console output to different files programmatically?
Go to run as and choose Run Configurations -> Common and in the Standard Input and Output you can choose a File also.
You could use a "variable" inside the output filename, for example:
/tmp/FetchBlock-${current_date}.txt
current_date:
Returns the current system time formatted as yyyyMMdd_HHmm. An optional argument can be used to provide alternative formatting. The argument must be valid pattern for java.util.SimpleDateFormat.
Or you can also use a system_property or an env_var to specify something dynamic (either one needs to be specified as arguments)
You can set the output of System.out programmatically by doing:
System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream("/location/to/console.out")), true));
Edit:
Due to the fact that this solution is based on a PrintStream, we can enable autoFlush, but according to the docs:
autoFlush - A boolean; if true, the output buffer will be flushed
whenever a byte array is written, one of the println methods is
invoked, or a newline character or byte ('\n') is written
So if a new line isn't written, remember to System.out.flush() manually.
(Thanks Robert Tupelo-Schneck)
To solve the problem I use ${string_prompt} variable.
It shows a input dialog when application runs. I can set the date/time manually at that dialog.
Move cursor at the end of file path.
Click variables and select string_prompt
Select Apply and Run
We can do this by setting out variable of System class in the following way
System.setOut(new PrintStream(new FileOutputStream("Path to output file"))). Also You need to close or flush 'out'(System.out.close() or System.out.flush()) variable so that you don't end up missing some output.
Source : http://xmodulo.com/how-to-save-console-output-to-file-in-eclipse.html

Reading already-written text from console

I feel silly asking this but: how can I read a string from a console that is not input but has already been written to the console?
For instance, if I print a line to the console how can I read it after the fact? I know this is atypical.
Except in certain special circumstances, you can't, as Brad pointed out in the comments. As a justification, consider that when you send some text to the console (via standard output or standard error) to be printed, there's no guarantee that the text actually will be printed. Perhaps the user has redirected that output stream to /dev/null, in which case the text is gone for good. Or perhaps the text has scrolled out of view.
Basically, don't count on ever being able to access something that was sent to the console for output. If you need it, keep a copy in your program. And if you're trying to get at something that another program sent to the console, you need to use some sort of different arrangement like shared memory, sockets, or a fifo pipe.
Replace both System.in and System.out with your own streams and
try to create a pipe between System.in and System.out;
I am not sure that, whether it works or not;

reading a file while it's being written

I've read some posts on stackoverflow about this topic but I'm still confused. When reading a file that is currently being written in Java, how do you keep track of how many lines have actually been written so that you don't get weird read results?
EDIT: sorry, I should have mentioned that the file writing it is in C++ and the one reading it is in Java so variables can't really be shared easily
When reading a file that is currently being written in Java, how do you keep track of how many lines have actually been written so that you don't get weird read results?
The problem is that you can never be sure that the current last character of the file is the end of a line. If it is a line terminator, you are OK. If BufferedReader.readLine() will interpret it as a complete line without a line terminator ... and weird results will ensue.
What you need to do is to implement your own line buffering. When you get an EOF you wait until the file grows some more and then resume reading the line.
Alternatively, if you are using Java 7 or later, the file watcher APIs allow you to watch for file writes without polling the file's size.
By the way, there is an Apache commons class that is designed for doing this kind of thing:
http://commons.apache.org/io/api-2.0/org/apache/commons/io/input/Tailer.html
If I understand, the file is being written in C# in some process and another Java process wants to read it while it is being written.
Look at File Monitoring section on the tail command here. But I want to warn you that when I used the cygwin tail on Windows recently to follow log files that were rolling over, it sometimes failed under heavy load. Other implementations may be more robust.
To have a count of the number of lines, just keep a counter on the side that's doing the writing.
So, every time you write a line, increment a counter, and make that counter readable via a method, something like, public int getNumLinesWritten()
The obvious answer to me... Why not use a buffer? Use a string or whatever you need. (You could use a list/array of strings if you want, one for each line maybe?) Append to the string just as you would write to the file, then instead of reading from the file, read from that string. Would that work for you?

Use of System.err.println() in Java

On standard console all things are printed in white whether we have written it in System.out or System.err. In IDE(for me Eclipse) we can see different color output on console for both. i.e. black for System.out and red for System.err.
Is System.err is only provided for use in IDEs? Cause on cmd we can not distinguish System.out and System.err. Both are printed in same color.
These are two different output streams that are available in most of OS's. You don't have them color coded due to settings of your terminal/command line environment. On the other hand your IDE provides different visualization for different streams.
If you wanted to color them, consider using ANSI escape sequences.
This is a relict from the unix world, where most functionality is available as unix commands which were intended to be chained. The output of one command is used to feed another like here:
grep -i 'token' file | mail peter#address.de
The pipe symbol only redirects the stdout (System.out), but not the stderr (System.err). So error messages would be seen on the console, and the regular output would go to the mail command.
If there were just one stream, one could not distinguish between them.
Windows, not relying on the command line (This changed in Windows Server 2008!) didn't invent again but just took the unix concepts and made them available in their dos commands, too. It is just that nearly no Windows only users usually know what they are good for.
From system-in-out-error:
System.err is a PrintStream.
System.err works like System.out
except it is normally only used to
output error texts. Some programs
(like Eclipse) will show the output to
System.err in red text, to make it
more obvious that it is error text.
From JLS:
20.18.3 public static PrintStream err;
The initial value of this variable is
a "standard" error output stream,
already open and ready to accept
output data. Typically, this
corresponds to display output or
another output destination specified
by the host environment or user. By
convention, this output stream is used
to display error messages or other
information that should come to the
immediate attention of a user even if
the principal output stream, the value
of the variable out, has been
redirected to a file or other
destination that is typically not
continuously monitored. Note that this
field is not final, so its value may
be updated if necessary.
From Java World 02-qa-1220-console.html
Other post in Stackoverflow coloring-text-with-java-in-windows
System.out goes to the standard output stream (stdout) and System.err goes to the standard error stream (stderr). See standard streams for details and how you can control where they go. Eclipse just conveniently colour codes them for you so you can distinguish them in one view.
Both System.out and System.err always exist in Java.
Depending on your console it might be possible to get it to display the two streams in a different colour.
Example use:
try {
Class.doSomething(myFile);
} catch (Exception e){
System.err.println("Fatal error performing doSomething: " + e);
System.exit(-1);
}

Cleaner debug level logging in Java?

Is there a cleaner way for me to write debug level log statements? In some ways one could say that the string literals are basically commenting the code and providing logging in one line and that it is already very clean. But after I add debug level log statements, I find the code much less easier to read up and down. Take this example (I may update to a real example if I get back to my home PC):
int i = 0;
logger.debug("Setting i to 0,"); //Just an example, would show something more complex
i++;
InputStream is = socket.getInputStream();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
IOUtils.write(request, dos);
logger.debug("request written to output");
while (!is.read(buffer))
logger.debug("Reading into buffer");
logger.debug("Data read completely from socket");
CustomObject.doStuff(buffer);
logger.debug("Stuff has been done to buffer");
You could try using aspects, although these have the limitation that you can only put log statements "around" method calls, i.e. before entering and/or after leaving a specific method.
For more detailed logging, I am afraid there is no other way than hand-coded log messages.
I typically strive to remove the not-so-much-needed debug log statements from the code once I made sure that it works the way it should (for which unit tests are a must).
Ask yourself if I run this in a different machine/country/planet, and things go wrong and all I have is only a log file what information do I need to know what has gone wrong ?
Use debug logs in a for loop, or a while loop sparingly. For example, if you are reading 1000 records from a file, performing an op for each record. You could record before the for loop that "file exists and is readable and is going to read 1000 records" and print status after the process is done. If it is say 1000000 records then you could print something every say 100 or 1000 iterations
In your code except for the logger for setting i to 0 everything else sorta makes sense to me. Also care to use log.isDebugEnabled() if your string in the logger statmeent is hard to compute..
ex:
if(log.isDebugEnabled) {
logger.debug("Here " + obj.aMethodCallThatTakes5MinsToEvaluateToString());
}
UPDATE 1: SLF4J solves only half the problem.
if(slfLog.isDebugEnabled) {
slfLog.debug(obj.getObjectThatTakes5Mins());
}
Yes the toString is prevented but if you are logging an actual object which is result of some computation you are not prevented.
If you want very fine grained debug instructions I am not sure you can separate the actual code from the debug code.
If you want it at a higher level, maybe adding your logging using AOP could help make things easier to read, maybe use a proxy object?
But if you have debug instructions as fine grained as in the example you provided, IMHO you could gain more by replacing the loggers with unit tests. Don't write in a log that something happened, test that it did.
You will not be able to do much if you dislike the log statements. The information needs to be there somehow.
What you CAN do, is strongly considering what NEEDS to be there. You are basically writing for the log file reader who per definition does not know about how your program works, so the information needs to be concise and correct. Personally I very frequently add the method name to the log statement.
Also note that slf4j allows you to use the {}-syntax which helps somewhat
log.debug("main() date={}, args={}", new java.util.Date(), args);
Also note that having unit tests, allow you to move much stuff to there simply because you know that THAT works.

Categories

Resources