Lesson ১৪৭ মিনিট পড়া

ফাইল আই/ও (File I/O)

একজন প্রফেশনালের মতো ফাইলে ডেটা লিখুন এবং তা থেকে পড়ুন

ফাইল আই/ও কেন প্রয়োজন? (Why File I/O?)

এতক্ষণ পর্যন্ত, আপনার প্রোগ্রামের কাজ শেষ হওয়ার সাথে সাথে এর সমস্ত ডেটাও মুছে যাচ্ছিল — অনেকটা হোয়াইটবোর্ডে লিখে আবার সেটি মুছে ফেলার মতো। ফাইল আই/ও বা File I/O (ইনপুট/আউটপুট বা Input/Output) আপনাকে এই ডেটাগুলো ফাইলে সংরক্ষণ করার এবং পরে আবার তা পড়ে দেখার সুযোগ করে দেয়। এটি হোয়াইটবোর্ডের বদলে একটি খাতায় লিখে রাখার মতোই ব্যাপার।

ফাইল নিয়ে কাজ করার জন্য জাভা আপনাকে বেশ কিছু টুলস বা সরঞ্জাম দেয়:

  • File — এটি মূলত কোনো ফাইল বা ডিরেক্টরির পাথকে (path) প্রকাশ করে। এটি নিজে থেকে সরাসরি কোনো কিছু পড়ে না বা লেখে না, বরং ফাইলের অবস্থানটি নির্দেশ করে।
  • Scanner — এটি ফাইল থেকে টেক্সট বা লেখা পড়ে (আপনি তো ইতিমধ্যেই ইউজারের কাছ থেকে ইনপুট নেওয়ার ব্যাপারে এর সাথে পরিচিত!)।
  • FileWriter / PrintWriter — ফাইলগুলোতে টেক্সট লেখার কাজ করে।
  • BufferedReader — অত্যন্ত দক্ষতার সাথে লাইন বাই লাইন ফাইলগুলো থেকে ডেটা পড়ে থাকে।

সবচেয়ে জরুরি নিয়মটি হলো: কাজ শেষ হওয়ার পর সব সময় আপনার ফাইলগুলোকে বন্ধ করে দেবেন (close your files)। এর চেয়েও ভালো হয় যদি আপনি try-with-resources ব্যবহার করেন, কারণ তাহলে জাভা নিজেই আপনার হয়ে সেগুলো বন্ধ করে দেবে।

ফাইলে লেখা (Writing to a File)

import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
// Method 1: PrintWriter — easy and familiar
try (PrintWriter writer = new PrintWriter(new FileWriter("scores.txt"))) {
writer.println("=== High Scores ===");
writer.println("Anika: 950");
writer.println("Rafi: 870");
writer.println("Sadia: 920");
writer.printf("Average: %.1f%n", (950 + 870 + 920) / 3.0);
System.out.println("File written successfully!");
} catch (IOException e) {
System.out.println("Error writing file: " + e.getMessage());
}
// Method 2: Appending to an existing file (true = append mode)
try (PrintWriter appender = new PrintWriter(new FileWriter("scores.txt", true))) {
appender.println("Tariq: 990"); // added to the end
System.out.println("Appended successfully!");
} catch (IOException e) {
System.out.println("Error appending: " + e.getMessage());
}
}
}
Output
File written successfully!
Appended successfully!

ফাইল থেকে ডেটা পড়া (Reading Files)

ফাইল পড়া অনেকটা বই পড়ার মতোই — আপনি চাইলে লাইন ধরে ধরে, শব্দ মিলিয়ে মিলিয়ে অথবা চোখের পলকে পুরোটা একসাথে পড়ে ফেলতে পারেন। এর মধ্যে সবচেয়ে পরিচিত উপায়গুলো হলো:

  • Scanner — এটি বেশ সহজ এবং পরিচিত একটি পদ্ধতি। ছোট আকারের ফাইল এবং ভিন্ন ভিন্ন ধরনের ডেটা পার্স (parsing) করার ক্ষেত্রে এটি খুব কাজে আসে।
  • BufferedReader — বড় ফাইলগুলোর ক্ষেত্রে এটি অনেক বেশি কার্যকর বা দক্ষ। এটি এক এক করে অক্ষর বা ক্যারেক্টার পড়ার বদলে একসাথে অনেকগুলো ডেটার ব্লক বা চাঙ্ক (chunk) মেমোরির একটি বাফারে (buffer) লোড করে (ঠিক যেমন একসাথে একটি অক্ষরের দিকে না তাকিয়ে অনেকগুলো পৃষ্ঠা মাথায় লোড করে নেওয়া)।

