Working with Java I/O: Byte and Character Streams along with Buffering
A typical I/O stream operation involves three steps: declaring exceptions, performing read/write actions, and closing resources (always close in reverse order of opening).
Byte Streams
Byte streams are preferred for copying any type of file, though they aren't recommended for reading Chinese characters directly.
Reading with FileInputStream
try {
FileInputStream inputStream = new FileInputStream("e:/b.txt");
int byteRead;
while ((byteRead = inputStream.read()) != -1) {
System.out.print((char) byteRead);
}
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
Writing with FileOutputStream
try {
FileOutputStream outputStream = new FileOutputStream("e:/b.txt");
outputStream.write(99); // 'c'
outputStream.write(100); // 'd'
outputStream.close();
// Append mode: true prevents overwriting existing data
FileOutputStream appendStream = new FileOutputStream("e:/b.txt", true);
appendStream.write(97); // 'a'
appendStream.write(98); // 'b'
appendStream.close();
// Writing a string character by character
FileOutputStream fos2 = new FileOutputStream("e:/b.txt");
String text = "abcdefghijklmn";
for (int i = 0; i < text.length(); i++) {
fos2.write(text.charAt(i));
}
fos2.close();
} catch (Exception e) {
e.printStackTrace();
}
Efficient Copying Using Byte Arrays
A more efficient approach is to copy using a byte buffer. The recommended buffer size is new byte[8192] (8KB).
try {
FileInputStream source = new FileInputStream("e:/1.jpg");
FileOutputStream destination = new FileOutputStream("e:/cba/1.jpg");
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = source.read(buffer)) != -1) {
destination.write(buffer, 0, bytesRead);
}
destination.close();
source.close();
} catch (Exception e) {
e.printStackTrace();
}
An alternative490 approach reads all bytes at once but can cause memory issues with large files:
try {
FileInputStream in = new FileInputStream("e:/1.jpg");
FileOutputStream out = new FileOutputStream("e:/cba/1.jpg");
byte[] allBytes = new byte[in.available()];
in.read(allBytes);
out.write(allBytes);
out.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
Buffered Byte Streams
Buffered wrappers internally use an 8192-byte array to reduce system calls.
try {
FileInputStream fis = new FileInputStream("e:/cba/w.mp4");
BufferedInputStream bufferedInput = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("e:/abc/w.mp4");
BufferedOutputStream bufferedOutput = new BufferedOutputStream(fos);
int data;
while ((data = bufferedInput.read()) != -1) {
bufferedOutput.write(data);
}
bufferedOutput.close();
bufferedInput.close();
} catch (Exception e) {
e.printStackTrace();
}
Standard Resource Handling
Always close streams in a finally block, checknig for null to avoid NullPointerException.
FileInputStream fin = null;
FileOutputStream fout = null;
try {
fin = new FileInputStream("e:/cba/w.mp4");
fout = new FileOutputStream("e:/abc/ww.mp4");
byte[] buf = new byte[8192];
int len;
while ((len = fin.read(buf)) != -1) {
fout.write(buf, 0, len);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fout != null) {
try { fout.close(); } catch (IOException e) { e.printStackTrace(); }
}
if (fin != null) {
try { fin.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
Writing Keyboard Input to a File
With unbuffered streams:
Scanner scanner = new Scanner(System.in);
FileOutputStream fileOut = null;
try {
fileOut = new FileOutputStream("e:/cba/aaa.txt", true);
while (true) {
System.out.println("Enter text (type 'quit' to stop):");
String line = scanner.next();
if ("quit".equals(line)) break;
fileOut.write(line.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOut != null) {
try { fileOut.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
Using bufferign and flushing:
Scanner input = new Scanner(System.in);
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
fos = new FileOutputStream("e:/cba/bbb.txt");
bos = new BufferedOutputStream(fos);
while (true) {
System.out.println("Enter text (type 'puit' to exit):");
String userInput = input.next();
if ("puit".equals(userInput)) break;
bos.write(userInput.getBytes());
bos.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bos != null) {
try { bos.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
Character Streams
Character streams are15 designed for text files and must not be used for binary files like images or videos.
FileReader
FileReader reader = null;
try {
reader = new FileReader("e:/cba/a.txt");
int ch;
while ((ch = reader.read()) != -1) {
System.out.print((char) ch);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
FileWriter
FileWriter writer = null;
try {
writer = new FileWriter("e:/cba/n.txt");
String message = "你好,我不好!";
char[] chars = message.toCharArray();
writer.write(chars);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
try { writer.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
Copying Text with Character Arrays
Using a character buffer yields better performance.
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("e:/cba/a.txt");
fw = new FileWriter("e:/abc/a.txt");
char[] cbuf = new char[8192];
int count;
while ((count = fr.read(cbuf)) != -1) {
fw.write(cbuf, 0, count);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fw != null) {
try { fw.close(); } catch (IOException e) { e.printStackTrace(); }
}
if (fr != null) {
try { fr.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
Buffered Character Streams
BufferedReader provides readLine() to read whole lines.
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
fileReader = new FileReader("e:/abc/a.txt");
bufferedReader = new BufferedReader(fileReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
BufferedWriter can write single characters, strings, and also provides newLine() for platform-independent line breaks.
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
try {
fileWriter = new FileWriter("e:/abc/ab.txt");
bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("你好");
bufferedWriter.newLine();
bufferedWriter.write("早上好");
bufferedWriter.newLine();
bufferedWriter.write("不好!");
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedWriter != null) {
try { bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
Combining both:
FileReader fr = null;
BufferedReader br = null;
FileWriter fw = null;
BufferedWriter bw = null;
try {
fr = new FileReader("e:/abc/a.txt");
br = new BufferedReader(fr);
fw = new FileWriter("e:/cba/t.txt");
bw = new BufferedWriter(fw);
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bw != null) {
try { bw.close(); } catch (IOException e) { e.printStackTrace(); }
}
if (br != null) {
try { br.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
Reversing Text Content
A practical example that reads a file, reverses the entire text, and writes it back.
FileReader fr = null;
BufferedReader br = null;
FileWriter fw = null;
BufferedWriter bw = null;
try {
fr = new FileReader("e:/abc/a.txt");
br = new BufferedReader(fr);
StringBuilder builder = new StringBuilder();
String currentLine;
while ((currentLine = br.readLine()) != null) {
builder.append(currentLine).append("\r\n");
}
builder.reverse();
fw = new FileWriter("e:/abc/ccc.txt");
bw = new BufferedWriter(fw);
bw.write(builder.toString());
bw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bw != null) {
try { bw.close(); } catch (IOException e) { e.printStackTrace(); }
}
if (br != null) {
try { br.close(); } catch (IOException e) { e.printStackTrace(); }
}
}
Flush vs Close
flush() forces buffered data to be written to the destination without closing the stream, allowing subsequent writes. close() also flushes the buffer but then releases the resource.