Streams and NIO
This lesson covers Java's stream-based IO and NIO for lower-level file operations.
IO Stream Architecture
TEXT
Input Streams (Reading)
InputStream (byte input)
├── FileInputStream (file)
├── BufferedInputStream (buffer)
├── ByteArrayInputStream (byte array)
└── DataInputStream (primitive types)
Reader (character input)
├── FileReader (file)
├── BufferedReader (buffer)
└── InputStreamReader (conversion)
Output Streams (Writing)
OutputStream (byte output)
├── FileOutputStream (file)
├── BufferedOutputStream (buffer)
└── DataOutputStream (primitive types)
Writer (character output)
├── FileWriter (file)
├── BufferedWriter (buffer)
└── OutputStreamWriter (conversion)
Byte Streams
FileInputStream Reading
JAVA
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("test.txt")) {
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileOutputStream Writing
JAVA
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
String text = "Hello, World!";
fos.write(text.getBytes());
System.out.println("Write successful");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Example: Byte Stream File Copy
JAVA
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteCopy {
public static void copy(String src, String dest) throws IOException {
try (FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dest)) {
byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) != -1) {
fos.write(buffer, 0, length);
}
}
}
public static void main(String[] args) {
try {
copy("source.txt", "dest.txt");
System.out.println("Copy complete");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Buffered Streams
Buffered streams improve IO efficiency by reducing disk access次数.
BufferedInputStream/BufferedOutputStream
JAVA
import java.io.*;
public class BufferedStreamDemo {
public static void main(String[] args) throws IOException {
// Write
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("buffered.txt"))) {
for (int i = 0; i < 1000; i++) {
bos.write(("Line " + i + "\n").getBytes());
}
}
// Read
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("buffered.txt"))) {
byte[] buffer = new byte[1024];
int length;
while ((length = bis.read(buffer)) != -1) {
System.out.write(buffer, 0, length);
}
}
}
}
Data Streams
DataInputStream/DataOutputStream can read and write primitive types.
Example: Data Streams
JAVA
import java.io.*;
public class DataStreamDemo {
public static void main(String[] args) throws IOException {
// Write
try (DataOutputStream dos = new DataOutputStream(
new FileOutputStream("data.dat"))) {
dos.writeInt(100);
dos.writeDouble(3.14);
dos.writeUTF("Hello");
}
// Read
try (DataInputStream dis = new DataInputStream(
new FileInputStream("data.dat"))) {
int i = dis.readInt();
double d = dis.readDouble();
String s = dis.readUTF();
System.out.println("int: " + i); // 100
System.out.println("double: " + d); // 3.14
System.out.println("string: " + s); // Hello
}
}
}
NIO (New IO)
Java NIO provides more efficient IO operations.
Path Interface
JAVA
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathDemo {
public static void main(String[] args) {
Path path = Paths.get("/home/user/test.txt");
System.out.println("Filename: " + path.getFileName()); // test.txt
System.out.println("Parent: " + path.getParent()); // /home/user
System.out.println("Root: " + path.getRoot()); // /
System.out.println("Name count: " + path.getNameCount()); // 3
}
}
Files Utility Class
JAVA
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class FilesDemo {
public static void main(String[] args) throws IOException {
Path path = Paths.get("test.txt");
// Check
System.out.println("Exists: " + Files.exists(path));
System.out.println("Is file: " + Files.isRegularFile(path));
System.out.println("Is readable: " + Files.isReadable(path));
// Read all lines
List<String> lines = Files.readAllLines(path);
lines.forEach(System.out::println);
// Read as byte array
byte[] bytes = Files.readAllBytes(path);
System.out.println("Size: " + bytes.length);
// Write
Files.write(Paths.get("output.txt"), "Hello".getBytes());
// Create directory
Files.createDirectories(Paths.get("newdir/subdir"));
// Copy
Files.copy(Paths.get("source.txt"), Paths.get("dest.txt"));
// Move
Files.move(Paths.get("old.txt"), Paths.get("new.txt"));
// Delete
Files.deleteIfExists(Paths.get("temp.txt"));
}
}
File Attributes
JAVA
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
public class FileAttributes {
public static void main(String[] args) throws IOException {
Path path = Paths.get("test.txt");
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("Size: " + attrs.size());
System.out.println("Created: " + attrs.creationTime());
System.out.println("Modified: " + attrs.lastModifiedTime());
System.out.println("Is directory: " + attrs.isDirectory());
System.out.println("Is file: " + attrs.isRegularFile());
}
}
File Traversal (NIO)
JAVA
import java.io.IOException;
import java.nio.file.*;
import java.util.stream.Stream;
public class NIODirectoryWalk {
public static void main(String[] args) throws IOException {
Path dir = Paths.get(".");
// List directory
try (Stream<Path> stream = Files.list(dir)) {
stream.forEach(path -> {
String type = Files.isDirectory(path) ? "[DIR]" : "[FILE]";
System.out.println(type + " " + path.getFileName());
});
}
// Recursive walk
try (Stream<Path> stream = Files.walk(dir, 3)) { // Max 3 levels
stream.forEach(path -> System.out.println(path));
}
// Find files
try (Stream<Path> stream = Files.find(dir, 10,
(path, attrs) -> attrs.isRegularFile() && path.toString().endsWith(".txt"))) {
stream.forEach(System.out::println);
}
}
}
IO vs NIO
| Feature | IO | NIO |
|---|---|---|
| Model | Stream-oriented | Buffer-oriented |
| Blocking | Blocking IO | Non-blocking IO |
| Selectors | None | Yes |
| API | Older | Newer |
Selection Guide
| Scenario | Recommendation |
|---|---|
| Simple file read/write | Files utility class |
| Large file processing | Buffered streams |
| High-concurrency network | NIO |
| Legacy code maintenance | IO streams |
❓ Frequently Asked Questions
Q How to choose between byte streams and character streams?
A Use character streams for text files, byte streams for binary files.
Q What are the benefits of buffered streams?
A Reduce disk access次数, improve IO efficiency.
Q Is NIO faster than IO?
A Not necessarily. NIO's main advantages are non-blocking and selectors. For simple file operations, the difference is minimal.
📖 Summary
- IO streams are分为 byte streams and character streams
- Buffered streams improve IO efficiency
- NIO provides more efficient file operations
- Files utility class simplifies file operations
📝 Exercises
- File comparison: Compare two files to check if they're identical
- Large file processing: Read large files in chunks, count lines
- Directory sync: Sync one directory to another
Next Lesson
In the next lesson, we'll learn about Regex and JSON — advanced string processing techniques.



