Fundamentals 18 min read

Master Java File I/O: Practical Tips for Reading, Writing, and Managing Files

This article explains the fundamentals of Java I/O streams, showing how to efficiently read, write, copy, delete, move, and inspect both text and binary files using NIO, Buffered streams, and modern APIs, while providing ready‑to‑use code examples.

Lin is Dream
Lin is Dream
Lin is Dream
Master Java File I/O: Practical Tips for Reading, Writing, and Managing Files

Introduction

Developers should know that a computer has two core capabilities: computation and storage, and storage is essentially I/O (Input/Output). I/O can be divided into file I/O (local program and disk interaction) and network I/O (TCP data transmission).

Java unifies these concepts by treating any data flow as a stream, whether it is a byte stream or a character stream.

1. Essence of Input/Output Streams

Java streams are divided into InputStream/Reader (reading data from the outside) and OutputStream/Writer (writing data to the outside). The external source can be a file, a socket, a multipart upload, or a byte array.

All I/O operations can be summarized in three steps:

Determine the base class (byte vs. character).

Identify the data source or target (File, ByteArray, Socket, etc.).

Choose a decorator class (e.g., BufferedReader, BufferedWriter) to add buffering, formatting, or other features. Remember the rule: first decide byte or character, then the source, then the decorator.

2. Handling Text Files

Text files are readable with a text editor and are processed with character streams. The typical combination is Reader/FileReader → BufferedReader for reading and Writer/FileWriter → BufferedWriter for writing.

String uri = "/Users/Desktop/target.txt";
List<String> lines = Files.readAllLines(Paths.get(uri), StandardCharsets.UTF_8);
lines.forEach(System.out::println);

Files.write(Paths.get(uri), lines, StandardCharsets.UTF_8,
    StandardOpenOption.CREATE,
    StandardOpenOption.TRUNCATE_EXISTING,
    StandardOpenOption.WRITE);

Other common operations include copying, deleting, moving, and inspecting file attributes using Files and BasicFileAttributes or PosixFileAttributes for permission details.

Path path = Paths.get("/Users/Desktop/target2.txt");
BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
String perms = getPermissions(path);
String owner = Files.getOwner(path).getName();
long size = attr.size();
String time = DateTimeFormatter.ofPattern("MMM dd HH:mm")
    .withZone(ZoneId.systemDefault())
    .format(attr.lastModifiedTime().toInstant());
String name = path.getFileName().toString();
System.out.printf("%s %s %8d %s %s%n", perms, owner, size, time, name);

3. Handling Binary Files

Binary files (images, videos, archives, etc.) are processed with byte streams. Typical scenarios are uploading/downloading, in‑memory processing, and generating compressed archives.

// Upload example (Spring MVC)
MultipartFile file = null; // actual file from request
Path target = Paths.get("/Users/uploads/" + file.getOriginalFilename());
Files.createDirectories(target.getParent());
try (InputStream in = file.getInputStream()) {
    Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
}

// Download example (zero‑copy)
HttpServletResponse response = null; // actual response
Path filePath = Paths.get("/Users/uploads/", filename);
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(filename, "UTF-8") + "\"");
try (InputStream in = Files.newInputStream(filePath);
     OutputStream out = response.getOutputStream()) {
    in.transferTo(out);
}

In‑memory streams such as ByteArrayOutputStream and ByteArrayInputStream are useful for temporary data that should not touch the disk.

ByteArrayOutputStream baos = new ByteArrayOutputStream();
// write data to baos
InputStream in = new ByteArrayInputStream(baos.toByteArray());

Examples include creating a ZIP archive in memory, generating an Excel file with EasyExcel, or loading a key file into a byte array.

// ZIP in memory
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
    zos.putNextEntry(new ZipEntry("hello.txt"));
    zos.write("Hello, this is a file inside the zip!".getBytes("UTF-8"));
    zos.closeEntry();
}
InputStream zipIn = new ByteArrayInputStream(baos.toByteArray());

4. Decorator Classes – Standard vs. Third‑Party

Java’s standard library provides decorators for common formats (ZIP, images, text, audio). For more complex formats like PDF, Office, or video, third‑party libraries are required (e.g., Apache PDFBox, Apache POI, iText, FFmpeg). File Type Recommended Library Notes PDF Apache PDFBox, iText Read, generate, sign, merge PDFs Word (.doc/.docx) Apache POI (HWPF/XWPF) Read paragraphs, images, tables Excel (.xls/.xlsx) Apache POI (HSSF/XSSF), EasyExcel Large‑scale read/write CSV OpenCSV, SuperCSV Column‑wise processing for huge files JSON Jackson, Gson, Fastjson2 Serialization / deserialization Compression (rar/7z/tar/gz) Apache Commons Compress Universal archive support

5. Conclusion

The purpose of this article is not to make you memorize a list of Java I/O classes, but to give you a holistic view of data flow and storage. Once you grasp that everything is a stream of bytes, you can confidently tackle IM systems, logging, file services, or media processing.

JavaNIOFile I/OStreamsDecorator Patternfile-handlingBinary files
Lin is Dream
Written by

Lin is Dream

Sharing Java developer knowledge, practical articles, and continuous insights into computer engineering.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.