1、IO
1、File类
被定义为文件和目录路径名的抽象表现形式,这是因为File类既可以表示文件也可以表示目录,他们都通过对应的路径来描述。
创建一个File类:
File f = new File("D:\\temp.txt"); //通过f对temp.txt进行操作File类的常用方法
构造方法
File(String pathname)
通过路径字符串创建对象File(String parent, String child)
通过父路径和子路径组合创建对象File(File parent, String child)
通过父File对象和子路径组合创建对象文件检测
boolean exists()
检测文件/目录是否存在boolean isFile()
判断是否是文件boolean isDirectory()
判断是否是目录boolean canRead()
检测是否可读boolean canWrite()
检测是否可写文件操作
boolean createNewFile()
创建新文件(仅当文件不存在时)boolean delete()
删除文件或空目录boolean renameTo(File dest)
重命名/移动文件路径获取
String getPath()
获取相对路径字符串String getAbsolutePath()
获取绝对路径字符串String getName()
获取文件名/目录名long length()
获取文件字节数目录操作
boolean mkdir()
创建单级目录boolean mkdirs()
创建多级目录String[] list()
获取目录下的文件名数组File[] listFiles()
获取目录下的File对象数组其他方法
long lastModified()
获取最后修改时间戳boolean setReadOnly()
设置为只读File[] listRoots()
获取系统根目录(如Windows的盘符)
2、IO流概述
1、什么是IO流
I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读 / 写文件,网络通讯等。
IO 流是一组有序的,有起点和终点的数据集合,是对数据传输的总称和抽象。
IO作用:
- 人机交互
- 文件数据读取写入,数据持久化保存
IO 流的源和目的地:
- 内存
- 控制台
- 磁盘文件
- 网络端点
关于
Input和Output:
- Input 读取外部数据 (磁盘、光盘等存储设备的数据) 到程序 (内存) 中;
- Output 将程序 (内存) 数据输出到磁盘、光盘等存储设备中。
2、IO流分类
根据处理的数据单元不同:
- 字节流:操作的数据单元是8位字节,
InputStream、OutputStream。二进制文件(声音、图片、视频)、文本文件;- 字符流:操作的数据单元是16位字符,
Reader、Writer,通常处理文本文件。根据数据流向不同:
- 输入流:硬盘->内存,只能从中读取数据,而不能向其写入数据。
InputStream、Reader;- 输出流:内存->硬盘,只能向其写入数据,而不能从中读取数据。
OutputStream、Writer;IO流大概有40多个子类,因这四个流都是抽象类,因此子类才是平常调用的类。
3、IO流处理流程
- 打开流
- 在流中进行相应的操作(输入读取,输出写入)
- 关闭流(程序中打开的文件所产生的
IO资源不属于内存里的资源,垃圾回收机制无法进行回收,因此需要显示的关闭文件IO资源)
3、字节流
1、InputStream
InputStream是所有字节输入流的父类,用于从源中读取字节数据。常见的子类包括:
- FileInputStream:从文件系统中的某个文件中获取输入字节。
- 方法:
int read():从输入流中读取一个字节的数据。int read(byte[] b):从输入流中读取一定数量的字节,并将其存储到字节数组中。int read(byte[] b, int off, int len):从输入流中读取一定数量的字节,并将其存储到字节数组的指定偏移量位置。void close():关闭输入流并释放与之相关的系统资源。- ByteArrayInputStream:将字节数组作为输入流。
- 方法:
int read():从字节数组中读取一个字节。int read(byte[] b):从字节数组中读取一定数量的字节。void reset():将流的偏移量重置为0。void mark(int readlimit):标记当前的读取位置。- BufferedInputStream:带有缓冲区的输入流,可以提高读取效率。
- 方法:
int read():从缓冲区中读取一个字节。int read(byte[] b):从缓冲区中读取一定数量的字节。void mark(int readlimit):标记当前的读取位置。void reset():将流的偏移量重置到标记的位置。- DataInputStream:允许从输入流中读取基本Java数据类型的数据。
- 方法:
int readInt():从输入流中读取一个整数。float readFloat():从输入流中读取一个浮点数。double readDouble():从输入流中读取一个双精度浮点数。String readUTF():从输入流中读取一个字符串。
2、OutputStream
OutputStream是所有字节输出流的父类,用于向目标写入字节数据。常见的子类包括:
- FileOutputStream:将字节写入文件系统中的某个文件。
- 方法:
void write(int b):将一个字节写入输出流。void write(byte[] b):将字节数组中的所有字节写入输出流。void write(byte[] b, int off, int len):将字节数组中的一部分字节写入输出流。void close():关闭输出流并释放与之相关的系统资源。- ByteArrayOutputStream:将字节写入字节数组。
- 方法:
void write(int b):将一个字节写入字节数组。void write(byte[] b):将字节数组中的所有字节写入字节数组。byte[] toByteArray():将字节数组输出流的内容转换为字节数组。void reset():清空字节数组输出流。- BufferedOutputStream:带有缓冲区的输出流,可以提高写入效率。
- 方法:
void write(int b):将一个字节写入缓冲区。void write(byte[] b):将字节数组中的所有字节写入缓冲区。void flush():清空缓冲区,将所有数据写入目标。- DataOutputStream:允许将基本Java数据类型的数据写入输出流。
- 方法:
void writeInt(int v):将一个整数写入输出流。void writeFloat(float v):将一个浮点数写入输出流。void writeDouble(double v):将一个双精度浮点数写入输出流。void writeUTF(String str):将一个字符串写入输出流。
3、字节流实现文件拷贝
使用字节流实现文件拷贝的步骤如下:
- 创建源文件的
FileInputStream对象。- 创建目标文件的
FileOutputStream对象。- 使用
read()方法从源文件读取字节数据,并使用write()方法将数据写入目标文件。- 关闭输入流和输出流,释放资源。
4、字符流
1、Reader
Reader是所有字符输入流的父类,用于从源中读取字符数据。常见的子类包括:
- FileReader:从文件系统中的某个文件中获取字符输入。
- 方法:
int read():从输入流中读取一个字符。int read(char[] cbuf):从输入流中读取一定数量的字符,并将其存储到字符数组中。int read(char[] cbuf, int off, int len):从输入流中读取一定数量的字符,并将其存储到字符数组的指定偏移量位置。void close():关闭输入流并释放与之相关的系统资源。- BufferedReader:带有缓冲区的字符输入流,可以提高读取效率。
- 方法:
int read():从缓冲区中读取一个字符。int read(char[] cbuf):从缓冲区中读取一定数量的字符。String readLine():从输入流中读取一行文本。void mark(int readlimit):标记当前的读取位置。void reset():将流的偏移量重置到标记的位置。- StringReader:将字符串作为字符输入流。
- 方法:
int read():从字符串中读取一个字符。int read(char[] cbuf):从字符串中读取一定数量的字符。void reset():将流的偏移量重置为0。
2、Writer
Writer是所有字符输出流的父类,用于向目标写入字符数据。常见的子类包括:
- FileWriter:将字符写入文件系统中的某个文件。
- 方法:
void write(int c):将一个字符写入输出流。void write(char[] cbuf):将字符数组中的所有字符写入输出流。void write(char[] cbuf, int off, int len):将字符数组中的一部分字符写入输出流。void write(String str):将字符串写入输出流。void close():关闭输出流并释放与之相关的系统资源。- BufferedWriter:带有缓冲区的字符输出流,可以提高写入效率。
- 方法:
void write(int c):将一个字符写入缓冲区。void write(char[] cbuf):将字符数组中的所有字符写入缓冲区。void newLine():写入一个行分隔符。void flush():清空缓冲区,将所有数据写入目标。- StringWriter:将字符写入字符串。
- 方法:
void write(int c):将一个字符写入字符串。void write(char[] cbuf):将字符数组中的所有字符写入字符串。String toString():将字符串输出流的内容转换为字符串。
3、字符流实现文件拷贝
使用字符流实现文件拷贝的步骤如下:
- 创建源文件的
FileReader对象。- 创建目标文件的
FileWriter对象。- 使用
read()方法从源文件读取字符数据,并使用write()方法将数据写入目标文件。- 关闭输入流和输出流,释放资源。
5、缓冲流
为了提高数据读写的效率,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,默认使用8192个字节或字符的缓冲区。缓冲流要套接在相应的节点流之上。
根据数据操作单位可以把缓冲流分为:
BufferedInputStream和BufferedOutputStream;BufferedReader和BufferedWriter。当使用
BufferedInputStream读取字节文件时,BufferedInputStream会一次性从文件中读取8192个(8KB),存在缓冲区中,直到缓冲区装满了,才更新从文件中读取下一个8192个字节数组。向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,
BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法flush()可以强制将缓冲区的内容全部写入输出流。关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流。如果是带缓冲区的流对象的
close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出。
1、使用缓冲流实现文件拷贝
使用缓冲流(
BufferedInputStream和BufferedOutputStream或BufferedReader和BufferedWriter)实现文件拷贝可以提高效率。步骤如下:
- 创建源文件的缓冲输入流(
BufferedInputStream或BufferedReader)。- 创建目标文件的缓冲输出流(
BufferedOutputStream或BufferedWriter)。- 使用
read()方法从缓冲输入流读取数据,并使用write()方法将数据写入缓冲输出流。- 调用
flush()方法清空缓冲区,确保所有数据都被写入目标文件。- 关闭缓冲输入流和缓冲输出流,释放资源。
2、按行读取
使用
BufferedReader的readLine()方法可以按行读取文本文件的内容:
- 创建文件的
FileReader对象,并将其包装为BufferedReader。- 使用
readLine()方法逐行读取文件内容,直到返回null(表示文件末尾)。- 处理每一行的内容。
- 关闭
BufferedReader,释放资源。
6、序列化和反序列化
1、简介
序列化(Serialization)是指将对象的状态信息转换为可以存储或传输的形式的过程。反序列化(Deserialization)则是将序列化后的数据重新转换为对象的过程。序列化和反序列化在Java中主要用于对象的持久化存储、网络传输等场景。
2、序列化
序列化是指将对象的状态信息转换为字节序列的过程。在Java中,通过实现
java.io.Serializable接口来使一个类的对象可以被序列化。
- 实现步骤:
- 让类实现
Serializable接口。- 定义一个唯一的序列化ID,
serialVersionUID的静态常量。- 使用
ObjectOutputStream将对象写入到输出流中。- 关闭输出流。
- 重要方法:
ObjectOutputStream.writeObject(Object obj):将对象序列化并写入到输出流中。ObjectOutputStream.flush():刷新输出流,确保所有数据都被写入。ObjectOutputStream.close():关闭输出流并释放资源。- 注意事项:
Serializable是一个标记接口,不包含任何方法。- 如果类中包含非序列化字段,可以使用
transient关键字修饰。- 序列化时,对象的类必须在运行时类路径中存在。
3、反序列化
反序列化是指将字节序列重新转换为对象的过程。在Java中,通过
ObjectInputStream来实现反序列化。
- 实现步骤:
- 创建一个
ObjectInputStream,并将其绑定到一个输入流(如文件输入流)。- 使用
ObjectInputStream.readObject()方法读取对象。- 关闭输入流。
- 重要方法:
ObjectInputStream.readObject():从输入流中读取对象。ObjectInputStream.close():关闭输入流并释放资源。- 注意事项:
- 反序列化时,对象的类必须在运行时类路径中存在。
- 如果对象的类在序列化后发生了变化(如添加或删除字段),可能会导致反序列化失败。
- 可以通过实现
readObject()和writeObject()方法来自定义序列化和反序列化过程。
4、transient关键字
1、基本概念
transient是一个Java关键字,用于修饰类的成员变量。被transient修饰的成员变量不会被序列化。在序列化过程中,这些变量会被忽略,不会被写入到输出流中。
2、使用场景
- 敏感信息:某些成员变量可能包含敏感信息(如密码、密钥等),这些信息不应该被序列化。
- 性能优化:某些成员变量的值可以在反序列化时重新计算或获取,不需要通过序列化保存。
- 避免序列化不必要的字段:某些字段可能与对象的状态无关,或者在序列化时不需要保存。
3、示例代码
以下是一个简单的示例,展示如何使用 transient 关键字:
import java.io.*;
class User implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private transient String password; // 不会被序列化
public User(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
public class SerializationExample {
public static void main(String[] args) {
User user = new User("Alice", "123456");
// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"))) {
oos.writeObject(user);
System.out.println("对象已序列化:" + user);
} catch (IOException e) {
e.printStackTrace();
}
// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser"))) {
User deserializedUser = (User) ois.readObject();
System.out.println("对象已反序列化:" + deserializedUser);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
输出结果:
对象已序列化:User{username='Alice', password='123456'}
对象已反序列化:User{username='Alice', password='null'}
说明:
- 在反序列化后,
password字段的值为null,因为它是transient字段,没有被序列化。
1221

被折叠的 条评论
为什么被折叠?



