Java redirect System.out and appending - java

In Java, I have redirected System.out: System.setOut("someText.txt"); to write to a text file. I would like to run this program once an hour, and would like to append each set of print statements to the end of the file. For example suppose at hour 1, my program runs, prints "Hello\n" and then quits. Then at hour 2, my program runs, prints "hello again\n", and then quits.
If this happened I would like the contents of my text-file to be something like:
Hello
Hello again
Currently, I am just overwriting the text file.
How can I append to the end of the text file with this redirected printStream?
EDIT How can I also print to the console?

When you build the FileOutputStream use the following:
FileOutputStream(File file, boolean append)
Creates a file output stream to write to the file represented by the specified File object.
from the JAVADOC
Code example:
OutputStream outStream = new FileOutputStream("file1.txt",true);

Use
OutputStream printStream = new OutputStream(new FileOutputStream("someText.txt", true));
System.setOut(printStream);

the answers by #Frank and #Petr Mensik are correct. But just in case you wanted to try something different:
System.out.append("Hello World\n") should do the trick. Hence, instead of doing a System.out.print, you do a System.out.append

The simplest answer is not to do this using Java code, but to use tee; trying to reimplement tee in Java is just reinventing a square wheel. Just do this:
java -jar yourapp.jar | tee -a output.log
On Windows? Install MinGW and/or Cygwin. :-)

Related

Is there a way to simply copy console output into new text file?

I had a very simple request, I have a full code that sorts through an input file and outputs the merged strings properly into the console. My question is can I take this already perfect output from my CONSOLE and simply output it into a seperate .txt fle as well?
I've tried doing a simple
PrintStream printStream = new PrintStream(new FileOutputStream("output.txt"));
System.setOut(printStream);
it does create my output.txt file, but it's always empty?
Option 1: Output via Terminal
Since your script already outputs perfectly to the terminal, you can redirect that output to a file via >
$ ./my-script > output.txt
You can also use the tee command if you still want to see the output in your terminal.
$ ./my-script | tee output.txt
Option 2: Generate file via code
I'm not too familiar with Java / PrintStream but from https://www.tutorialspoint.com/java/io/printstream_print_string.htm, you should see content in your file by:
PrintStream printStream = new PrintStream(new FileOutputStream("output.txt"));
printStream.print("foo");
printStream.flush();

How to run “echo” command through Java?

I want to change a value inside of a file named scaling_max_freq located in /sys/devices/system/cpu/cpu0/cpufreq/ on an Android device.
On an another post I've read that I'm able to do this through an echo command like:
echo 255 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
Where "255" is the value I want to put in the file.
How can I succeed it through java?
You can do system call, Runtime.exec(). Or if you want to do it in pure Java you can reproduce the behavior of the command line. "echo" is just writing on the standard output, and the '>' operator is redirecting the standard output to a file (but do not append).
So in Java..
FileWriter writer = new FileWriter(file);
writer.write("255");

PrintWriter erases file of contents before the close() function executed

