Lesson 5 | Writing bytes |
Objective | Write a program that copies data from System.in to System.out with maximum efficiency. |
Writing Bytes in Java
Write a program that copies data from System.in to System.out using Classic Input and Output from Java 1.1
The following is a Java program that uses the classic InputStream and OutputStream classes from Java 1.1 to copy data from System.in to System.out. This program reads bytes from standard input (System.in) and writes them directly to standard output (System.out), effectively copying the input stream to the output stream.
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
public class CopyStream {
public static void main(String[] args) {
// Set up InputStream and OutputStream
InputStream in = System.in;
OutputStream out = System.out;
try {
int data;
// Read and write each byte
while ((data = in.read()) != -1) { // -1 indicates the end of the stream
out.write(data);
}
out.flush(); // Ensure all data is outputted
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Explanation
- InputStream and OutputStream: The program uses
InputStream
for reading data and OutputStream
for writing data, which were foundational in Java 1.1.
- in.read(): Reads one byte at a time from
System.in
. If it returns -1
, it means the end of the input stream has been reached.
- out.write(data): Writes the byte read from
System.in
to System.out
.
- out.flush(): Ensures any remaining buffered data is sent to
System.out
.
- Exception Handling: Handles
IOException
in case of input-output errors and closes the streams in the finally
block.
This approach is useful for simple byte-by-byte data copying.
It is often faster to write larger chunks of data at a time, rather than writing byte by byte.
Two polymorphic
variants of write() method do this. The following code fragment sends the bytes in a string onto
System.out
:
String s = "How are streams treating you?";
byte[] b = s.getBytes();
System.out.write(b);
Polymorphic Variants of the write() method
public void write(byte b[]) throws IOException
public void write(byte b[], int offset, int length) throws IOException
The first variant writes the entire byte array
b
.
The second writes only the subarray of
b
starting at
offset
and continuing for
length
bytes.
In Java, the write() method is defined in the OutputStream and Writer classes, which are the base classes for byte and character output streams, respectively. These classes and their subclasses provide various polymorphic variants of the write() method. Here are some common ones:
- OutputStream:
- void write(int b): Writes the specified byte to the output stream. The argument b should be in the range of 0 to 255. If a value outside this range is provided, only the least significant 8 bits are written.
- void write(byte[] b): Writes b.length bytes from the specified byte array to the output stream.
- void write(byte[] b, int off, int len): Writes len bytes from the specified byte array, starting at the specified offset off, to the output stream.
- Writer:
- void write(int c): Writes a single character to the writer. The character is derived from the least significant 16 bits of the provided integer value.
- void write(char[] cbuf): Writes an array of characters to the writer.
- void write(char[] cbuf, int off, int len): Writes a portion of an array of characters, given by the specified offset off and length len, to the writer.
- void write(String str): Writes a string to the writer.
- void write(String str, int off, int len): Writes a portion of a string, given by the specified offset off and length len, to the writer.
These polymorphic variants of the write() method allow you to write different data types (bytes, characters, strings, or arrays) and control the portions of data being written using offsets and lengths. The actual behavior of these methods depends on the specific subclasses of OutputStream and Writer being used, for example
- FileOutputStream,
- ByteArrayOutputStream,
- FileWriter,
- StringWriter.
You can also run into performance problems if you attempt to write too much data at once. The exact turnaround point depends on the eventual destination of the data.
Files are often best written in small multiples of the block size of the disk, typically 512; 1,024; or 2,048 bytes. Network connections often require smaller buffer sizes, typically 128 or 256 bytes. The optimal buffer size depends on too many system-specific details for anything to be guaranteed, but I often use 128 bytes for network connections and 1,024 bytes for files.
Writing Java Bytes - Exercise
Click the Exercise link below to write a program that reads data from
System.in
into a byte array buffer, then copies the data onto
System.out
.
Writing Java Bytes - Exercise