(OOP)
SE AIML
UNIT-V
FILE HANDLING AND DESIGN
PATTERNS
By:
Dr. Puja Gholap
WHAT IS FILE HANDLING?
File handling in programming refers to the process of
creating, reading, writing, and manipulating files
stored on secondary storage (like hard disk).It allows
programs to store data permanently instead of keeping
it temporarily in memory (RAM).
NEED FOR FILE HANDLING
To store data permanently instead of keeping it only in
memory.
To read and write data from/to files for later use.
To share data between different programs or systems.
To organize and manage large data efficiently.
Backup and Security – Files help in creating backups
and securing important data.
FILE HANDLING
The File class from the java.io package, allows us to
work with files.
To use the File class, create an object of the class, and
specify the filename or directory name:
Example
import java.io.File; // Import the File class
File myObj = new File("filename.txt"); // Specify the
filename
TYPES OF FILES
Text Files (.txt, .csv, etc.)- Store data in human-
readable form.
Example: "Hello World" stored directly as characters.
Binary Files (.dat, .bin, etc.)- Store data in
machine-readable (binary) format.
More compact and faster to read/write, but not human-
readable.
BASIC OPERATIONS IN FILE HANDLING
Creating a File – Make a new empty file.
Opening a File – Load a file into the program.
Reading from a File – Access data stored inside a file.
Writing to a File – Add new data or overwrite existing
data.
Closing a File – Release resources after operations.
FILE HANDLING CLASSES IN JAVA
Java provides classes in the java.io and java.nio
packages for file handling.
Commonly used classes:
File – Represents file or directory.
FileReader, BufferedReader – For reading text files.
FileWriter, BufferedWriter – For writing text files.
FileInputStream, FileOutputStream – For binary files.
CONCEPTS OF STREAMS
In Java, streams are the sequence of data that are read from the
source and written to the destination.
An input stream is used to read data from the source. And, an
output stream is used to write data to the destination.
In Java, streams are sequences of data.
A stream acts as a channel or pipeline through which data flows
from a source to a destination.
Java treats I/O (Input/Output) as a stream of bytes or characters.
I/O STREAMS
STREAM CLASSES IN JAVA
Stream classes are divided into two main categories:
1. Byte Stream Classes
2. Character Stream Classes
1. BYTE STREAM CLASSES
A Byte Stream in Java is used to handle input and
output of raw binary data.
It reads and writes data in bytes (8-bit data), making
it suitable for handling audio, video, and image files. It
uses InputStream and OutputStream classes to
perform these operations.
Used for handling raw binary data (images, audio,
video, executable files). Based on 8-bit bytes. Java
Provide s two kind of byte stream classes:
1. InputStream Classes → for reading byte data.
2. OutputStream Classes → for writing byte data.
1. INPUTSTREAM CLASSES
In Java, the InputStream class is an abstract superclass that represents
all classes that read bytes from a source (like files, network connections,
or memory).
It belongs to the package:import java.io.*;
It is used for reading binary data (byte-based input).
Hierarchy of InputStream
java.lang.Object
java.io.InputStream
FileInputStream ByteArrayInputStream
FilterInputStream PipedInputStream
BufferedInputStream
DataInputStream
PushbackInputStream
EXAMPLE- FILEINPUTSTREAM
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class InputStreamExample {
public static void main(String[] args) {
try (InputStream inputStream = new
FileInputStream("example.txt")) {
int data;
while ((data = inputStream.read()) != -1) {
System.out.print((char) data); // Assuming text
data for demonstration
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
EXAMPLE- FILEINPUTSTREAM
Input file example.txt
Output file InputStreamExample.java
METHODS IN INPUTSTREAM CLASS
Method Description
Reads one byte of data; returns -1 at
int read()
end of file.
int read(byte[] b) Reads bytes into an array.
Reads up to len bytes into part of an
int read(byte[] b, int off, int len)
array.
Closes the stream and releases
void close()
system resources.
Returns number of bytes that can be
int available()
read without blocking.
long skip(long n) Skips over n bytes.
2. OUTPUTSTREAM CLASSES IN JAVA
1. IntroductionOutputStream is an abstract superclass
representing all classes that write bytes to a
destination such as:
a file,
a network socket,
or an array in memory.
It is byte-oriented, meaning it deals with binary data,
not text characters.
Belongs to package:import java.io.*;
2. OUTPUTSTREAM CLASSES IN JAVA
java.lang.Object
java.io.OutputStream
FileOutputStream ByteArrayOutputStream FilterOutputStream
BufferedOutputStream
DataOutputStream
PrintStream
2. CHARACTER STREAM CLASSES
These handle data in 16 bit Unicode. Using these you
can read and write text data only.
The Reader and Writer classes are the super classes of
all the character stream classes: classes that are used
to read/write character streams. Following are the
character array stream classes provided by Java −
Reader Writer
BufferedReader BufferedWriter
CharacterArrayReader CharacterArrayWriter
StringReader StringWriter
FileReader FileWriter
InputStreamReader InputStreamWriter
FileReader FileWriter
EXAMPLE
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class IOStreamsExample {
public static void main(String args[]) throws IOException {
//Creating FileReader object
File file = new File("D:/myFile.txt");
FileReader reader = new FileReader(file);
char chars[] = new char[(int) file.length()];
//Reading data from the file
reader.read(chars);
//Writing data to another file
File out = new File("D:/CopyOfmyFile.txt");
FileWriter writer = new FileWriter(out);
//Writing data to the file
writer.write(chars);
writer.flush();
System.out.println("Data successfully written in the specified file");
}
}
EXAMPLE
Input file example.txt
Output file example1.txt
Output file IOStreamsExample.java
DIFFERENCE BETWEEN BYTE STREAM AND
CHARACTER STREAM
Feature Byte Stream Character Stream
InputStream,
Base Classes Reader, Writer
OutputStream
Data Type Bytes (8-bit) Characters (16-bit)
Binary data (images, Text data (files,
Suitable For
audio) documents)
Automatic
Encoding No conversion
encoding/decoding
FileInputStream,
Example Classes FileReader, FileWriter
FileOutputStream
FILE CREATION IN JAVA
import java.io.*;
public class CreateFileExample {
Output:
public static void main(String[] args) {
File created: example.txt
try { If run again:
File already exists.
// Create a File object
File file = new File("example.txt");
// Create new file if not already exists
if (file.createNewFile()) {
System.out.println("File created: " + file.getName());
} else {
System.out.println("File already exists.");
}
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
WRITING CHARACTERS TO A FILE
import java.io.*;
public class WriteCharactersExample {
public static void main(String[] args) {
try {
FileWriter fw = new FileWriter("characterFile.txt");
fw.write("Hello Java!\n");
fw.write("This is a character stream example.");
fw.close();
System.out.println("Successfully written to the file.");
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
} Output: Hello Java!
This is a character stream example.
WRITING CHARACTERS TO A FILE
READING CHARACTERS FROM A FILE
import java.io.*;
public class ReadCharactersExample {
public static void main(String[] args) {
try {
FileReader fr = new FileReader("characterFile.txt");
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
fr.close();
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
} On Command Prompt:
Hello Java!
This is a character stream example.
READING AND WRITING BYTES
In Java, Byte Streams are used to perform input and
output of 8-bit bytes.
These streams are mainly used for binary data like
images, audio, video, or executable files.
Java provides two abstract classes for byte stream
operations:
InputStream – for reading bytes from a source.
OutputStream – for writing bytes to a destination.
COMMON BYTE STREAM CLASSES
Class Description
FileInputStream Used to read bytes from a file
FileOutputStream Used to write bytes to a file
Adds buffering for efficient byte
BufferedInputStream
reading
Adds buffering for efficient byte
BufferedOutputStream
writing
DataInputStream / Used to read/write primitive data
DataOutputStream types
ByteArrayInputStream /
Used for byte array input/output
ByteArrayOutputStream
WRITING BYTES TO A FILE
// Program: Writing bytes to a file using FileOutputStream
import java.io.*;
public class WriteBytesExample {
public static void main(String[] args) {
try {
// Create a file output stream to write bytes
FileOutputStream fos = new FileOutputStream("output.txt");
// Data to write (converted to bytes)
String data = "Hello, Java Byte Stream!";
byte[] bytes = data.getBytes();
// Write data to the file
fos.write(bytes);
System.out.println("Data written successfully to output.txt");
fos.close();
}
catch (IOException e) {
System.out.println("Error writing file: " + e.getMessage());
}
}
}
READING BYTES FROM A FILE
// Program: Reading bytes from a file using FileInputStream
import java.io.*;
public class ReadBytesExample {
public static void main(String[] args) {
try {
// Create a file input stream to read bytes
FileInputStream fis = new FileInputStream("output.txt");
int i;
System.out.print("File content: ");
// Read byte by byte until end of file (-1)
while ((i = fis.read()) != -1) {
System.out.print((char) i); // convert byte to character
}
fis.close();
}
catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
}
}
}
HANDLING PRIMITIVE DATA TYPES
When you work with files in Java, Byte Streams
(FileInputStream, FileOutputStream) and Character
Streams (FileReader, FileWriter) can only handle raw
bytes or characters.
But sometimes, we need to store and retrieve primitive
data types like int, float, double, boolean, etc. directly
in binary form.
For this, Java provides special filter stream classes:
DataOutputStream — for writing primitive data types.
DataInputStream — for reading primitive data types.
Both belong to the java.io package.
FILTER STREAM CLASSES:
Class Description
Writes primitive data types (int, float, double,
DataOutputStream boolean, char, long, short) in binary form to an
output stream.
Reads primitive data types from an input stream.
DataInputStream
Must read in the same order they were written.
COMMON METHODS
Class Method Description
Writes an integer (4
DataOutputStream writeInt(int v)
bytes)
DataOutputStream writeDouble(double v) Writes a double (8 bytes)
DataOutputStream writeBoolean(boolean v) Writes a boolean (1 byte)
Writes a string in UTF-8
DataOutputStream writeUTF(String s)
format
DataInputStream readInt() Reads an integer
DataInputStream readDouble() Reads a double
DataInputStream readBoolean() Reads a boolean
Reads a string written by
DataInputStream readUTF()
writeUTF()
WRITING PRIMITIVE DATA TYPES TO A FILE
// Program: Writing primitive data types using DataOutputStream
import java.io.*;
public class WritePrimitivesExample {
public static void main(String[] args) {
try {
// Create a DataOutputStream connected to a file
FileOutputStream fos = new FileOutputStream(“example.txt");
DataOutputStream dos = new DataOutputStream(fos);
// Writing primitive data types
dos.writeInt(25);
dos.writeDouble(123.45);
dos.writeBoolean(true);
dos.writeChar('A');
dos.writeUTF("Hello Java");
System.out.println("Data written successfully to data.dat");
dos.close();
fos.close();
}
catch (IOException e) {
System.out.println("Error writing file: " + e.getMessage());
}
}
}
WRITING PRIMITIVE DATA TYPES TO A FILE
READING PRIMITIVE DATA TYPES FROM A FILE
// Program: Reading primitive data types using DataInputStream
import java.io.*;
public class ReadPrimitivesExample {
public static void main(String[] args) {
try {
// Create a DataInputStream connected to the file
FileInputStream fis = new FileInputStream("data.dat");
DataInputStream dis = new DataInputStream(fis);
// Reading must be done in the same order as writing
int num = dis.readInt();
Output:
double value = dis.readDouble();
boolean flag = dis.readBoolean();
Integer: 25
char ch = dis.readChar(); Double: 123.45
String text = dis.readUTF(); Boolean: true
// Display read data
Character: A
System.out.println("Integer: " + num);
String: Hello Java
System.out.println("Double: " + value);
System.out.println("Boolean: " + flag);
System.out.println("Character: " + ch);
System.out.println("String: " + text);
dis.close();
fis.close();
}
catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
}
}
}
CONCATENATING AND BUFFERING FILES
Concatenation means combining the contents of two or
more files into a single output file.
In Java, this can be done using:
SequenceInputStream (for reading multiple files
sequentially)
FileInputStream and FileOutputStream (for writing
the combined content)
SEQUENCEINPUTSTREAM
Class Used: SequenceInputStream
Package: java.io
Purpose: Reads multiple input streams sequentially as
one continuous stream.
Constructor Description
SequenceInputStream(InputStre
Combines two input streams.
am s1, InputStream s2)
SequenceInputStream(Enumerat Combines multiple input streams
ion<? extends InputStream> e) using an Enumeration.
EXAMPLE: CONCATENATING TWO FILES
import java.io.*;
import java.util.*;
public class ConcatenateFiles {
public static void main(String[] args) {
try {
FileInputStream file1 = new FileInputStream("file1.txt"); // Open two input files
FileInputStream file2 = new FileInputStream("file2.txt");
SequenceInputStream sis = new SequenceInputStream(file1, file2); // Combine both input
streams
FileOutputStream fos = new FileOutputStream("combined.txt"); // Create output file
int i;
while ((i = sis.read()) != -1) {
fos.write(i);
}
System.out.println("Files concatenated successfully into combined.txt");
sis.close(); // Close all streams
fos.close(); Output:
file1.close(); If:
file2.close(); file1.txt → Hello
} file2.txt → Java
catch (IOException e) { Then:
System.out.println("Error: " + e.getMessage()); combined.txt → HelloJava
} }}
BUFFERING FILES
What is Buffering?
Buffering means temporarily storing data in a memory
buffer to improve performance.
Instead of reading/writing one byte at a time, data is
handled in chunks — reducing disk I/O operations.
Class Description
Buffers input data to improve
BufferedInputStream
reading speed
Buffers output data to improve
BufferedOutputStream
writing speed
WORKING OF BUFFERED STREAM CLASSES
FileInputStream --> BufferedInputStream --> Program
Program --> BufferedOutputStream -->
FileOutputStream
EXAMPLE: BUFFERED READING AND WRITING
// Program: Using Buffered Streams for efficient file copy
import java.io.*;
public class BufferedFileCopy {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("source.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("copy.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int b;
while ((b = bis.read()) != -1) {
bos.write(b);
}
bos.flush(); // ensures all data is written
System.out.println("File copied successfully using buffering!");
// Close all streams
bis.close();
bos.close();
}
catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
ADVANTAGES OF BUFFERING
Faster performance (reduces I/O operations).
Efficient use of resources.
Automatically flushes data when buffer is full.
Ideal for large files or frequent I/O operations.
RANDOM ACCESS FILES
Normally, file I/O in Java is sequential — meaning
data is read or written from start to end only.
If you want to jump (seek) to any position in a file and
read or write data there, you use a Random Access
File.
Class: RandomAccess
FilePackage: java.io
Purpose: Allows both reading and writing data at any
position in a file.
It behaves like a combination of:
FileInputStream + FileOutputStream with the extra
ability to move the file pointer anywhere inside the file
BENEFITS OF USING RANDOM ACCESS FILE
Unlike IO streams that allow reading and writing data
sequentially, random access file allows you to read and
write a small chunk of data at any position in the file,
using a file pointer.
By controlling this file pointer, you can move forth and
back within the file to perform reading and writing
operations, at any position you want, in a random
fashion.
Random access file is ideal for manipulating a
particular file format at low level, such as reading,
creating and updating MP3 files, PDF files, etc and
even your own file format
HOW TO USE THE RANDOMACCESSFILE
CLASS
Constructor
RandomAccessFile(String filename, String mode)
Parameter Description
filename Name or path of the file
"r" for read-only, "rw" for read and
mode
write
File: employee
+------------------------------------------------+
| EmpID | Name | Salary | EmpID | Name | Salary |
+------------------------------------------------+
↑
File Pointer
(Can move anywhere)
WRITING AND READING USING RANDOMACCESSFILE
// Program: Demonstrate RandomAccessFile for read/write operations
import java.io.*;
public class RandomAccessExample {
public static void main(String[] args) {
try {
// Open file in read-write mode
RandomAccessFile raf = new RandomAccessFile("data.dat", "rw");
// Writing data
raf.writeInt(101);
raf.writeUTF("Alice");
raf.writeDouble(55000.75);
raf.writeInt(102);
raf.writeUTF("Bob");
raf.writeDouble(62000.50);
System.out.println("Data written successfully!");
// Move pointer to start
raf.seek(0);
WRITING AND READING USING RANDOMACCESSFILE
// Reading data
while (raf.getFilePointer() < raf.length()) {
int id = raf.readInt();
String name = raf.readUTF();
double salary = raf.readDouble();
System.out.println("ID: " + id + ", Name: " + name + ",
Salary: " + salary);
}
raf.close();
}
catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
} Data written successfully!
} ID: 101, Name: Alice, Salary: 55000.75
ID: 102, Name: Bob, Salary: 62000.5
ADVANTAGES OF RANDOM ACCESS FILES
Advantage Description
Jump to any position without reading the
Direct access
whole file
Modify only required parts instead of
Fast updates
rewriting the whole file
Versatile Can read/write both text and binary data
Ideal for databases Useful for storing fixed-size records
DESIGN PATTERN
“A design pattern is a general reusable solution to a
commonly occurring problem within a given context in
software design.”
A Design Pattern is a reusable solution to a common
problem that occurs during software design and
development.
They are not code templates but well-proven design
concepts that make software flexible, reusable, and
maintainable.
ADVANTAGES OF USING DESIGN PATTERNS
Reusability – Proven solutions can be reused across
projects.
Maintainability – Easier to understand and modify.
Scalability – Supports changes and future
enhancements.
Improved communication – Common vocabulary
among developers (e.g., “Use Singleton pattern
here”).Efficiency – Reduces development time by
reusing solutions.
TYPES OF DESIGN PATTERNS
Type Purpose Example Patterns
Object creation
mechanisms, trying to Singleton, Factory, Builder,
Creational
create objects in a suitable Prototype
way
Composition of classes and
Adapter, Decorator, Proxy,
Structural objects to form larger
Facade
structures
Communication between
Iterator, Observer, Strategy,
Behavioral objects and the way they
Command
interact
1. ADAPTER PATTERN (STRUCTURAL)
The Adapter Pattern allows two incompatible
interfaces to work together.
It acts as a bridge between existing classes with
different interfaces.
E.g
Think of a mobile charger adapter — your phone’s
charger plug doesn’t fit into every socket,so you use an
adapter to make it compatible.
1. ADAPTER PATTERN (STRUCTURAL)
Purpose:
The Adapter Pattern allows incompatible interfaces to
work together. It acts as a bridge between two
incompatible classes.
Definition
The Adapter Pattern converts the interface of a class
into another interface the client expects.
Real-Life Example
A memory card cannot be directly connected to a
laptop — you use a card reader (adapter).Similarly, in
Java, an adapter makes incompatible classes
compatible.
1. ADAPTER PATTERN (STRUCTURAL)
interface MediaPlayer {// Target interface
void play(String audioType, String fileName);
}
class MediaAdapter implements MediaPlayer { // Adaptee class
AdvancedMediaPlayer advancedMusicPlayer = new AdvancedMediaPlayer();
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("mp3"))
advancedMusicPlayer.playMp3(fileName);
else if(audioType.equalsIgnoreCase("mp4"))
advancedMusicPlayer.playMp4(fileName);
} }
class AdvancedMediaPlayer {// Helper class
void playMp3(String fileName) {
System.out.println("Playing MP3 file: " + fileName);
}
void playMp4(String fileName) {
System.out.println("Playing MP4 file: " + fileName);
} }
public class AdapterPatternDemo {// Client code
public static void main(String[] args) {
MediaPlayer player = new MediaAdapter();
player.play("mp3", "song1.mp3");
player.play("mp4", "video1.mp4"); Playing MP3 file: song1.mp3
}
Playing MP4 file: video1.mp4
}
2. SINGLETON DESIGN PATTERN (CREATIONAL
PATTERN)
Purpose
Ensures that only one instance of a class is created
and provides a global point of access to it.
Definition
The Singleton Pattern restricts the instantiation of a
class to a single object.
Use Cases
Managing shared resources (e.g., Database connection,
Logger, Configuration settings).Thread pools, caching,
etc.
2. SINGLETON DESIGN PATTERN (CREATIONAL
class Singleton { PATTERN)
private static Singleton instance;
// private constructor
private Singleton() {}
// static method to get single instance
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
} Output;
return instance; Singleton Instance Called!
} true
void showMessage() {
System.out.println("Singleton Instance Called!");
}
}
public class SingletonDemo {
public static void main(String[] args) {
Singleton obj1 = Singleton.getInstance();
Singleton obj2 = Singleton.getInstance();
obj1.showMessage();
// both objects point to same instance
System.out.println(obj1 == obj2); // true
}
}
3. ITERATOR DESIGN PATTERN (BEHAVIORAL
PATTERN)
Purpose
Provides a way to access elements of a collection
sequentially without exposing its internal structure.
Definition
The Iterator Pattern allows clients to traverse a
collection one element at a time.
Use Cases
Traversing collections (ArrayList, HashSet,
etc.)Custom collections that need sequential access
3. ITERATOR DESIGN PATTERN (BEHAVIORAL
PATTERN)
import java.util.*;
public class IteratorExample {
public static void main(String[] args) {
ArrayList<String> students = new ArrayList<>();
students.add("Pooja");
students.add("Ravi");
students.add("Sneha");
Iterator<String> itr = students.iterator();
while (itr.hasNext()) {
System.out.println("Student: " + itr.next());
}
Output:
} Student: Pooja
} Student: Ravi
Student: Sneha
DESIGN PATTERN TYPES
Pattern Type Purpose Example Use
Connect old
Connect
media player
Adapter Structural incompatible
with new file
interfaces
types
Database
Ensure only one
Singleton Creational connection,
instance exists
Logger
Sequential access
Traversing
Iterator Behavioral to collection
ArrayList or Set
elements
THANK YOU