JAVA I/O
Java I/O revolves around two primary concepts: streams and readers/writers.
Streams: Streams represent a sequence of data. In Java, there are two types of
streams: input streams and output streams. Input streams are used to read data
from a source, while output streams are used to write data to a destination.
Streams can be categorized into byte streams (InputStream and OutputStream)
and character streams (Reader and Writer).
Readers/Writers: Readers and writers are specialized stream classes designed for
handling character data. They provide a convenient way to read from and write to
character-based data sources. Readers read character data from input streams,
while writers write character data to output streams.
Stream
A stream is a sequence of data. In Java, a stream is composed of bytes. It's called a
stream because it is like a stream of water that continues to flow.
In Java, 3 streams are created for us automatically. All these streams are attached
with the console.
1) [Link]: standard output stream
2) [Link]: standard input stream
3) [Link]: standard error stream
Let's see the code to print output and an error message to the console.
1. [Link]("simple message");
2. [Link]("error message");
Let's see the code to get input from console.
1. int i=[Link]();//returns ASCII code of 1st character
2. [Link]((char)i);//will print the character
OutputStream Vs. InputStream
The explanation of OutputStream and InputStream classes are given below:
1
OutputStream
Java application uses an output stream to write data to a destination; it may be a
file, an array, peripheral device or socket.
InputStream
Java application uses an input stream to read data from a source; it may be a file,
an array, peripheral device or socket.
Let's understand the working of Java OutputStream and InputStream class by the
figure given below.
OutputStream Class
OutputStream class is an abstract class. It is the superclass of all classes
representing an output stream of bytes. An output stream accepts output bytes
and sends them to some sink.
Useful Methods of OutputStream Class
Method Description
public void write(int) throws It is used to write a byte to the
IOException current output stream.
2
public void write(byte[])throws It is used to write an array of byte
IOException to the current output stream.
public void flush() throws It flushes the current output
IOException stream.
public void close() throws It is used to close the current
IOException output stream.
OutputStream Hierarchy
InputStream Class
InputStream class is an abstract class. It is the superclass of all classes representing
an input stream of bytes.
Useful Methods of InputStream Class
Method Description
public abstract int read() throws It reads the next byte of data from
IOException the input stream. It returns -1 at the
end of the file.
public int available() throws It returns an estimate of the number
IOException of bytes that can be read from the
current input stream.
public void close() throws IOException It is used to close the current input
stream.
3
InputStream Hierarchy
Java I/O Classes
1. Java provides a rich set of classes for performing I/O operations. Some of
the key classes include:
2. InputStream and OutputStream: These abstract classes form the
foundation for byte-oriented I/O operations. They provide methods for
reading and writing bytes from/to various sources and destinations.
3. Reader and Writer: These abstract classes are used for character-based I/O
operations. They provide methods for reading and writing characters
from/to character-based streams.
4. FileInputStream and FileOutputStream: These classes allow reading from
and writing to files in a byte-oriented manner.
5. FileReader and FileWriter: These classes enable reading from and writing
to files using character-oriented operations.
6. BufferedInputStream and BufferedOutputStream: These classes provide
buffering capabilities, which can significantly improve I/O performance by
reducing the number of system calls.
7. BufferedReader and BufferedWriter: These classes offer buffered reading
and writing of character data, enhancing I/O efficiency when working with
character-based streams.
Practical Applications of Java I/O
Java I/O is employed in various real-world scenarios, including:
1. File Handling: Java I/O is extensively used for reading from and writing to
files. Developers can manipulate files, create directories, and perform file-
related operations using Java's file I/O classes.
4
2. Network Communication: Java's socket classes (Socket and ServerSocket)
facilitate network communication by enabling data exchange between
client and server applications over TCP/IP.
3. Serialization: Java's serialization mechanism allows objects to be converted
into a stream of bytes for storage or transmission. It is particularly useful for
storing object state or transferring objects between applications.
4. Data Processing: Java I/O is integral to data processing tasks such as
parsing text files, processing CSV data, and interacting with databases
through JDBC (Java Database Connectivity).
Best Practices for Java I/O
When working with Java I/O, consider the following best practices:
1. Use Try-with-Resources: Always use the try-with-resources statement
when working with streams to ensure proper resource management. This
automatically closes the streams when they are no longer needed,
preventing resource leaks.
2. Use Buffered I/O: Whenever possible, use buffered I/O classes to minimize
the number of system calls and improve performance.
3. Handle Exceptions Gracefully: Handle I/O exceptions gracefully by
implementing error handling mechanisms such as logging or error
propagation.
4. Use NIO for Performance: For high-performance I/O operations, consider
using Java's NIO (New I/O) package, which provides non-blocking I/O
features and enhanced performance.
Program I/O Stream
Java I/O (Input and Output) streams are used for reading and writing data to files,
network connections, and other data sources and sinks. Java provides a comprehensive
set of classes for handling I/O operations. Understanding these streams is crucial for
effective Java programming.
Types of I/O Streams in Java
Java I/O streams can be broadly categorized into two types:
1. Byte Streams: Handle raw binary data.
2. Character Streams: Handle character data (text).
Byte Streams
Byte streams read and write data in bytes (8 bits). They are used for handling binary data
such as images, audio files, etc.
Common Byte Stream Classes
1. InputStream: The superclass for all byte input streams.
2. OutputStream: The superclass for all byte output streams.
5
Example of Byte Streams
Reading from a File using FileInputStream
import [Link];
import [Link];
public class ByteStreamExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("[Link]")) {
int data;
while ((data = [Link]()) != -1) {
[Link]((char) data);
}
} catch (IOException e) {
[Link]();
}
}
}
Writing to a File using FileOutputStream
import [Link];
import [Link];
public class ByteStreamExample {
public static void main(String[] args) {
String data = "Hello, Byte Stream!";
try (FileOutputStream fos = new FileOutputStream("[Link]")) {
[Link]([Link]());
} catch (IOException e) {
[Link]();
}
}
}
Character Streams
Character streams read and write data in characters (16 bits). They are used for handling
text data.
Common Character Stream Classes
6
1. Reader: The superclass for all character input streams.
2. Writer: The superclass for all character output streams.
Example of Character Streams
Reading from a File using FileReader
import [Link];
import [Link];
public class CharacterStreamExample {
public static void main(String[] args) {
try (FileReader fr = new FileReader("[Link]")) {
int data;
while ((data = [Link]()) != -1) {
[Link]((char) data);
}
} catch (IOException e) {
[Link]();
}
}
}
Writing to a File using FileWriter
import [Link];
import [Link];
public class CharacterStreamExample {
public static void main(String[] args) {
String data = "Hello, Character Stream!";
try (FileWriter fw = new FileWriter("[Link]")) {
[Link](data);
} catch (IOException e) {
[Link]();
}
}
}
Buffered Streams
Buffered streams are used to improve the efficiency of I/O operations by reducing the
number of read and write operations. They wrap around byte or character streams.
7
Example of Buffered Streams
Reading from a File using BufferedReader
import [Link];
import [Link];
import [Link];
public class BufferedStreamExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("[Link]"))) {
String line;
while ((line = [Link]()) != null) {
[Link](line);
}
} catch (IOException e) {
[Link]();
}
}
}
Writing to a File using BufferedWriter
import [Link];
import [Link];
import [Link];
public class BufferedStreamExample {
public static void main(String[] args) {
String data = "Hello, Buffered Stream!";
try (BufferedWriter bw = new BufferedWriter(new FileWriter("[Link]"))) {
[Link](data);
} catch (IOException e) {
[Link]();
}
}
}
Data Streams
Data streams allow you to read and write primitive data types (int, char, etc.) and strings
in a machine-independent way.
Example of Data Streams
8
Writing to a File using DataOutputStream
import [Link];
import [Link];
import [Link];
public class DataStreamExample {
public static void main(String[] args) {
try (DataOutputStream dos = new DataOutputStream(new
FileOutputStream("[Link]"))) {
[Link](123);
[Link](45.67);
[Link](true);
[Link]("Hello, Data Stream!");
} catch (IOException e) {
[Link]();
}
}
}
Reading from a File using DataInputStream
import [Link];
import [Link];
import [Link];
public class DataStreamExample {
public static void main(String[] args) {
try (DataInputStream dis = new DataInputStream(new
FileInputStream("[Link]"))) {
int intValue = [Link]();
double doubleValue = [Link]();
boolean booleanValue = [Link]();
String utfValue = [Link]();
[Link]("Integer: " + intValue);
[Link]("Double: " + doubleValue);
[Link]("Boolean: " + booleanValue);
[Link]("String: " + utfValue);
} catch (IOException e) {
[Link]();
}
9
}
}
Setting Permissions to a File in Java
In Java, the `FilePermission` class is used to manage the permissions for files and
directories. Permissions can be set to allow or deny actions such as reading, writing,
executing, or deleting files and directories.
Example: Setting File Permissions
Here’s an example that demonstrates how to set read and write permissions for a
specific file and directory:
import [Link];
import [Link];
public class FilePermissionExample {
public static void main(String[] args) {
// Define the file and directory path
String filePath = "D:\\IO Package\\[Link]";
String dirPath = "D:\\IO Package\\-";
// Create FilePermission object for directory with read permission
FilePermission dirPermission = new FilePermission(dirPath, "read");
PermissionCollection permissions = [Link]();
[Link](dirPermission);
// Create FilePermission object for file with write permission
FilePermission filePermission = new FilePermission(filePath, "write");
[Link](filePermission);
// Check if the permissions are implied
if ([Link](new FilePermission(filePath, "read,write"))) {
[Link]("Read, Write permission is granted for the path " + filePath);
} else {
[Link]("No Read, Write permission is granted for the path " +
filePath);
}
}
}
10
In this example:
- `FilePermission` objects are created for the directory and the specific file.
- Permissions are added to a `PermissionCollection`.
- The `implies` method checks if the required permissions are granted.
FilterStreams
`FilterStream` classes in Java are used to add additional functionalities to the basic I/O
streams. They act as wrappers that enhance the capabilities of existing streams by
filtering data in some way.
Example: Using FilterStreams
Here’s an example of using `BufferedOutputStream` and `BufferedInputStream`, which
are subclasses of `FilterOutputStream` and `FilterInputStream` respectively.
import [Link];
import [Link];
import [Link];
class UpperCaseInputStream extends FilterInputStream {
protected UpperCaseInputStream(InputStream in) {
super(in);
}
@Override
public int read() throws IOException {
int c = [Link]();
return (c == -1 ? c : [Link](c));
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int result = [Link](b, off, len);
for (int i = off; i < off + result; i++) {
b[i] = (byte) [Link]((char) b[i]);
}
return result;
}
}
public class IOFilterExample {
public static void main(String[] args) {
11
String data = "This is a test.";
try (InputStream in = new UpperCaseInputStream(new
FileInputStream("[Link]"))) {
int c;
while ((c = [Link]()) != -1) {
[Link]((char) c);
}
} catch (IOException e) {
[Link]();
}
}
}
What is an I/O Filter?
An I/O filter is an object that reads from one stream and writes to another, often
transforming the data in the process. Filters can be used to compress data, encrypt data,
or perform other transformations.
Example: Using an I/O Filter
Here’s an example demonstrating a custom filter that converts all characters to
uppercase:
import [Link];
import [Link];
import [Link];
class UpperCaseInputStream extends FilterInputStream {
protected UpperCaseInputStream(InputStream in) {
super(in);
}
@Override
public int read() throws IOException {
int c = [Link]();
return (c == -1 ? c : [Link](c));
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int result = [Link](b, off, len);
12
for (int i = off; i < off + result; i++) {
b[i] = (byte) [Link]((char) b[i]);
}
return result;
}
}
public class IOFilterExample {
public static void main(String[] args) {
String data = "This is a test.";
try (InputStream in = new UpperCaseInputStream(new
FileInputStream("[Link]"))) {
int c;
while ((c = [Link]()) != -1) {
[Link]((char) c);
}
} catch (IOException e) {
[Link]();
}
}
}
read Method (single byte): Overrides the read() method to convert the read byte
to uppercase.
Calls [Link]() to read a byte from the underlying input stream.
Converts the byte to uppercase using [Link].
If the end of the stream is reached ([Link]() returns -1), it returns -1.
read Method (byte array): Overrides the read(byte[] b, int off, int len) method to
convert multiple bytes to uppercase.
Calls [Link](b, off, len) to read bytes into the array.
Converts each byte in the specified range to uppercase.
Main Method:
Try-with-Resources: Ensures that the input stream is closed automatically.
Creates an UpperCaseInputStream wrapping a FileInputStream for the file
"[Link]".
13
Reading from the Stream:
Reads characters one by one using the read() method of UpperCaseInputStream.
Converts and prints each character to uppercase.
Exception Handling: Catches and prints any IOException.
Summary
The UpperCaseInputStream class extends FilterInputStream to convert all
characters read from an underlying input stream to uppercase.
It overrides the read() methods to implement this conversion.
The IOFilterExample class demonstrates how to use this custom filter to read and
convert data from a file.
Taking Input from the Console in Java
There are three main ways to take input from the console in Java: `BufferedReader`,
`Scanner`, and `Console`.
Using BufferedReader
import [Link];
import [Link];
import [Link];
public class BufferedReaderExample {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader([Link]));
[Link]("Enter your name:");
String name = [Link]();
[Link]("Hello, " + name);
}
}
Using Scanner
import [Link];
public class ScannerExample {
public static void main(String[] args) {
Scanner scanner = new Scanner([Link]);
[Link]("Enter your name:");
14
String name = [Link]();
[Link]("Hello, " + name);
}
}
Using Console
import [Link];
public class ConsoleExample {
public static void main(String[] args) {
Console console = [Link]();
if (console != null) {
[Link]("Enter your name:");
String name = [Link]();
[Link]("Hello, " + name);
} else {
[Link]("No console available");
}
}
}
15