Understanding Input and Output Streams
Java IO operations revolve around moving data between a program and external sources (like files or networks).
- Input (Reading): Reading data from a source (e.g., a file on disk) into the Java application as a stream.
- Output (Writing): Sending data from the Java application out to a destination (e.g., saving to a disk file).
In the context of file transfer:
- Uploading involves using an Input Stream to bring local data into the program.
- Downloading involves using an Output Stream to send program data to the local system.
The File Class
The java.io.File class represents file and directory pathnames in an abstract manner. Each instance corresponds to a specific file or folder on the filesystem.
| Method Signature | Description |
|---|---|
File(String pathname) |
Creates a new File instance by converting the given pathname string into an abstract pathname. |
String getName() |
Returns the name of the file or directory denoted by this abstract pathname. |
String getParent() |
Returns the pathname string of this abstract pathname's parent, or null if this pathname does not name a parent directory. |
String getPath() |
Converts this abstract pathname into a pathname string. |
boolean exists() |
Tests whether the file or directory denoted by this abstract pathname exists. |
boolean isDirectory() |
Tests whether the file denoted by this abstract pathname is a directory. |
boolean isFile() |
Tests whether the file denoted by this abstract pathname is a normal file. |
long length() |
Returns the length of the file denoted by this abstract pathname. |
boolean createNewFile() |
Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist. |
boolean delete() |
Deletes the file or directory denoted by this abstract pathname. |
boolean mkdir() |
Creates the directory named by this abstract pathname. |
boolean renameTo(File dest) |
Renames the file denoted by this abstract pathname. |
File Operation Example
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) {
// Example: Checking file properties
// File source = new File("D:/java/123.png");
// if (source.exists()) {
// System.out.println("Parent: " + source.getParent());
// System.out.println("Path: " + source.getPath());
// System.out.println("Name: " + source.getName());
// System.out.println("Is Directory: " + source.isDirectory());
// System.out.println("Is File: " + source.isFile());
// System.out.println("Size: " + source.length() + " bytes");
// }
// Example: Renaming a file
File oldFile = new File("D:/java/789.png");
File renamedFile = new File("D:/java/78910.png");
if (oldFile.exists()) {
System.out.println("Rename successful: " + oldFile.renameTo(renamedFile));
}
// Example: Creating a new file or directory
// try {
// File newFile = new File("D:/java/newFile.txt");
// System.out.println("File created: " + newFile.createNewFile());
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
Stream Classifications
IO streams are categorized based on two factors:
- Direction: Input Stream (reading data) vs. Output Stream (writing data).
- Data Unit: Byte Stream (handles raw bytes) vs. Character Stream (handles Unicode characters).
Byte Streams: InputStream
InputStream is the superclass of all classes representing an input stream of bytes.
| Method | Description |
|---|---|
int read() |
Reads the next byte of data from the input stream. |
int read(byte[] b) |
Reads some number of bytes from the input stream and stores them into the buffer array b. |
int read(byte[] b, int off, int len) |
Reads up to len bytes of data from the input stream into an array of bytes, starting at offset off. |
int available() |
Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream. |
void close() |
Closes this input stream and releases any system resources associated with the stream. |
Note on Encoding: In standard Java streams, English characters, digits, and punctuation usually ocupy 1 byte, while Chinese characters may occupy 3 bytes (depending on the encoding, e.g., UTF-8).
Reading Bytes (Single Byte)
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
public class ByteReaderDemo {
public static void main(String[] args) {
File imgFile = new File("D:\\java\\123.png");
if (!imgFile.exists()) {
System.out.println(imgFile.getName() + " not found.");
return;
}
try (InputStream is = new FileInputStream(imgFile)) {
int byteData;
while ((byteData = is.read()) != -1) {
// Processing raw byte data (e.g., printing integer value)
System.out.println(byteData);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Reading Bytes into a Buffer
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
public class BufferReadDemo {
public static void main(String[] args) {
File textFile = new File("D:\\java\\test2.txt");
if (!textFile.exists()) {
System.out.println(textFile.getName() + " not found.");
return;
}
try (InputStream is = new FileInputStream(textFile)) {
byte[] buffer = new byte[1024];
int bytesRead = is.read(buffer);
System.out.println("Bytes read: " + bytesRead);
for (int i = 0; i < bytesRead; i++) {
System.out.println(buffer[i]);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Reading with Offset
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
public class OffsetReadDemo {
public static void main(String[] args) {
File textFile = new File("D:\\java\\test2.txt");
if (!textFile.exists()) {
System.out.println(textFile.getName() + " not found.");
return;
}
try (InputStream is = new FileInputStream(textFile)) {
byte[] buffer = new byte[1024];
// Read 4 bytes starting at offset 3 in the array
int bytesRead = is.read(buffer, 3, 4);
System.out.println("Bytes read: " + bytesRead);
for (byte b : buffer) {
System.out.println(b);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Checking Available Bytes
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
public class AvailableDemo {
public static void main(String[] args) {
File textFile = new File("D:\\java\\test2.txt");
if (!textFile.exists()) {
System.out.println(textFile.getName() + " not found.");
return;
}
try (InputStream is = new FileInputStream(textFile)) {
int byteData;
System.out.println("Initial available: " + is.available());
while ((byteData = is.read()) != -1) {
System.out.println("Data: " + byteData + ", Remaining: " + is.available());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Byte Streams: OutputStream
OutputStream is the superclass of all classes representing an output stream of bytes.
| Method | Description |
|---|---|
void write(int b) |
Writes the specified byte to this output stream. |
void write(byte[] b) |
Writes b.length bytes from the specified byte array to this output stream. |
void write(byte[] b, int off, int len) |
Writes len bytes from the specified byte array starting at offset off to this output stream. |
void close() |
Closes this output stream and releases any system resources associated with the stream. |
Writing Bytes to a File
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.IOException;
public class ByteWriterDemo {
public static void main(String[] args) {
File outFile = new File("D:\\java\\output.txt");
try (OutputStream os = new FileOutputStream(outFile)) {
// Write a single byte (ASCII for 'C')
os.write(67);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Writing a Byte Array
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.IOException;
public class ArrayWriterDemo {
public static void main(String[] args) {
File outFile = new File("D:\\java\\output.txt");
// Byte values for 'C', 'a', 't', 'B', 'X', 'c', 'd'
byte[] data = {67, 97, 116, 66, 88, 99, 100};
try (OutputStream os = new FileOutputStream(outFile)) {
os.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Writing Partial Byte Array
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.IOException;
public class PartialWriterDemo {
public static void main(String[] args) {
File outFile = new File("D:\\java\\output.txt");
byte[] data = {67, 97, 116, 66, 88, 99, 100};
try (OutputStream os = new FileOutputStream(outFile)) {
// Write 3 bytes starting from index 3 ('B', 'X', 'c')
os.write(data, 3, 3);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Character Streams vs. Byte Streams
The primary difference is the unit of data:
- Byte Streams: Handle raw 8-bit bytes. Ideal for binary data (images, audio, class files).
- Character Streams: Handle 16-bit Unicode characters. Ideal for text data.
Character Streams: Reader
Reader is the abstract class for reading character streams.
| Method | Description |
|---|---|
int read() |
Reads a single character. |
int read(char[] cbuf) |
Reads characters into an array. |
int read(char[] cbuf, int off, int len) |
Reads characters into a portion of an array. |
void close() |
Closes the stream and releases any system resources asssociated with it. |
Reading Characters
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.io.IOException;
public class CharReaderDemo {
public static void main(String[] args) {
File textFile = new File("D:\\java\\test2.txt");
if (!textFile.exists()) {
System.out.println(textFile.getName() + " not found.");
return;
}
try (Reader reader = new FileReader(textFile)) {
int charData;
while ((charData = reader.read()) != -1) {
System.out.println(charData); // Prints Unicode value
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Reading Characters into Array with Offset
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.io.IOException;
public class CharArrayDemo {
public static void main(String[] args) {
File textFile = new File("D:\\java\\test2.txt");
if (!textFile.exists()) {
System.out.println(textFile.getName() + " not found.");
return;
}
try (Reader reader = new FileReader(textFile)) {
char[] charBuffer = new char[1024];
int charsRead = reader.read(charBuffer, 3, 1);
System.out.println("Characters read: " + charsRead);
for (char c : charBuffer) {
System.out.println(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Character Streams: Writer
Writer is the abstract class for writing to character streams.
| Method | Description |
|---|---|
void write(int c) |
Writes a single character. |
void write(char[] cbuf) |
Writes an array of characters. |
void write(char[] cbuf, int off, int len) |
Writes a portion of an array of characters. |
void write(String str) |
Writes a string. |
void write(String str, int off, int len) |
Writes a portion of a string. |
void close() |
Closes the stream, flushing it first. |
Writing Characters and Strings
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.io.IOException;
public class CharWriterDemo {
public static void main(String[] args) {
File outFile = new File("D:\\java\\output.txt");
char[] greetings = {'你', '好', '世', '界'};
String message = "我爱写代码";
try (Writer writer = new FileWriter(outFile)) {
// Write a portion of the string starting at index 2 ("写代码")
writer.write(message, 2, 3);
} catch (IOException e) {
e.printStackTrace();
}
}
}
File Copying Operations
Copying files involves reading from a source and writing to a destination.
Copying Text using Character Streams
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
import java.io.IOException;
public class TextCopyDemo {
public static void main(String[] args) {
File source = new File("D:\\java\\source.txt");
File dest = new File("D:\\java\\dest.txt");
try (Reader reader = new FileReader(source);
Writer writer = new FileWriter(dest)) {
int charData;
while ((charData = reader.read()) != -1) {
writer.write(charData);
}
System.out.println("Text file copied successfully.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Copying Files using Byte Streams (Universal)
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
public class BinaryCopyDemo {
public static void main(String[] args) {
File source = new File("D:\\java\\source.png");
File dest = new File("D:\\java\\dest.png");
try (InputStream is = new FileInputStream(source);
OutputStream os = new FileOutputStream(dest)) {
int byteData;
while ((byteData = is.read()) != -1) {
os.write(byteData);
}
System.out.println("File copied successfully.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Important Note: Use Byte Streams for copying non-text files (like images, PDFs, executables). Character streams may corrupt binary data. For text files, both stream types work, but Character streams are often preferred for proper encoding handling.