简单了解Java的I/O流机制与文件读写操作
一、理解Java的I/O流机制
字节流
Java中的字节流主要由 InputStream
和 OutputStream
这两个抽象类及其子类构成。字节流以字节(byte)为基本处理单元,适用于处理所有类型的数据,包括文本、图片、音频、视频等。
1. InputStream
InputStream
是所有字节输入流的父类。常见的子类有 FileInputStream
(用于从文件中读取字节数据)、ByteArrayInputStream
(从字节数组中读取数据)等。以 FileInputStream
为例,以下是从文件中读取字节数据的简单代码:
import java.io.FileInputStream;
import java.io.IOException;public class FileInputStreamExample {public static void main(String[] args) {try (FileInputStream fis = new FileInputStream("test.txt")) {int data;while ((data = fis.read()) != -1) {System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();}}
}
在这段代码中,fis.read()
方法每次读取一个字节的数据,返回值为读取到的字节值,当读取到文件末尾时返回 -1 。
2. OutputStream
OutputStream
是所有字节输出流的父类。常见子类有 FileOutputStream
(用于向文件中写入字节数据)、ByteArrayOutputStream
(将数据写入字节数组)等。以下是使用 FileOutputStream
向文件写入字节数据的代码:
import java.io.FileOutputStream;
import java.io.IOException;public class FileOutputStreamExample {public static void main(String[] args) {String message = "Hello, Java I/O!";try (FileOutputStream fos = new FileOutputStream("output.txt")) {fos.write(message.getBytes());} catch (IOException e) {e.printStackTrace();}}
}
这里先将字符串转换为字节数组,然后通过 fos.write()
方法将字节数组写入到指定文件中。
字符流
字符流基于字节流构建,以字符(char)为基本处理单元,更适合处理文本数据。字符流由 Reader
和 Writer
这两个抽象类及其子类组成。
1. Reader
Reader
是所有字符输入流的父类。常见子类有 FileReader
(用于从文件中读取字符数据)、BufferedReader
(带有缓冲功能的字符输入流,能提高读取效率)等。使用 BufferedReader
逐行读取文件内容的代码如下:
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("test.txt"))) {String line;while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}}
}
br.readLine()
方法会读取文件中的一行内容并返回,当读取到文件末尾时返回 null
。
2. Writer
Writer
是所有字符输出流的父类。常见子类有 FileWriter
(用于向文件中写入字符数据)、BufferedWriter
(带有缓冲功能的字符输出流,能提高写入效率)等。下面是使用 BufferedWriter
向文件写入字符数据的代码:
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("output.txt"))) {bw.write("This is a line written by BufferedWriter.");bw.newLine();bw.write("Another line.");} catch (IOException e) {e.printStackTrace();}}
}
bw.write()
方法用于写入字符数据,bw.newLine()
方法用于写入换行符。
二、熟悉文件的读写操作
文件读取操作
- 按字节读取:使用
FileInputStream
逐字节读取文件,适用于读取二进制文件或对读取精度要求高的场景。但对于大文件,频繁的单个字节读取效率较低。 - 按字符读取:采用
FileReader
结合BufferedReader
逐行读取文本文件是很常见的方式。它能有效提高读取文本文件的效率,尤其适合处理大文本文件。 - 随机读取:如果需要在文件的不同位置进行跳跃式读取,可以使用
RandomAccessFile
类。它既可以读取也可以写入,并且支持文件指针的随机移动。例如:
import java.io.IOException;
import java.io.RandomAccessFile;public class RandomAccessFileExample {public static void main(String[] args) {try (RandomAccessFile raf = new RandomAccessFile("test.txt", "r")) {raf.seek(5); // 将文件指针移动到第5个字节位置int data;while ((data = raf.read()) != -1) {System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();}}
}
文件写入操作
- 覆盖写入:使用
FileOutputStream
或FileWriter
时,如果文件已存在,默认会覆盖原文件内容。如前文示例中,FileOutputStream fos = new FileOutputStream("output.txt")
就是这种情况。 - 追加写入:如果希望在文件末尾追加内容,可以在创建
FileOutputStream
或FileWriter
时传入第二个参数true
。例如:
import java.io.FileWriter;
import java.io.IOException;public class AppendWriteExample {public static void main(String[] args) {try (FileWriter fw = new FileWriter("output.txt", true)) {fw.write("This is appended content.");} catch (IOException e) {e.printStackTrace();}}
}
三、总结
在使用这些流的时候,要记住一点,我们是为电脑编写程序,这里的Input是指输入到电脑中,reader是指读到电脑中。一开始的时候,总是搞混这些,用久了就清楚了。