I am trying to write contents of my parsed HTML with PrintWriter so I can convert HTML to the other formats. But PrintWriter erases file of contents before the close() function executedçI can use other file writing techniques but I am wondering why PrintWriter behave like this.
for (Element element : elements) {
if (element.tagName() == "a") {
PrintWriter writer2 = new PrintWriter("contenthtml.html", "UTF-8");
writer2.print(a.ExtractHTMLByIDandDomain(Domain + element.attr("href"), Content_HTML_ID));
Process proc = Runtime.getRuntime().exec("pandoc -f html -t asciidoc contenthtml.html >> contentasciidoc.adoc");
//Thread.sleep(5000); //I have tried wait but it didn't work
writer2.flush();
writer2.close();
}
There are a few problems with your code:
You cannot compare strings with '==', as '==' compares references. If element.getTagName() is "a", whether that if on line 2 of your paste actually fires depends on the situation, but it probably wont.
A PrintWriter is a resource. Resources need to be closed; if you do not close them, the resource remains open indefinitely, and this is called a resource leak. Use the Automatic Resource Management construct for a convenient way to do so.
You create the printwriter, tell the printwriter to write some data, you do not flush or close the resource, you then exec another process, and finally after that process completes, you flush/close. Which means, the file is empty, as printwriter buffers. You should write your file and then close your resource, and only then call the external process; both you and the process you launch having the same file open at the same time is confusing and problematic, and in this case, unneccessary, so, don't.
Runtime.getRuntime().exec() is NOT bash and NOT a command line prompt. The concept of redirecting via >> someFile.txt is a bashism/command-promptism. Runtime has no idea what you're talking about and will just pass it along as an argument to the launched process. Invoke bash if you need bash's redirection features or write the redirection in java by reading the outputstream of the process and appending it to the file yourself.
Applying all 4 fixes:
create a file named 'run.sh' containing:
#!/bin/sh
pandoc -f html -t asciidoc contenthtml.html >> contentasciidoc.asciidoc
and update your java code:
for (Element element : elements) {
if ("a".equalsIgnoreCase(element.tagName()) {
try (PrintWriter writer2 = new PrintWriter("contenthtml.html", "UTF-8")) {
writer2.print(a.ExtractHTMLByIDandDomain(Domain + element.attr("href"), Content_HTML_ID));
}
}
Process proc = Runtime.getRuntime().exec("/usr/bin/bash run.sh");
}
There is no guarantee that PrintWriter will write to the file until you call flush()
It might work if you move flush() to before exec()
First: Please read an try to understand the answer rzwitserloot wrote because it contains some valid constructive criticism.
To answer your question why PrintWriter deletes already existing file contents: It's designed to do so. If you look in the documentation for PrintWriter which you can find here: https://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html#PrintWriter(java.io.File,%20java.lang.String)
The part about the File Parameter:
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.

Writing to the OutputStream of Java Process/ProcessBuilder as pipe

I have problems sending data from java to a (linux)-subprocess created by ProcessBuilder/Process.
A shell-only based basic example would look like as follows and works fine.
echo "hello world" | cat - >/tmp/receive.dat
Now, I want to substituted the echo "hello world" by a java program which should internally create a new process (the cat - >/tmp/receive.dat) and then send data to it.
I tried the following, but the file /tmp/receive.dat remains untouched:
String[] cmdArray = { "/bin/cat", "-", ">/tmp/receive.dat" };
ProcessBuilder builder = new ProcessBuilder (cmdArray);
builder.directory (new File ("/tmp"));
Process p = builder.start ();
OutputStream pos = p.getOutputStream ();
byte [] bytes = "hello world".getBytes ();
pos.write (bytes);
pos.close ();
p.waitFor ();
The same happens under Windows, of course with an adapted cmdArray:
cmd /c type con >c:\tmp\receive.dat
Printing directly to system.out from java is no alternative as many subprocesses should be called within the livecycle of the java program.
thx for any help!
Tombo
The issue here is that /bin/cat does not actually write to files, it merely writes to standard out. The output redirection >/tmp/receive.dat is actually performed by the shell, but you are bypassing the shell by invoking cat in this manner.
If what you are trying to achieve is merely an OutputStream that writes to a file, then doing that via standard java I/O (e.g., FileOutputStream and friends) is what you want. It is also cross-platform (i.e., Windows-friendly), unlike anything that depends on the shell.
Regarding the comment about not being able to merely write to standard out from java because of subprocesses - any subprocess you invoke can inherit standard out from their parent process (the java process - look at ProcessBuilder.Redirect.INHERIT). So even if you are invoking subprocesses from java, redirecting all the output to a file should still work in the same way as your initial example (where the java program replaces the echo command).
You probably want ProcessBuilder#redirectOutput(File), as the > functionality is not of cat, rather what is calling cat (in our sense, the process builder).

Java application can't run external jar (FOP) properly, when fop data are larger

I have problem with running FOP from Java program.
I use Java 1.8_25.
Run commands:
String[] cmd4 = {"java", "-jar", rootDir+"build"+ FileSeparator +"fop.jar", "-c", rootDir+"lib" + FileSeparator + "conf" + FileSeparator + "myfop.xconf", pathToFOP.getCanonicalPath(), outputFile.getCanonicalPath()};
System.out.println(Arrays.toString(cmd4));
Process p = Runtime.getRuntime().exec(cmd4);
p.waitFor();
java.io.InputStream is=p.getInputStream();
byte b[]=new byte[is.available()];
is.read(b,0,b.length);
System.out.println(new String(b));
When I generate in program relatively short output, FOP proceeds normally and generates .pdf file.
When I generate bigger output (but still on one A4 page) FOP process executes, creates empty .pdf file and waits. When I kill the main program, FOP saves .pdf correctly. But I want to have .pdf file converted while main program is running (it also after that opens generated .pdf file)
No error is displayed
output of program:
[java, -jar, C:\JForm\build\fop.jar, -c, C:\JForm\lib\conf\myfop.xconf, C:\Users\Phoros\Documents\test29x.pdf.fop, C:\Users\Phoros\Documents\test29x.pdf]
Thanks for any help.
It is not so easy in Java to read output from an external process once that output does not fit into a single buffer anymore. You then have to create a separate thread to read away that output otherwise the process cannot write more and will just block and never finish (which is what you are seeing).
You could work on fixing that, but since FOP is a Java library, it should be easier to directly call the Java API, without the external process.
Another idea would be to involve a temporary file where the external process places its result. That way, the process' direct output won't be big.
more remarks:
java.io.InputStream is=p.getInputStream();
byte b[]=new byte[is.available()];
is.read(b,0,b.length);
I don't think that will reliably work, either. available won't necessarily contain all data, just indicate how much data there is before it blocks to get more.
Is it necessary to read the whole thing into memory?
System.out.println(new String(b));
Why turn the bytes into a String just to print them again? Cannot you just print the bytes directly?

Categories

Resources