Week 5: I/O redirection (185)
2013-02-13
All programs have access to 3 standard streams, which
when run on the command line behave as follows by default:
- standard input (
stdin
): the keyboard input
- standard output (
stdout
): the console output
- standard error (
stderr
): the console output, used primarily to report
errors.
You can control the behavior of those streams using redirection, which can
change the source of stdin
, or the destination of stdout
or stderr
.
We'll work with examples in Microsoft Windows, but the same ideas and most of
the same syntax work in Linux or OSX (usually more consistently and with more
powerful features); later in the semester we'll cover the command line
interfaces available on those systems (or something similar).
Output redirection
Rather than printing to the console, you can signal that output (stdout
)
should go to a named file by using the >
operator. The following example
lists the contents of C:\
into a file:
dir /b C:\ > c-contents.txt
Note that if there is no output, an empty file will be created. In either
case, any existing file named c-contents.txt
will be destroyed. If you
want to add on to the file rather than overwrite it, use the >>
operator:
dir /b C:\ >> c-contents.txt
Now the output from that dir
command will be appended to the file if
it already exists (otherwise it will be created just like the first case).
You can also redirect stderr
; for example, the following command
lists the contents of C:\XYZ
into a file, and saves any error output
into another file. There will probably be error output, unless you happen
to have a directory named XYZ
.
dir /b C:\XYZ > xyz-contents.txt 2> xyz-errors.txt
On earlier versions of Windows, redirection of stderr
might not be available.
Input redirection
You can signal to a program that its input should come from a file
(rather than the keyboard) by using the <
operator.
For an example, let's look at the find
command (Windows version). This
command searches its input for a target string, and prints lines where it finds
the target. For example, find "banana"
will print back all the lines that you
type that contain "banana" (quotes not necessary). Note that when you run the
command, you'll need a way to signal that you're done. On the Windows command
line, type Ctrl-Z
and then Enter
to signal end-of-file.
That's probably not very useful, since when you're typing you already know
yourself which lines contain "banana". The command is really made to search
through files, and you can send input from a file by redirection:
find "banana" < banana-info.txt
The above command will print all lines in banana-info.txt
that contain the
word "banana".
Pipes
Finally, you might want to get output from one program and send it directly
to another; so you combine output and input redirection. This is called
piping output, and uses the pipe character (|
) as the operator.
Here's an example:
dir /b C:\Windows\System32 | find "reg"
That particular example could be accomplished more simply by using a wildcard
(dir /b C:\Windows\System32\*reg*
), but in general pipes provide a powerful
way to combine programs to gain new functionality.
In Java
Java programs work with I/O redirection just like any other program. Here's
an example that counts words read from stdin
:
import java.io.IOException;
class WordCount {
public static void main(String[] args) throws IOException {
boolean inWord = false; // flag to indicate we're reading a word
int count = 0; // current word count
int c; // current letter
while ((c = System.in.read()) != -1) {
// If we hit a space, add to count if we have seen a word
if (Character.isWhitespace(c)) {
if (inWord) {
count++;
inWord = false;
}
} else {
inWord = true;
}
}
System.out.println(count);
}
}
To use with a file as input, compile and run
java WordCount < FILE.txt
Other readings