Blocking or redirecting standard output / error


Blocking or redirecting

Sometimes a poorly designed 3rd-party library will write unwanted diagnostics to System.out or System.err streams. The recommended solutions to this would be to either find a better library or (in the case of open source) fix the problem and contribute a patch to the developers.

If the above solutions are not feasible, then you should consider redirecting the streams.

Redirection on the command line

On a UNIX, Linux or MacOSX system can be done from the shell using > redirection. For example:

$ java -jar app.jar arg1 arg2 > /dev/null 2>&1
$ java -jar app.jar arg1 arg2 > out.log 2> error.log

The first one redirects standard output and standard error to "/dev/null", which throws away anything written to those streams. The second of redirects standard output to "out.log" and standard error to "error.log".

(For more information on redirection, refer to the documentation of the command shell you are using. Similar advice applies to Windows.)

Alternatively, you could implement the redirection in a wrapper script or batch file that launches the Java application.

Redirection within a Java application

It is also possible to redired the streams within a Java application using System.setOut() and System.setErr(). For example, the following snippet redirects standard output and standard error to 2 log files:

System.setOut(new PrintStream(new FileOutputStream(new File("out.log"))));
System.setErr(new PrintStream(new FileOutputStream(new File("err.log"))));

If you want to throw away the output entirely, you can create an output stream that "writes" to an invalid file descriptor. This is functionally equivalent to writing to "/dev/null" on UNIX.

System.setOut(new PrintStream(new FileOutputStream(new FileDescriptor())));
System.setErr(new PrintStream(new FileOutputStream(new FileDescriptor())));

Caution: be careful how you use setOut and setErr:

  • The redirection will affect the entire JVM.
  • By doing this, you are taking away the user's ability to redirect the streams from the command line.

Reading a whole file at once

File f = new File(path);
String content = new Scanner(f).useDelimiter("\\Z").next();

\Z is the EOF (End of File) Symbol. When set as delimiter the Scanner will read the fill until the EOF Flag is reached.


Locking

A file can be locked using the FileChannel API that can be acquired from Input Output streams and readers

Example with streams

import java.io.FileInputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
 
public class FileLockExample {
    public static void main(String[] args) throws Exception {
        String customFilename = "example.txt";
 
        // Open a file stream
        FileInputStream customInputStream = new FileInputStream(customFilename);
 
        // get underlying channel
        FileChannel customChannel = customInputStream.getChannel();
 
        // try to lock the file
        FileLock customLock = customChannel.tryLock(0, Long.MAX_VALUE, true);
 
        if (customLock == null) {
            System.out.println("Unable to acquire lock");
        } else {
            System.out.println("Lock acquired successfully");
        }
 
        // you can also use blocking call which will block until a lock is acquired.
        customChannel.lock();
 
        // Once you have completed desired operations of the file, release the lock
        if (customLock != null) {
            customLock.release();
        }
 
        // close the file stream afterwards
 
        // Example with reader
        RandomAccessFile customRandomAccessFile = new RandomAccessFile(customFilename, "rw");
        FileChannel customReadWriteChannel = customRandomAccessFile.getChannel();
 
        // Repeat the same steps as above, now using the channel in read-write mode
        FileLock customReadWriteLock = customReadWriteChannel.tryLock(0, Long.MAX_VALUE, true);
 
        if (customReadWriteLock == null) {
            System.out.println("Unable to acquire read-write lock");
        } else {
            System.out.println("Read-write lock acquired successfully");
        }
 
        // Release the read-write lock once operations are completed
        if (customReadWriteLock != null) {
            customReadWriteLock.release();
        }
    }
}

Iterate over a directory printing subdirectories

public void iterate(final String dirPath) throws IOException {
	final DirectoryStream<Path> paths = Files.newDirectoryStream(Paths.get(dirPath));
	for (final Path path : paths) {
		if (Files.isDirectory(path)) {
			System.out.println(path.getFileName());
		}
	}
}

Basic Programs