顺序读取文件
在 Java 中,如果主要是顺序访问文件,可以使用 FileInputStream
、FileOutputStream
、FileReader
和 FileWriter
等类。它们主要用于顺序读写文件,不支持直接的随机访问,适合逐行或逐字节顺序读取或写入文件的场景。
1. FileInputStream
和 FileOutputStream
FileInputStream
和 FileOutputStream
是基于字节流的类,适合处理二进制文件(如图片、视频、音频等),也可以用于文本文件。
FileInputStream
用法
用于从文件中逐字节读取数据:
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("example.txt")) {
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content); // 输出内容
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileOutputStream
用法
用于向文件中逐字节写入数据:
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamExample {
public static void main(String[] args) {
String data = "Hello, FileOutputStream!";
try (FileOutputStream fos = new FileOutputStream("example.txt")) {
fos.write(data.getBytes()); // 将字符串写入文件
} catch (IOException e) {
e.printStackTrace();
}
}
}
2. FileReader
和 FileWriter
FileReader
和 FileWriter
是基于字符流的类,专门用于处理文本文件,更适合读取和写入字符数据。
FileReader
用法
用于从文件中逐字符读取数据:
import java.io.FileReader;
import java.io.IOException;
public class FileReaderExample {
public static void main(String[] args) {
try (FileReader fr = new FileReader("example.txt")) {
int content;
while ((content = fr.read()) != -1) {
System.out.print((char) content); // 输出内容
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileWriter
用法
用于向文件中逐字符写入数据:
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterExample {
public static void main(String[] args) {
String data = "Hello, FileWriter!";
try (FileWriter fw = new FileWriter("example.txt")) {
fw.write(data); // 将字符串写入文件
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. 缓冲流:BufferedReader
和 BufferedWriter
BufferedReader
和 BufferedWriter
提供了带缓冲区的字符流类,更适合逐行读取和写入文本文件。可以提高 I/O 操作的效率,尤其是在读取大文件时。
BufferedReader
用法
BufferedReader
提供了 readLine()
方法,可以按行读取文件内容:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line); // 输出每行内容
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedWriter
用法
BufferedWriter
提供了 newLine()
方法,可以方便地逐行写入内容:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterExample {
public static void main(String[] args) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter("example.txt"))) {
bw.write("Hello, BufferedWriter!");
bw.newLine(); // 写入一个新行
bw.write("This is another line.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
4. 选择合适的类
- 处理二进制文件(如图片、音频、视频):
FileInputStream
和FileOutputStream
。 - 处理文本文件的逐字符读写:
FileReader
和FileWriter
。 - 处理文本文件的逐行读写,提高效率:
BufferedReader
和BufferedWriter
。
这类顺序访问类适合大多数需要顺序读写文件的场景,如果需要随机访问,则可以考虑 RandomAccessFile
。
随机读取文件
RandomAccessFile
是 Java 中用于文件的读写操作的类,它允许在文件中读取和写入的同时,可以随意移动文件指针,从而在文件的任意位置进行操作。它支持随机访问,因此在需要频繁地访问文件的不同位置时非常有用。
1. 构造方法
RandomAccessFile
有两个主要构造方法:
RandomAccessFile(String file, String mode)
RandomAccessFile(File file, String mode)
其中,file
是文件路径或 File
对象,mode
是打开文件的模式,常见的模式有:
"r"
:只读模式,文件必须存在。"rw"
:读写模式,文件可以不存在,不存在时会自动创建。
2. 常用方法
打开文件
RandomAccessFile raf = new RandomAccessFile("example.txt", "rw");
写入数据
raf.writeInt(100); // 写入一个整数
raf.writeUTF("Hello"); // 写入一个UTF字符串
raf.writeBoolean(true); // 写入布尔值
读取数据
在读取数据时需要注意数据类型的顺序与写入时一致。
raf.seek(0); // 移动文件指针到开头
int number = raf.readInt();
String text = raf.readUTF();
boolean flag = raf.readBoolean();
随机访问
通过 seek(long pos)
方法可以将文件指针移动到文件的任意位置。pos
是文件中的字节偏移量,从 0 开始。
raf.seek(8); // 移动文件指针到第 8 个字节位置
获取文件长度
long length = raf.length();
设置文件长度
可以通过 setLength(long newLength)
来设置文件长度。如果新长度小于当前文件长度,会截断文件。
raf.setLength(100); // 设置文件长度为 100 字节
获取文件指针位置
long pos = raf.getFilePointer();
关闭文件
使用完成后应关闭文件,以释放资源。
raf.close();
3. 示例代码
以下是一个简单示例,演示如何使用 RandomAccessFile
进行写入、读取和随机访问。
import java.io.*;
public class RandomAccessFileExample {
public static void main(String[] args) {
try (RandomAccessFile raf = new RandomAccessFile("example.txt", "rw")) {
// 写入数据
raf.writeInt(123);
raf.writeUTF("Hello World");
raf.writeBoolean(true);
// 读取数据
raf.seek(0); // 将指针移动到文件开头
int num = raf.readInt();
String str = raf.readUTF();
boolean bool = raf.readBoolean();
System.out.println("Integer: " + num);
System.out.println("String: " + str);
System.out.println("Boolean: " + bool);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4. 注意事项
- 使用
RandomAccessFile
时,请确保文件读写的顺序和数据格式一致。 - 读写文件需要捕获
IOException
异常。 RandomAccessFile
适用于文件的随机读写,而不是大量的数据追加操作。
这样就可以在 Java 中实现文件的随机访问,适合一些需要频繁对文件的某个位置进行读写的场景,比如简单的数据库实现。
在 Java 中,I/O 类主要可以分为 字节流 和 字符流 两大类。字节流用于处理所有类型的文件(文本或二进制文件),而字符流专门用于处理文本数据。
1. 字节流
字节流的基本单位是 字节(8 位),因此它适合处理所有类型的数据,包括图片、音频、视频等。Java 提供了两组字节流类:输入字节流和输出字节流,分别从文件中读取或向文件中写入字节数据。
字节流的两大基类
InputStream
:字节输入流的基类,用于从文件或其他数据源读取字节数据。OutputStream
:字节输出流的基类,用于将字节数据写入文件或其他输出目标。
常用字节流类
类名 | 描述 |
---|---|
FileInputStream | 从文件中按字节读取数据 |
FileOutputStream | 向文件中按字节写入数据 |
BufferedInputStream | 提供带缓冲区的字节输入流,提高读取效率 |
BufferedOutputStream | 提供带缓冲区的字节输出流,提高写入效率 |
DataInputStream | 包装在其他字节流上,按基本数据类型读取字节数据 |
DataOutputStream | 包装在其他字节流上,按基本数据类型写入字节数据 |
ByteArrayInputStream | 从字节数组中读取数据,适用于内存中的字节数据 |
ByteArrayOutputStream | 写入字节数据到字节数组 |
字节流的使用示例
// 使用 FileInputStream 读取文件
try (FileInputStream fis = new FileInputStream("example.bin")) {
int byteData;
while ((byteData = fis.read()) != -1) {
System.out.print(byteData + " ");
}
} catch (IOException e) {
e.printStackTrace();
}
2. 字符流
字符流的基本单位是 字符(16 位),因此它更适合处理文本数据,因为字符流能够正确处理 Unicode 字符。Java 中字符流的核心是将字节流按字符编码进行解码,并提供按字符操作数据的方法。
字符流的两大基类
Reader
:字符输入流的基类,用于从文件或其他数据源读取字符数据。Writer
:字符输出流的基类,用于将字符数据写入文件或其他输出目标。
常用字符流类
类名 | 描述 |
---|---|
FileReader | 从文件中按字符读取数据 |
FileWriter | 向文件中按字符写入数据 |
BufferedReader | 提供带缓冲区的字符输入流,支持按行读取 |
BufferedWriter | 提供带缓冲区的字符输出流,支持按行写入 |
InputStreamReader | 将字节流转为字符流,通常用于指定字符编码 |
OutputStreamWriter | 将字符流转为字节流,通常用于指定字符编码 |
StringReader | 从字符串中读取字符数据,适用于内存中的字符数据 |
StringWriter | 写入字符数据到字符串 |
字符流的使用示例
// 使用 FileReader 和 BufferedReader 读取文本文件
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
字节流和字符流的区别
特性 | 字节流 | 字符流 |
---|---|---|
基本单位 | 字节(8 位) | 字符(16 位) |
适用场景 | 二进制数据和文本数据 | 仅文本数据 |
基类 | InputStream / OutputStream | Reader / Writer |
缓冲类 | BufferedInputStream / BufferedOutputStream | BufferedReader / BufferedWriter |
编码支持 | 不处理字符编码 | 支持字符编码,通常为 UTF-8 等 |
字节流与字符流的转换
可以通过 InputStreamReader
和 OutputStreamWriter
将字节流与字符流相互转换,以便处理带有编码的文本数据。例如从字节流读取文件并按 UTF-8 编码解码为字符流:
try (InputStreamReader isr = new InputStreamReader(new FileInputStream("example.txt"), "UTF-8");
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
在实际开发中,选择字节流或字符流取决于文件数据的类型以及是否需要处理编码。
输入流链接:DataInputStream -> BufferedInputStream -> DataInputStream
输出流链接:DataOutputStream -> BufferedOutputStream -> FileOutputStream