Java Streams, Files, and I/O
The java.io
package includes almost all the classes needed for input and output operations. All these stream classes represent input sources and output destinations.
Streams in the java.io
package support many data formats, such as basic types, objects, localized character sets, etc.
A stream can be understood as a sequence of data. An input stream represents reading data from a source, and an output stream represents writing data to a destination.
Java provides robust and flexible support for I/O, making it widely applicable in file transfer and network programming.
This section covers the most basic functionalities related to streams and I/O. We will learn these functionalities through examples.
Reading Console Input
Java console input is accomplished through System.in
.
To obtain a character stream bound to the console, you can wrap System.in
in a BufferedReader
object to create a character stream.
Here is the basic syntax for creating a BufferedReader
:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
After creating the BufferedReader
object, we can use the read()
method to read a single character from the console, or the readLine()
method to read a string.
Reading Multi-Character Input from the Console
To read a character from a BufferedReader
object, use the read()
method, which has the following syntax:
int read() throws IOException
Each call to the read()
method reads a character from the input stream and returns it as an integer value. It returns -1 when the end of the stream is reached. This method throws an IOException
.
The following program demonstrates reading characters from the console continuously until the user inputs 'q'.
BRRead.java File Code:
// Reading characters from the console using BufferedReader
import java.io.*;
public class BRRead {
public static void main(String[] args) throws IOException {
char c;
// Creating BufferedReader using System.in
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter characters, press 'q' to quit.");
// Reading characters
do {
c = (char) br.read();
System.out.println(c);
} while (c != 'q');
}
}
The above example compiles and runs with the following result:
Enter characters, press 'q' to quit.
tutorialpro
r
u
n
o
o
b
q
q
Reading Strings from the Console
To read a string from standard input, use the readLine()
method of BufferedReader
.
Its general format is:
String readLine() throws IOException
The following program reads and displays lines of characters until you input the word "end".
BRReadLines.java File Code:
// Reading lines of text from the console using BufferedReader
import java.io.*;
public class BRReadLines {
public static void main(String[] args) throws IOException {
// Creating BufferedReader using System.in
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("Enter lines of text.");
System.out.println("Enter 'end' to quit.");
do {
str = br.readLine();
System.out.println(str);
} while (!str.equals("end"));
}
}
The above example compiles and runs with the following result:
Enter lines of text.
English:
Enter 'end' to quit.
This is line one
This is line one
This is line two
This is line two
end
end
After JDK 5, we can also use the [Java Scanner](java-scanner-class.html) class to get input from the console.
## Console Output
As previously mentioned, console output is accomplished with print() and println(). These methods are defined by the PrintStream class, and System.out is a reference to an object of this class.
PrintStream inherits from the OutputStream class and implements the write() method. Thus, write() can also be used for writing to the console.
The simplest form of the write() method defined by PrintStream is as follows:
void write(int byteval)
This method writes the lower eight bits of the byteval to the stream.
### Example
The following example uses write() to output the character "A" and a newline to the screen:
## WriteDemo.java File Code:
import java.io.*;
// Demonstrates System.out.write(). public class WriteDemo { public static void main(String[] args) { int b; b = 'A'; System.out.write(b); System.out.write('\n'); } }
Running the above example outputs the character "A" in the console window:
A
**Note:** The write() method is not commonly used because print() and println() are more convenient.
---
## Reading and Writing Files
As mentioned earlier, a stream is defined as a sequence of data. An input stream is used to read data from a source, and an output stream is used to write data to a destination.
The following diagram illustrates the class hierarchy for input and output streams.
[Image of Input and Output Stream Hierarchy]
The two important streams discussed next are **FileInputStream** and **FileOutputStream**.
---
## FileInputStream
This stream is used to read data from files. Its objects can be created using the new keyword.
There are several constructor methods available to create objects.
You can create an input stream object using a file name to read the file:
InputStream f = new FileInputStream("C:/java/hello");
You can also create an input stream object using a file object. First, create a file object using the File() method:
File f = new File("C:/java/hello"); InputStream in = new FileInputStream(f);
Once you have created an InputStream object, you can use the following methods to read the stream or perform other stream operations.
| No. | Method and Description |
| --- | --- |
| 1 | public void close() throws IOException{} <br> Closes this file input stream and releases any system resources associated with this stream. Throws an IOException. |
| 2 | protected void finalize() throws IOException {} <br> This method clears the connection to the file. Ensures that the close method of this file input stream is called when there are no more references to it. Throws an IOException. |
| 3 | public int read(int r) throws IOException{} <br> This method reads the specified byte of data from the InputStream object. Returns an integer. Returns the next byte of data, or -1 if the end of the file is reached. |
| 4 | public int read(byte[] r) throws IOException{} <br> This method reads r.length bytes from the input stream. Returns the number of bytes read. Returns -1 if the end of the file is reached. |
| 5 | public int available() throws IOException{} <br> Returns the number of bytes that can be read from this input stream without blocking. Returns an integer. |
In addition to InputStream, there are other input streams. For more details, refer to the following links:
- [ByteArrayInputStream](java-bytearrayinputstream.html)
## FileOutputStream
This class is used to create a file and write data to it.
If the target file does not exist before the stream is opened for output, the stream will create the file.
There are two constructors that can be used to create a FileOutputStream object.
Using a string type file name to create an output stream object:
OutputStream f = new FileOutputStream("C:/java/hello")
Alternatively, you can use a file object to create an output stream to write to the file. We first need to create a file object using the File() method:
File f = new File("C:/java/hello"); OutputStream fOut = new FileOutputStream(f);
Once the OutputStream object is created, you can use the following methods to write to the stream or perform other stream operations.
| No. | Method and Description |
| --- | --- |
| 1 | public void close() throws IOException{} <br> Closes this file input stream and releases any system resources associated with this stream. Throws IOException. |
| 2 | protected void finalize() throws IOException {} <br> This method clears the connection to the file. Ensures that the close method is called when there are no more references to the file input stream. Throws IOException. |
| 3 | public void write(int w) throws IOException{} <br> This method writes the specified byte to the output stream. |
| 4 | public void write(byte[] w) <br> Writes the bytes of length w.length from the specified byte array to the OutputStream. |
In addition to OutputStream, there are other output streams. For more details, refer to the following links:
- [ByteArrayOutputStream](java-bytearrayoutputstream.html)
- [DataOutputStream](java-dataoutputstream.html)
### Example
Below is an example demonstrating the usage of InputStream and OutputStream:
## fileStreamTest.java File Code:
import java.io.*;
public class fileStreamTest { public static void main(String[] args) { try { byte bWrite[] = { 11, 21, 3, 40, 5 }; OutputStream os = new FileOutputStream("test.txt"); for (int x = 0; x < bWrite.length; x++) { os.write(bWrite[x]); // writes the bytes } os.close();
InputStream is = new FileInputStream("test.txt");
int size = is.available();
for (int i = 0; i < size; i++) {
System.out.print((char) is.read() + " ");
}
is.close();
} catch (IOException e) {
System.out.print("Exception");
}
}
}
The above program first creates the file test.txt and writes the given numbers in binary form to the file, also outputting them to the console.
The above code may result in garbled characters due to binary writing. You can use the following code example to resolve the garbled character issue:
## fileStreamTest2.java File Code:
// File name : fileStreamTest2.java import java.io.*;
public class fileStreamTest2 { public static void main(String[] args) throws IOException {
```java
File f = new File("a.txt");
FileOutputStream fop = new FileOutputStream(f);
// Constructs a FileOutputStream object; the file will be automatically created if it does not exist
OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8");
// Constructs an OutputStreamWriter object with the specified encoding; defaults to the operating system's default encoding, which is GBK on Windows
writer.append("中文输入");
// Writes to the buffer
writer.append("\r\n");
// Adds a newline
writer.append("English");
// Flushes the buffer and writes to the file; if there is no more content to write, closing the stream will also flush the buffer
writer.close();
// Closes the writer stream, which also writes the buffer content to the file, so the previous comment is redundant
fop.close();
// Closes the output stream, releasing system resources
FileInputStream fip = new FileInputStream(f);
// Constructs a FileInputStream object
InputStreamReader reader = new InputStreamReader(fip, "UTF-8");
// Constructs an InputStreamReader object with the same encoding as used for writing
StringBuffer sb = new StringBuffer();
while (reader.ready()) {
sb.append((char) reader.read());
// Converts to char and appends to the StringBuffer object
}
System.out.println(sb.toString());
reader.close();
// Closes the reader stream
fip.close();
// Closes the input stream, releasing system resources
Files and I/O
There are several classes related to files and I/O that we need to be aware of:
Directories in Java
Creating a Directory:
The File class has two methods for creating directories:
- mkdir() method creates a single directory. It returns true if successful, or false if the directory already exists or the path does not exist.
- mkdirs() method creates both a directory and all its parent directories.
The following example creates the directory "/tmp/user/java/bin":
CreateDir.java File Code:
import java.io.File;
public class CreateDir {
public static void main(String[] args) {
String dirname = "/tmp/user/java/bin";
File d = new File(dirname);
// Now create the directory
d.mkdirs();
}
}
Compile and execute the above code to create the directory "/tmp/user/java/bin".
Note: Java automatically recognizes file path separators in UNIX and Windows. If you use the separator (/) in a Windows version of Java, the path will still be correctly parsed.
Reading a Directory
A directory is a File object that contains other files and folders.
If a File object is a directory, the isDirectory() method returns true.
You can extract the list of files and folders it contains by calling the list() method on the object.
The following example demonstrates how to use the list() method to check the contents of a folder:
DirList.java File Code:
import java.io.File;
public class DirList {
public static void main(String args[]) {
String dirname = "/tmp";
File f1 = new File(dirname);
if (f1.isDirectory()) {
System.out.println("Directory of " + dirname);
String s[] = f1.list();
for (int i = 0; i < s.length; i++) {
File f = new File(dirname + "/" + s[i]);
if (f.isDirectory()) {
System.out.println(s[i] + " is a directory");
} else {
System.out.println(s[i] + " is a file");
}
}
} else {
System.out.println(dirname + " is not a directory");
}
}
}
public class DirList {
public static void main(String args[]) {
String dirname = "/tmp";
File f1 = new File(dirname);
if (f1.isDirectory()) {
System.out.println("Directory " + dirname);
String s[] = f1.list();
for (int i = 0; i < s.length; i++) {
File f = new File(dirname + "/" + s[i]);
if (f.isDirectory()) {
System.out.println(s[i] + " is a directory");
} else {
System.out.println(s[i] + " is a file");
}
}
} else {
System.out.println(dirname + " is not a directory");
}
}
}
The above example compiles and runs with the following output:
Directory /tmp
bin is a directory
lib is a directory
demo is a directory
test.txt is a file
README is a file
index.html is a file
include is a directory
Deleting Directories or Files
Files can be deleted using the java.io.File.delete() method.
The following code deletes the directory /tmp/java/. It's important to note that a directory must be empty to be successfully deleted; otherwise, the deletion will fail.
Test directory structure:
/tmp/java/
|-- 1.log
|-- test
DeleteFileDemo.java File Code:
import java.io.File;
public class DeleteFileDemo {
public static void main(String[] args) {
// Modify this to your test directory
File folder = new File("/tmp/java/");
deleteFolder(folder);
}
// Delete files and directories
public static void deleteFolder(File folder) {
File[] files = folder.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
deleteFolder(f);
} else {
f.delete();
}
}
}
folder.delete();
}
}