Java-IO-小记
字数 2241 2025-08-11 21:26:21
Java I/O 流详解
一、概述
I/O(input/output)流是Java中用于输入输出的核心机制,定义在java.io包中。I/O流可以分为以下几类:
-
按数据单位分类:
- 字节流:以字节为单位
- 字符流:以字符为单位
-
按传输方向分类:
- 输入流
- 输出流
-
按功能分类:
- 节点流(低级流):直接连接数据源进行读写
- 处理流(高级流):对已存在的节点流进行封装
Java I/O中有四个顶级类:
- 字节流:
InputStream、OutputStream - 字符流:
Reader、Writer
二、字节流
1. FileInputStream和FileOutputStream
import java.io.*;
public class StreamTest {
public static void main(String[] args) throws Exception {
// 读取文件内容
FileInputStream file_in = new FileInputStream("test.txt");
int b = 0;
while ((b = file_in.read()) != -1) {
System.out.println(b); // 输出ASCII码
System.out.println((char)b); // 转字符输出
}
file_in.close();
// 写出文件
FileOutputStream file_out = new FileOutputStream("test2.txt");
String str1 = "hello world";
file_out.write(str1.getBytes());
file_out.close();
// 文件复制
FileInputStream copy_in = new FileInputStream("test.txt");
FileOutputStream copy_out = new FileOutputStream("testCOPY2.txt");
copy_out.write(copy_in.readAllBytes());
}
}
read()方法有三种形式:
read():每次读一个字节read(byte[] bs):读取多个字节到字节数组read(byte[] bs, int offset, int len):跳过offset个字节读取len个字节
2. BufferedInputStream和BufferedOutputStream
字节缓冲流,内部自带8192字节的缓冲区。
import java.io.*;
public class StreamTest {
public static void main(String[] args) throws Exception {
BufferedInputStream buffer_in = new BufferedInputStream(
new FileInputStream("test.txt"));
BufferedOutputStream buffer_out = new BufferedOutputStream(
new FileOutputStream("bufferOUT.txt"));
buffer_out.write(buffer_in.readAllBytes());
buffer_in.close();
buffer_out.close();
}
}
三、字符流
1. Reader
import java.io.*;
public class StreamTest {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("test.txt");
int len1 = 0;
while ((len1 = fr.read()) != -1) {
System.out.println(((Object)len1).getClass().toString());
System.out.println(len1);
}
fr.close();
}
}
2. Writer
import java.io.*;
public class StreamTest {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("Writer.txt");
fw.write("Java是世界上最好的语言.py");
fw.close();
}
}
四、转换流
InputStreamReader和OutputStreamWriter用于字节流和字符流之间的转换。
InputStreamReader:将字节输入流转换成字符输入流OutputStreamWriter:将字节输出流转换成字符输出流
注意:只能对文本文件进行转换,图片、视频等非文本文件转换会导致数据丢失。
五、File类
File类用于封装文件或目录路径,提供文件操作功能。
1. 常用构造方法
File(File parent, String child);
File(String pathname);
File(String parent, String child);
File(URI uri);
2. 常用方法
| 方法 | 描述 |
|---|---|
getName() |
返回文件或目录名称 |
getParent() |
返回父路径名字符串 |
getParentFile() |
返回父路径名的File对象 |
getPath() |
转换为路径名字符串 |
isAbsolute() |
测试是否为绝对路径 |
getAbsolutePath() |
返回绝对路径 |
canRead() |
测试是否可读 |
canWrite() |
测试是否可写 |
exists() |
测试是否存在 |
isDirectory() |
测试是否为目录 |
isFile() |
测试是否为标准文件 |
lastModified() |
返回最后修改时间 |
length() |
返回文件长度 |
createNewFile() |
创建新文件 |
delete() |
删除文件或目录 |
deleteOnExit() |
虚拟机终止时删除 |
list() |
返回目录中的文件和目录名数组 |
list(FilenameFilter filter) |
返回满足过滤器的文件名数组 |
listFiles() |
返回File对象数组 |
listFiles(FileFilter filter) |
返回满足过滤器的File对象数组 |
mkdir() |
创建目录 |
mkdirs() |
创建目录及必需父目录 |
renameTo(File dest) |
重命名文件 |
3. 文件过滤器
import java.io.*;
import java.util.Arrays;
public class FileTest {
public static void main(String[] args) {
File f = new File("C:\\JAVA");
if (f.isDirectory()) {
String[] filenames = f.list((dir, name) -> name.endsWith(".md"));
Arrays.stream(filenames).forEach(ff -> System.out.println(ff));
}
}
}
六、RandomAccessFile
可以随机访问文件任意位置进行读写。
1. 构造方法
RandomAccessFile(File file, String mode);
RandomAccessFile(String name, String mode);
2. 常用方法
long getFilePointer():返回当前指针位置void seek(long pos):设置文件指针偏移量int skipBytes(int n):跳过n个字节
七、对象序列化
1. 序列化接口
Serializable:简单实现,系统自动完成Externalizable:需手动实现方法,更灵活
2. serialVersionUID
private static final long serialVersionUID = 1L;
3. 示例
// SerializableTest.java
import java.io.*;
public class SerializableTest {
public static void main(String[] args) throws Exception {
// 序列化
FileOutputStream fos1 = new FileOutputStream("test1.txt");
ObjectOutputStream oos1 = new ObjectOutputStream(fos1);
Person ps1 = new Person("test", 8848);
oos1.writeObject(ps1);
oos1.close();
fos1.close();
// 反序列化
FileInputStream fis1 = new FileInputStream("test1.txt");
ObjectInputStream ois1 = new ObjectInputStream(fis1);
Person ps2 = (Person)ois1.readObject();
fis1.close();
ois1.close();
ps2.getInfo();
}
}
// Person.java
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void getInfo() {
System.out.println("name: " + name + " | age: " + age);
}
}
八、NIO
JDK1.4引入的New I/O,核心组件:
- Buffer
- Channel
- Selector
1. Buffer
Buffer子类:
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
创建Buffer:
CharBuffer buffer = CharBuffer.allocate(10);
Buffer属性:
- capacity:容量
- limit:界限(可读区域的第一个索引)
- position:下一个可读写的位置索引
示例:
import java.nio.CharBuffer;
public class FileTest {
public static void main(String[] args) {
CharBuffer cbf1 = CharBuffer.allocate(10);
for (int i = 0; i <= 9; i++) {
cbf1.put((char)i);
}
System.out.println(cbf1.capacity());
System.out.println(cbf1.limit());
System.out.println(cbf1.position());
cbf1.flip(); // 反转缓冲区
for (int i = 0; i <= 9; i++) {
System.out.println((int)cbf1.get());
}
}
}
2. Channel
Channel实现类:
- DatagramChannel:UDP通信
- FileChannel:文件读写
- Pipe.SinkChannel/Pipe.SourceChannel:线程间通信
- ServerSocketChannel/SocketChannel:TCP通信
示例:
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
public class FileTest {
public static void main(String[] args) throws Exception {
RandomAccessFile raf1 = new RandomAccessFile("test1.txt", "rw");
RandomAccessFile raf2 = new RandomAccessFile("test2.txt", "rw");
FileChannel fc1 = raf1.getChannel();
FileChannel fc2 = raf2.getChannel();
long transferto = fc1.transferTo(0, fc1.size(), fc2);
System.out.println(transferto);
}
}
3. NIO.2 (JDK7+)
新增内容:
java.nio.file包- 全面的文件系统支持
- 异步Channel I/O
3.1 Path接口
用于定位文件的对象。
3.2 Paths和Files工具类
Paths提供创建Path对象的静态方法:
Path path = Paths.get("example.txt");
Files提供操作文件的静态方法:
Files.copy(source, target);
Files.move(source, target);
Files.delete(path);
Files.readAllLines(path);