第七课:数据读写
Java 的流、文件和 IO 是 Java 程序和外部世界交互的基础,用于处理数据的读取和写入操作。例如,从文件读取数据、将数据写入文件、控制台的输入输出等。
java.io 包为这些功能提供了丰富的支持,包括字节流、字符流、文件操作及缓冲流等工具类。
(一)核心概念
1. 流,文件和 I/O
-
流(Stream):
- 数据流是指数据传输的序列。
- 输入流:从数据源读取数据。
- 输出流:向目标写入数据。
-
文件(File):
- 提供了对文件和目录的操作支持,如创建、删除、读写等。
-
I/O(输入与输出):
java.io是处理文件和流操作的基础包,支持二进制数据(如文件、图片)、文本数据和对象序列化。
2. Java I/O 基本分类
-
字节流 (
InputStream和OutputStream):-
用于处理二进制数据。例如图像、音频、视频等。
-
主要类:
FileInputStream/FileOutputStreamBufferedInputStream/BufferedOutputStreamDataInputStream/DataOutputStream
-
-
字符流 (
Reader和Writer):-
用于处理文本数据。
-
主要类:
FileReader/FileWriterBufferedReader/BufferedWriter
-
(二)控制台输入输出
1. 控制台输入
使用 BufferedReader
需要将 System.in 包装成 BufferedReader,然后使用 read() 或 readLine() 方法读取输入。
读取单个字符
import java.io.*;
public class BRRead {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
char c;
System.out.println("输入字符,按下 'q' 键退出:");
// 逐个读取字符
do {
c = (char) br.read();
System.out.println(c);
} while (c != 'q');
}
}
执行结果:
输入字符,按下 'q' 键退出:
r
r
u
u
q
q
代码解释:
throws IOException用于声明的异常通常出现在流操作时(例如输入输出时的错误)
System.in:标准输入流,默认为控制台键盘输入。
InputStreamReader将System.in的输入数据从字节转换成字符。
BufferedReader对字符流提供缓冲功能,允许使用read()和readLine()等方法读取字符或行。
读取一整行字符串
使用 readLine() 方法读取整行的输入直到按回车为止。
import java.io.*;
public class BRReadLines {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("输入文本行,输入 'end' 退出:");
// 循环读取字符串
do {
str = br.readLine();
System.out.println(str);
} while (!str.equals("end"));
}
}
执行结果:
输入文本行,输入 'end' 退出:
Hello World
Hello World
end
end
使用 scanner 读取输入 和 使用 BufferedReader 的区别:
特性 Scanner BufferedReader 所在包 java.utiljava.io解析功能 内置数据类型解析(如 nextInt())仅支持字符串读取(需手动解析数据类型) 读取单行/多行支持 支持逐词(带分隔符)和整行读取 多用于逐行读取 读取效率 较慢,适合小数据量输入(开销较高) 高效,适合大数据量读取(缓冲读取) 线程安全性 非线程安全 非线程安全 数据分隔 自动按空格、制表符、换行分隔 不自动分隔,仅按行读取 错误处理/异常 抛出 InputMismatchException等运行时异常抛出 IOException编译时异常适用场景 小数据量的用户输入和格式化数据处理 从文件或控制台读取大量数据
2. 控制台输出
System.out 是 PrintStream 的对象引用,支持 print()、println() 和低级的字节写操作 write()。
public class WriteDemo {
public static void main(String[] args) {
int b = 'A'; // 字符 'A'
System.out.write(b); // 写入单个字符
System.out.write('\n'); // 换行
}
}
输出结果:
A
(三) 读写文件
Java 可通过操作文件流来实现文件的读写,字节流类 (FileInputStream / FileOutputStream) 和字符流类 (FileReader / FileWriter) 是主要工具。
1. 使用字节流
- 读取文件 (
FileInputStream)
用于从文件中读取数据,字节流适合处理二进制文件。
import java.io.*;
public class FileInputStreamDemo {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("test.txt");
int ch;
while ((ch = fis.read()) != -1) { // 循环读取字节。文件读完 read() 返回 -1。
System.out.print((char) ch); // 强转为字符输出
}
fis.close(); // 关闭流
} catch (IOException e) { // 处理 IOException 异常。
e.printStackTrace();
}
}
}
- 写入文件 (
FileOutputStream)
将数据以字节形式写入文件。若文件不存在,系统会自动创建。
import java.io.*;
public class FileOutputStreamDemo {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("test.txt");
String content = "Hello, world!";
fos.write(content.getBytes()); // 写入内容
fos.close(); // 关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
Java 的工作目录: Java 程序的当前工作路径。
在程序运行时,Java 默认会使用当前工作目录作为相对路径的基准。
获取当前工作目录
System.out.println("当前工作目录:" + System.getProperty("user.dir"));
中文编码问题:
默认情况下,
FileInputStream读取的是原始字节流,并没有考虑字符编码,所以如果文件包含非 ASCII 字符(如中文),会出现乱码或?。你可以使用
InputStreamReader来处理字符编码, 这是一个桥接流,用来将字节流转换成字符流。在构造时,你可以指定字符编码(如
"UTF-8"或"GBK"),这会确保字符被正确地解码。把上面的
FileOutputStream fos = new FileOutputStream("test.txt");改成
InputStreamReader fos = new InputStreamReader(new FileInputStream("test.txt"), "UTF-8");
2. 使用字符流
使用 BufferedReader 和 BufferedWriter 读写文件
import java.io.*;
public class BufferedReaderWriterExample {
public static void main(String[] args) throws IOException {
// 写入文件
BufferedWriter writer = new BufferedWriter(new FileWriter("example.txt"));
writer.write("Hello, World!");
writer.newLine(); // 换行
writer.write("This is Java IO.");
writer.close();
// 读取文件
BufferedReader reader = new BufferedReader(new FileReader("example.txt"));
String line;
while ((line = reader.readLine()) != null) { // 逐行读取
System.out.println(line);
}
reader.close();
}
}
输出结果:
Hello, World!
This is Java IO.
(四)Java 文件操作
1. 创建目录
使用 File 类的 mkdir() 和 mkdirs() 方法可以分别创建单级和多级目录。
import java.io.*;
public class CreateDirectory {
public static void main(String[] args) {
File directory = new File("demo/newdir");
boolean result = directory.mkdirs(); // 创建目录
if (result) {
System.out.println("目录已创建!");
} else {
System.out.println("目录创建失败!");
}
}
}
2. 读取目录内容
使用 File 对象的 list() 方法获取目录列表。
import java.io.*;
public class ReadDirectory {
public static void main(String[] args) {
File directory = new File("/tmp");
if (directory.isDirectory()) {
String[] files = directory.list();
for (String file : files) {
System.out.println(file);
}
} else {
System.out.println("不是一个目录!");
}
}
}
3. 删除目录或文件
使用 File.delete() 方法删除文件或空目录。
import java.io.*;
public class DeleteFile {
public static void main(String[] args) {
File file = new File("demo/test.txt");
if (file.delete()) {
System.out.println("文件已删除!");
} else {
System.out.println("文件删除失败!");
}
}
}
对于非空目录,需要递归删除。