This question is pretty easy I guess but I can't figure out, how to do it best. I have a JAR file which I use in my program and basically I just call the main() method of one of the classes in this JAR file.
The problem is, that I don't want to have the output of this method on my program's output - it should be hidden.
I call the method just that way:
Main.main(new String[] {"some-arg1", "arg2", "some-argument3"});
Is there any possibility to hide/redirect the output of this method? Can I just set a new temporary stdout or something like that?
Any help is greatly appreciated. Thanks in advance!
You can use System.setOut() to redirect stdout. You can also close System.out completely if you want to.
Related
I am trying to redirect the output produced in a Java program into another file("output.txt") located in the same location. I found help on it from here. But when I try the same method I find that my file "output.txt" remains empty. My code looks like this:
System.setOut(new PrintStream(new FileOutputStream("output.txt")));
System.out.println("hello");
Could somebody please point out my mistake here.
Thank you in advance for your help.
As it is said in this answer, you should try to set autoflushing to true
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.
I hope there do have an operation for this topic,'cause I don't want to loop the file once again,and hope to read the file from the specific location say a line number,and then I will read the file with much more threads than just one.
Any idea?
Thanks first!!
To my knowledge there isn't anything like this in the standard Java API. You could use LineIterator or (even just a basic BufferedReader) to build a custom class that does what you need, like this guy did.
Note that a RandomAccessFile sounds promising but unfortunately for you, the seek() method takes an offset in bytes and not in lines so unless your lines are all always the same length, this wont' work for you.
Please suggest a method to obtain a similar behaviour in Java as when we do freopen("filename","r",stdin) OR freopen("filename","w",stdout) in C.
Assuming that this is to redirect stdin/stdout/stderr, have a look at System.setIn and friends. They allow you to assign a different InputStream and PrintStream to System.in, System.out and System.err.
See the webpage below. There's a solution to what you wanna do.
http://techtipshoge.blogspot.com/2011/01/connect-standard-io-to-files.html
I have the Java code below running on Unix (both AIX and Linux), but it doesn't work. If I run this code the file q1.01 is not compressed, and I don't get any exceptions thrown (The file q1.01 exists, and I expect to find the file q1.01.Z after the command runs.) At the command prompt if I type "which compress" it reports back with "/usr/bin/compress". If I type the command "/usr/bin/compress q1.01" at the Unix prompt it works fine. Any ideas on what might be wrong?
String cmd = "/usr/bin/compress q1.01";
Runtime.getRuntime().exec(cmd);
[Later edit: the problem was in the initial description; the OP was passing a wildcard and not q.01. So my answer below is wrong, except for the part in bold. I'm leaving it so the comments after it will make sense.]
It's trying to run /usr/bin/compress as the program name without arguments.
There are many forms of the Runtime.exec() method. You're using the .exec(String) version, which just takes the executable. Instead, you need to use the .exec(String[]) array version, which takes the executable in String[0] and the parameters in String[1..].
.exec() wants a String array for passing arguments.
Try
String[] cmd = new String[] { "/usr/bin/compress", "q1.01" };
Runtime.getRuntime().exec(cmd);
Note that .exec does not call the local command shell. That means we have to do, among other things, wildcard expansion and even some argument parsing before calling .exec(). This is why you can't just pass it your full command line.
There were a couple of problems. One was that I had tried using wildcards, and since the shell isn't invoked they weren't being expanded. The other problem was that I had created very small test files like this: "echo 'abc' >q1.01". This file was so small that compress couldn't compress it any further and so left it alone. (Stupidly, I think when I typed in the command at the shell I used a different filename, which did compress.)
Thanks everyone for the answers. It did help!
You probably need to use an absolute path to the file. Capture the output though, to see what the problem is - see this page for info on how to do that.
This site may be able to provide some clues.
If the process input stream is null, I suspect that Java wasn't even able to spawn the subprocess. What does Process#exitValue() return?
I'd recommend using strace to see what actually happens on the system-call level. The actual exec() arguments and return code would be especially interesting to see.