File I/O with java.nio.file
আধুনিক Java ফাইল I/O — Path, Files এবং streaming
1. The Modern Way — java.nio.file
For two decades Java developers fought with java.io.File — a clumsy, platform-confused API with
almost no error reporting. Java 7 introduced java.nio.file (the "NIO.2" API) to
fix all of that. It gives you Path for filesystem locations, Files for operations,
and built-in support for streaming gigabyte-sized files without loading them into memory.
java.io.File API অসুবিধাজনক ছিল — platform-এর দ্বিধাগ্রস্ত, error reporting খারাপ। Java 7 থেকে java.nio.file এসেছে। এখানে Path দিয়ে ফাইল-লোকেশন, Files দিয়ে operation, এবং GB-সাইজ ফাইলও memory-তে না এনে stream হিসেবে process করা যায়। নতুন কোডে সবসময় এই নতুন API ব্যবহার করুন।
The three pillars: Path (a location), Files (static operations),
and streams / readers for large files. Nearly every real Java backend — Spring Boot, Kafka, Elasticsearch —
uses java.nio.file under the hood.
2. Path, Files, and the Flow
A Path is just a reference to a file or directory — it does not mean the file exists yet.
You build one with Path.of("..."). Then Files gives you a huge static API:
readString, writeString, lines, exists, copy,
move, delete, walk, and many more.
Path হলো শুধু একটি reference — ফাইল আছে কিনা সেটা বলে না। Path.of("...") দিয়ে তৈরি করুন। তারপর Files-এর static method দিয়ে read, write, copy, move, delete সব operation করুন। এই দুটি class-ই ৯৫% সময় যথেষ্ট।
readString, বড় ফাইলে Files.lines।
3. Write and Read a Text File
The simplest round-trip: write a few lines with Files.writeString, read them back with
Files.readString. Everything throws IOException, so main declares
throws Exception.
Files.writeString দিয়ে লিখুন, Files.readString দিয়ে পড়ুন। I/O operation-এ IOException হতে পারে, তাই main-এ throws Exception দিয়ে দিন।
import java.nio.file.*;
class Main {
public static void main(String[] args) throws Exception {
Path path = Path.of("notes.txt");
// 1) write
Files.writeString(path, "Hello Bangladesh\nABCL TECH\nJava 21\n");
// 2) read it back
String text = Files.readString(path);
System.out.println("--- file content ---");
System.out.print(text);
// 3) metadata
System.out.println("size = " + Files.size(path) + " bytes");
System.out.println("exists = " + Files.exists(path));
}
}
4. Streaming Large Files with Files.lines
Files.readAllLines loads the whole file into a List<String> — fine for a config
file, a disaster for a 5 GB log. Files.lines returns a Stream<String> that
reads one line at a time. Always close it with try-with-resources.
Files.readAllLines পুরো ফাইল memory-তে আনে — ছোট config ঠিক আছে, কিন্তু ৫ GB log হলে OutOfMemoryError। Files.lines lazy stream দেয় — একবারে একটি line পড়ে। সবসময় try-with-resources দিয়ে বন্ধ করুন।
import java.nio.file.*;
import java.util.stream.*;
class Main {
public static void main(String[] args) throws Exception {
Path p = Path.of("log.txt");
Files.writeString(p,
"INFO starting\nERROR disk full\nINFO retry\nERROR timeout\nINFO ok\n");
// count only ERROR lines — without loading the whole file
long errors;
try (Stream<String> lines = Files.lines(p)) {
errors = lines.filter(l -> l.startsWith("ERROR")).count();
}
System.out.println("error lines: " + errors);
}
}
readString. File > 10 MB → Files.lines
in try-with-resources. Never call readAllLines on something you did not write yourself.
5. BufferedReader for Fine Control
Sometimes you need more than a stream — you want to read header lines separately, or you need a specific
charset. Files.newBufferedReader gives you a BufferedReader that plays nicely with
try-with-resources and defaults to UTF-8.
Files.newBufferedReader ব্যবহার করুন — try-with-resources-এ কাজ করে এবং default-এ UTF-8।
import java.io.*;
import java.nio.file.*;
class Main {
public static void main(String[] args) throws Exception {
Path p = Path.of("users.csv");
Files.writeString(p, "name,age\nRaihan,24\nNusrat,22\nTariq,30\n");
try (BufferedReader br = Files.newBufferedReader(p)) {
String header = br.readLine();
System.out.println("header: " + header);
String line;
while ((line = br.readLine()) != null) {
String[] cols = line.split(",");
System.out.println(cols[0] + " is " + cols[1]);
}
}
}
}
6. Binary I/O, Copy, and Delete
For binary data use Files.readAllBytes / Files.write(path, bytes). For filesystem
management use Files.copy, Files.move, Files.delete, and their
-IfExists variants. The StandardCopyOption.REPLACE_EXISTING flag is your friend.
readAllBytes / write(path, bytes)। ফাইল-সিস্টেম management-এ copy, move, delete এবং তাদের -IfExists সংস্করণ। একই নামের ফাইল থাকলে overwrite করতে REPLACE_EXISTING flag দিন।
| Task | API | বাংলায় |
|---|---|---|
| Build a path | Path.of("dir", "file.txt") | location তৈরি |
| Read small text | Files.readString(p) | ছোট ফাইল পড়া |
| Write text | Files.writeString(p, s) | ফাইল-এ লেখা |
| Append text | Files.writeString(p, s, APPEND) | শেষে যোগ |
| Stream lines | Files.lines(p) | বড় ফাইল stream |
| Binary read | Files.readAllBytes(p) | raw bytes |
| Exists / size | Files.exists, Files.size | metadata |
| Copy | Files.copy(src, dst, REPLACE_EXISTING) | কপি |
| Delete | Files.deleteIfExists(p) | থাকলে মুছবে |
| List dir | Files.list(dir) | ডিরেক্টরির ফাইল |
import java.nio.file.*;
import static java.nio.file.StandardCopyOption.*;
class Main {
public static void main(String[] args) throws Exception {
Path a = Path.of("a.txt");
Path b = Path.of("b.txt");
Files.writeString(a, "original");
Files.copy(a, b, REPLACE_EXISTING);
System.out.println("b says: " + Files.readString(b));
boolean removed = Files.deleteIfExists(b);
System.out.println("deleted b: " + removed);
}
}
7. Vocabulary
| Term | Meaning | বাংলায় |
|---|---|---|
| Path | An abstract location — file or directory. | ফাইল বা ডিরেক্টরির location। |
| Files | Static utility class for all common I/O operations. | I/O operation-এর static utility class। |
| Charset | Encoding used to turn bytes into characters (UTF-8 by default). | byte → character encoding (default UTF-8)। |
| BufferedReader | A reader that reads chunks efficiently for line-by-line access. | line-by-line পড়ার efficient reader। |
| Stream<String> | Lazy sequence of lines — processed one by one. | lazy line sequence — একবারে একটি line। |
| IOException | Checked exception thrown by almost every I/O call. | I/O call-এর checked exception। |
8. Practice Problems
Try each problem yourself, then open the answer.
-
Write "Hello, I/O" to
hello.txt, read it back, and print it.hello.txt-এ "Hello, I/O" লিখে আবার পড়ে print করুন।Show Answer (উত্তর দেখুন)
Main.javaimport java.nio.file.*; class Main { public static void main(String[] args) throws Exception { Path p = Path.of("hello.txt"); Files.writeString(p, "Hello, I/O"); System.out.println(Files.readString(p)); } } -
Count the number of lines in a multi-line file using
Files.lines.Files.linesদিয়ে একটি multi-line ফাইলের line সংখ্যা গুনুন।Show Answer (উত্তর দেখুন)
Main.javaimport java.nio.file.*; import java.util.stream.*; class Main { public static void main(String[] args) throws Exception { Path p = Path.of("poem.txt"); Files.writeString(p, "one\ntwo\nthree\nfour\n"); try (Stream<String> s = Files.lines(p)) { System.out.println("lines = " + s.count()); } } } -
Append a log message to an existing file without overwriting it.overwrite না করে একটি বিদ্যমান ফাইলে log বার্তা append করুন।
Show Answer (উত্তর দেখুন)
Main.javaimport java.nio.file.*; import static java.nio.file.StandardOpenOption.*; class Main { public static void main(String[] args) throws Exception { Path p = Path.of("app.log"); Files.writeString(p, "startup\n"); Files.writeString(p, "shutdown\n", APPEND); System.out.print(Files.readString(p)); } } -
Explain in 2–3 sentences why
Files.linesmust be used inside try-with-resources.দুই-তিন বাক্যে ব্যাখ্যা করুন —Files.linesকেন try-with-resources-এ ব্যবহার করতে হয়।Show Answer (উত্তর দেখুন)
Answer:
Files.lineskeeps an open file handle behind the lazy stream. If the stream is not closed, the OS file descriptor leaks — and on long-running servers that eventually hits the file-descriptor limit. Try-with-resources guarantees the stream (and its underlying reader) is closed whether iteration finishes normally or throws.Files.lines-এর lazy stream-এর পেছনে একটি খোলা ফাইল handle থাকে। stream বন্ধ না হলে OS file descriptor leak হয় — বড় server-এ এতে limit exceed হয়ে crash হয়। try-with-resources নিশ্চিত করে — iteration শেষ হোক বা exception হোক, stream বন্ধ হবেই। -
Create a text file with 5 names, then print only names that start with 'R'.৫টি নাম লেখা একটি ফাইল বানান, তারপর শুধু 'R' দিয়ে শুরু হওয়া নামগুলো print করুন।
Show Answer (উত্তর দেখুন)
Main.javaimport java.nio.file.*; import java.util.stream.*; class Main { public static void main(String[] args) throws Exception { Path p = Path.of("names.txt"); Files.writeString(p, "Raihan\nNusrat\nRafi\nTariq\nRina\n"); try (Stream<String> s = Files.lines(p)) { s.filter(n -> n.startsWith("R")).forEach(System.out::println); } } }
Summary — Module 32
Modern Java I/O lives in java.nio.file. Build locations with Path.of, operate with
the static methods on Files, and stream huge files with Files.lines inside
try-with-resources. Use readString / writeString for small text, readAllBytes
for binary, and always let I/O exceptions propagate to a sensible boundary instead of swallowing them.
java.nio.file। Path.of দিয়ে location তৈরি করুন, Files-এর static method দিয়ে কাজ করুন, বড় ফাইল Files.lines stream দিয়ে try-with-resources-এ পড়ুন। ছোট text-এ readString/writeString, binary-তে readAllBytes।