খুব ভালোভাবে ফাইল বন্ধ হওয়া নিশ্চিত করতে এই দুটির সাথেই try-with-resources ব্যবহার করা উচিত, এমনকি যদি মাঝপথে কোনো এরর বা ত্রুটিও দেখা দেয়।

Scanner দিয়ে পড়া (Reading with Scanner)

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// First, let's check if the file exists
File file = new File("scores.txt");
System.out.println("File exists: " + file.exists());
System.out.println("File name: " + file.getName());
System.out.println("Absolute path: " + file.getAbsolutePath());
System.out.println("---");
// Read the file line by line with Scanner
try (Scanner reader = new Scanner(file)) {
int lineNumber = 1;
while (reader.hasNextLine()) {
String line = reader.nextLine();
System.out.println(lineNumber + ": " + line);
lineNumber++;
}
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
}
}
}
Output
File exists: true
File name: scores.txt
Absolute path: /path/to/scores.txt
---
1: === High Scores ===
2: Anika: 950
3: Rafi: 870
4: Sadia: 920
5: Average: 913.3
6: Tariq: 990

BufferedReader — চমৎকার দক্ষতায় ডেটা পড়া (BufferedReader — Efficient Reading)

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.PrintWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// First, create a sample CSV file
try (PrintWriter w = new PrintWriter(new FileWriter("students.csv"))) {
w.println("Name,Grade,Score");
w.println("Anika,A,95");
w.println("Rafi,B,83");
w.println("Sadia,A,91");
w.println("Tariq,C,74");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
return;
}
// Read and parse the CSV with BufferedReader
ArrayList<String> honorRoll = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader("students.csv"))) {
String header = br.readLine(); // skip header row
System.out.println("Header: " + header);
System.out.println("---");
String line;
while ((line = br.readLine()) != null) {
String[] parts = line.split(",");
String name = parts[0];
String grade = parts[1];
int score = Integer.parseInt(parts[2]);
System.out.printf("%s got a %s (%d)%n", name, grade, score);
if (score >= 90) {
honorRoll.add(name);
}
}
System.out.println("\nHonor Roll: " + honorRoll);
} catch (IOException e) {
System.out.println("Error reading: " + e.getMessage());
}
}
}
Output
Header: Name,Grade,Score
---
Alice got a A (95)
Bob got a B (83)
Charlie got a A (91)
Diana got a C (74)

Honor Roll: [Anika, Sadia]
Note: ফাইল নিয়ে কাজ করার জন্য try-with-resources ব্যবহার করার অভ্যাস গড়ে তুলুন। যদি কোনো কারণে ফাইল থেকে পড়া বা ফাইলটিতে লেখা শেষ হওয়ার আগেই কিংবা ফাইলটিকে বন্ধ করার আগেই আপনার প্রোগ্রামটি ক্র্যাশ করে, তবে ডেটা হারিয়ে যেতে পারে অথবা ফাইলটি লক (lock) হয়ে আটকে থাকতে পারে। Try-with-resources হলো আপনার জন্য এক ধরনের নিরাপত্তা জাল — পরিস্থিতি যতই খারাপ হোক না কেন, এটি যেকোনো মূল্যেই আপনার ফাইলগুলো বন্ধ করতে ভুলবে না।
চ্যালেঞ্জ

ছোট কুইজ

File ক্লাসটি আসলে কী কাজ করে?
Exception HandlingLambdas & Streams