Reading and writing files in Java can be accomplished using
classes from the java.io package. Inner classes provide a way to logically
group classes that are only used in one place, increasing encapsulation.
Here, I'll guide you through a scenario where you use an
inner class to handle file reading and writing.
Overview
- Outer
Class (FileHandler): The main class that manages file operations.
- Inner
Class (FileReaderWriter): A nested class inside FileHandler
responsible for reading from and writing to a file.
Benefits of Using an Inner Class
- Encapsulation:
The inner class FileReaderWriter is encapsulated within FileHandler,
making it inaccessible from outside. This prevents unintended use by other
classes.
- Logical
Grouping: The FileReaderWriter class is closely related to the FileHandler
class, and logically it makes sense to group them together.
- Access
to Outer Class Members: The inner class can directly access the
members (fields and methods) of the outer class.
Implementation
Here’s how you can implement file reading and writing using
an inner class:
java
import
java.io.BufferedReader; import
java.io.BufferedWriter; import
java.io.FileReader; import
java.io.FileWriter; import
java.io.IOException; public class
FileHandler { private String filePath; // Constructor to initialize the file
path public FileHandler(String filePath) { this.filePath = filePath; } // Inner class to handle file reading and
writing public class FileReaderWriter { // Method to write content to a file public void writeToFile(String
content) { try (BufferedWriter writer = new
BufferedWriter(new FileWriter(filePath))) { writer.write(content);
System.out.println("Content written to file successfully."); } catch (IOException e) { System.out.println("An
error occurred while writing to the file: " + e.getMessage()); } } // Method to read content from a file public String readFromFile() { StringBuilder content = new
StringBuilder(); try (BufferedReader reader = new
BufferedReader(new FileReader(filePath))) { String line; while ((line =
reader.readLine()) != null) {
content.append(line).append("\n"); }
System.out.println("Content read from file successfully."); } catch (IOException e) { System.out.println("An
error occurred while reading from the file: " + e.getMessage()); } return content.toString(); } } public static void main(String[] args) { // Initialize the FileHandler with a
file path FileHandler fileHandler = new
FileHandler("example.txt"); // Create an instance of the inner
class FileReaderWriter fileRW =
fileHandler.new FileReaderWriter(); // Write content to the file fileRW.writeToFile("Hello, this
is a test file.\nThis file is written using Java."); // Read content from the file String content =
fileRW.readFromFile(); System.out.println("File
Content:\n" + content); } } |
Explanation
- Outer
Class (FileHandler):
- It
contains a private field filePath to store the path of the file.
- The
constructor initializes the filePath.
- Inner
Class (FileReaderWriter):
- It
handles file reading and writing operations.
- writeToFile
Method: Uses BufferedWriter to write content to the specified file.
It handles exceptions to ensure that the file operation is safe.
- readFromFile
Method: Uses BufferedReader to read content from the specified file.
It appends each line read to a StringBuilder and returns the full
content.
- main
Method:
- It
creates an instance of FileHandler and then an instance of the inner
class FileReaderWriter.
- It
writes content to the file using writeToFile.
- It
reads the content back using readFromFile and prints it to the console.
Key Concepts:
- Encapsulation:
FileReaderWriter is hidden inside FileHandler, so it's not exposed to
other parts of the program.
- Resource
Management: The try-with-resources statement ensures that the file
resources (BufferedWriter, BufferedReader) are automatically closed after
use, preventing resource leaks.
- Inner
Class Access: The inner class can access the filePath directly without
needing to pass it as a parameter, which simplifies the code.
This setup ensures that file operations are well-organized,
safe, and encapsulated within the FileHandler class.
Real example of Inner class use
public class
Main { |
The Java program you've shared reads data from an input.txt
file, processes it according to specific criteria, and writes the output to an output.txt
file. Let's break it down into its components and understand how it works.
Overview of the Program
- Student
Class:
- A
nested static class Student with three fields: id, courseName, and marks.
- Standard
getter and setter methods are provided to access and modify these fields.
- processData
Method:
- This
method processes a list of Student objects (ArrayList<Student>) and
returns a Map<String, Student>, which holds selected Student
objects based on the course name.
- The
students are first sorted by id and then by courseName.
- Only
one student per course ("Data Structures" and
"English") is retained in the output map.
- Main
Method:
- Reads
student data from input.txt, creates Student objects, and adds them to an
ArrayList<Student>.
- Calls
processData to process the list.
- Writes
the result to output.txt.
Step-by-Step Breakdown
- Reading
the File:
- The
program uses Scanner to read each line of the input.txt file.
- Each
line is split by the delimiter |, creating an array that holds the
student's id, courseName, and marks.
- Creating
Student Objects:
- For
each line, a new Student object is created and populated with the data
from the array.
- These
Student objects are then added to the ArrayList<Student> named studentCourseList.
- Processing
the Data:
- The processData
method sorts the students by id and then by courseName.
- It
selects the first student it encounters for each of the courses
"Data Structures" and "English" and adds them to the
result map (retVal).
- Writing
to the Output File:
- The
result map is iterated over, and the selected course names and marks are
written to output.txt.
Example Input and Output
input.txt:
1|Data
Structures|85 2|English|90 1|English|88 3|Data
Structures|75 |
output.txt (after processing):
Data
Structures: 85 English: 90 |
Explanation of Key Parts:
- Sorting:
- The
sorting is done using an anonymous Comparator class.
- Students
are sorted first by id and then by courseName. If the ids are different,
the comparison returns their difference. If the ids are the same, the courseName
is used for sorting.
- Course
Selection:
- The
program selects only the first occurrence of "Data Structures"
and "English" after sorting. This is controlled by the countDS
and countEng flags to ensure only the first encountered course is
processed.
- File
Handling:
- The
program uses BufferedReader and FileReader to read input and BufferedWriter
and FileWriter to write output, ensuring efficient file operations.
Notes and Improvements:
- Generics:
The Comparator could be improved by using generics to avoid the need for
unchecked casts.
- Exception
Handling: The program catches IOException, but other potential
exceptions (like NumberFormatException when parsing id and marks) should
also be handled.
- File
Paths: Consider using relative paths or configuration for file
locations, or better yet, pass file paths as command-line arguments to
make the program more flexible.
- Method
Overloading: The processData method could be overloaded or
parameterized to handle different course names, not just "Data
Structures" and "English".
This program demonstrates basic file I/O, sorting with a
custom comparator, and using an inner class to represent structured data in
Java.
0 Comments