读取字符流:
由于字符输入流的read()方法返回的是int类型的值,如果想获得字符就需要进行强制类型转换,所以输出语句中将变量len强转为了char类型。
public static void main(String[] args) throws IOException {
//创建FileReader对象
FileReader fileReader = new FileReader("test.txt");
//定义一个变量len,并且初始化
int len = 0;
//判断读到末尾了吗
while((len = fileReader.read())!=-1){
//输出读取到的字符
System.out.println((char)len);
}
//关闭流
fileReader.close();
}
写入字符流:
public static void main(String[] args) throws IOException {
//创建字符输出流文件,指定输出内容
FileWriter fileWriter = new FileWriter("out.txt");
fileWriter.write("轻轻的我来了");
fileWriter.write("轻轻的我又走了");
fileWriter.close();
}
FileWriter同FileOutputStream一样,如果指定的文件不存在,就会先创建文件,再写入数据,如果文件存在,则会首先清空文件中的内容,再进行写入。如果想在文件末尾追加数据,同样需要调用重载的构造方法,现将文件2中的第5行代码进行如下修改:
FileWriter writer = new FileWriter("writer.txt",true);
字符缓冲流: BufferedReader, BufferedWriter
上面两个文件示例通过字符流的形式完成了对文件内容的读写操作,但也是逐个字符进行读写,这样也需要频繁的操作文件,效率仍非常低。这里也可以使用提供的字符流缓冲区(类似于字节流缓冲区)进行读写操作,来提高执行效率。
读取包含中文的文本文件时,可能出现中文乱码
设置编码格式
InputStreamReader fr=new InputStreamReader(fis,"UTF-8");
字符流的缓冲区实现文件的拷贝 :
每次 fileReader.read(buff)
调用都会将读取的数据从数组的开头开始填充,因此写入时始终从 0
索引开始。
public static void main(String[] args) throws Exception {
// 创建FileReader对象,并指定需要读取的文件
FileReader fileReader = new FileReader("reader.txt");
// 创建FileWriter对象,并指定写入数据的目标文件
FileWriter fileWriter = new FileWriter("writer.txt");
// 定义一个int类型的变量len,其初始化值为0
int len = 0;
// 定义一个长度为1024的字符数组
char[] buff = new char[1024];
// 通过循环来判断是否读取到了文件末尾
while ((len = fileReader.read(buff)) != -1) {
// 输出读取到的字符
fileWriter.write(buff, 0, len);
}
// 关闭流
fileReader.close();
fileWriter.close();
}
使用这两个缓冲流实现文件的拷贝
字符流也提供了带缓冲区的字符缓冲流,分别是BufferedReader和BufferedWriter,其中BufferedReader用于对字符输入流进行操作,BufferedWriter用于对字符输出流进行操作。
代码解析:
每次循环都使用readLine()方法读取文件的一行,然后通过write()方法写入目标文件,同时使用了newLine()进行换行写入,否则读取源文件所有行内容都会追加写入目标文件一行中。其中readLine()方法会逐个读取字符,当读到回车符“\r”或换行符“\n”时会将读到的字符作为一行的内容返回。
BufferedReader br =new BufferedReader(new FileReader("reader.txt"));这句不懂
public static void main(String[] args) throws IOException {
BufferedReader br =new BufferedReader(new FileReader("reader.txt"));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("writer.txt"));
//声明一个字符串变量str
String str = null;
//循环时每次读取一行,如果不为null,则继续循环
while ((str = br.readLine())!=null){
//通过缓冲流对象写入文件
bufferedWriter.write(str);
//进入下一行
bufferedWriter.newLine();
}
//关闭流
br.close();
bufferedWriter.close();
}
转换流:
有时字节流和字符流之间也需要进行转换
在JDK中,提供了两个类用于实现将字节流转换为字符流,它们分别是InputStreamReader和OutputStreamWriter。
先创建字节输入流对象获取源文件,放入InputStreamReader中,再转为字符流。
public static void main(String[] args) throws Exception {
// 1、创建字节输入流对象,获取源文件
FileInputStream in = new FileInputStream("reader.txt");
// 将字节输入流对象转换成字符输入流对象
InputStreamReader isr = new InputStreamReader(in);
// 创建字符输入缓冲流对象
BufferedReader br = new BufferedReader(isr);
// 2、创建字节输出流对象,指定目标文件
FileOutputStream out = new FileOutputStream("writer.txt");
// 将字节输出流对象转换成字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(out);
// 创建字符输出缓冲流对象
BufferedWriter bw = new BufferedWriter(osw);
// 定义一个字符串变量
String line = null;
// 通过循环判断是否读到文件末尾
while ((line = br.readLine()) != null) {
// 输出读取到的文件1
bw.write(line);
bw.newLine();
}
// 关闭流
br.close();
bw.close();
}
InputStreamReader:
InputStreamReader构造方法:
InputStreamReader
的构造方法的主要作用是将字节流 (InputStream
) 转换为字符流 (Reader
),并允许你指定字符编码。这是因为不同的字节编码方式(如 UTF-8、ISO-8859-1)会将相同的字节序列解释为不同的字符。因此,通过 InputStreamReader
,你可以确保从字节流中读取的数据以正确的字符集转换为字符,从而正确处理文本数据。
InputStreamReader(InputStream in)
InputStreamReader(InputStream in,String charsetName)
FileReader类是InputStreamReader的子类FileReader(File file)FileReader(String name)该类只能按照本地平台的字符编码来读取数据,用户不能指定其他的字符编码类型
System.out.println(System.getProperty("file.encoding")); //获得本地平台的字符编码类型
OutputStreamWriter:
读写二进制文件:
DataInputStream类
FileInputStream的子类
与FileInputStream类结合使用读取二进制文件
DataOutputStream类
FileOutputStream的子类
与FileOutputStream类结合使用写二进制文件
序列化:
可能需要将一些数据永久的保存到磁盘上,而数据在Java中都是保存在对象当中的。这时就需要使用Java中的对象序列化。
对象序列化机制可以使内存中的Java对象转换成与平台无关的二进制流,既可以将这种二进制流持久地保存在磁盘上,又可以通过网络将这种二进制流传输到另一个网络节点,其他程序在获得了这种二进制流后,还可以将它恢复成原来的Java对象。这种将I/O流中的字节序列恢复为Java对象的过程被称之为反序列化(Deserialize)。
如果想让某个对象支持序列化机制,那么这个对象所在的类必须是可序列化的。在Java中,可序列化的类必须实现Serializable或Externalizable两个接口之一。
步骤:
1.这个student类如果想要序列化,那么就必须要实现Serializable接口或者Externalizable接口
2.创建一个输出流 ObjectOutputStream对象
3.通过输出流的.writeObject()方法写入文件
4.关闭输出流
public class Student implements java.io.Serializable{
}
//对象序列化,写入输出流
objectOutputStream.writeObject(list);
一个对象序列化,(这里的try-catch可以用throws代替)
public static void main(String[] args) {
ObjectOutputStream objectOutputStream = null;//创建一个对象输出流
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream("writer.txt"));
Student student = new Student("陈梦雨",20,"女");
//将对象序列化
objectOutputStream.writeObject(student);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (objectOutputStream!= null){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
多个对象序列化:
使用集合保存对象,可以将集合中的所有对象序列化
public static void main(String[] args) throws IOException {
//保存多个学生对象
ObjectOutputStream objectOutputStream = null;//创建一个对象输出流
objectOutputStream = new ObjectOutputStream(new FileOutputStream("writer.txt"));
Student student = new Student("陈梦雨", 20, "女");
Student student2 = new Student("豆豆", 21, "女");
ArrayList<Student> list = new ArrayList<Student>();
list.add(student);
list.add(student2);
//对象序列化,写入输出流
objectOutputStream.writeObject(list);
}
反序列化:
如果向文件中使用序列化机制写入多个对象,那么反序列化恢复对象时,必须按照写入的顺序读取
步骤:
1.实现Serializable接口
2.创建对象输入流
3.调用readObject()方法,读取对象
4.关闭输入流
一个对象序列化:
public static void main(String[] args) {
ObjectOutputStream objectOutputStream = null;//创建一个对象输出流
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream("writer.txt"));
Student student = new Student("陈梦雨",20,"女");
//将对象序列化
objectOutputStream.writeObject(student);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (objectOutputStream!= null){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
多个对象序列化:
public static void main(String[] args) {
ObjectOutputStream objectOutputStream = null;//创建一个对象输出流
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream("writer.txt"));
Student student1 = new Student("陈梦雨",20,"女");
Student student2 = new Student("阿豆",15,"女");
//将对象序列化
ArrayList<Student> arrayList = new ArrayList<>();
arrayList.add(student1);
arrayList.add(student2);
//对象序列化写入流
objectOutputStream.writeObject(arrayList);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (objectOutputStream!= null){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
一个对象反序列化:
public static void main(String[] args) throws Exception {
//反序列化,输出
ObjectInputStream objectInputStream =null;
//创建objectInputStream输入流
objectInputStream = new ObjectInputStream(new FileInputStream("writer.txt"));
//反序列化,进行强转
Student stu = (Student) objectInputStream.readObject();
//输出生成后的信息
System.out.println("姓名"+stu.getName());
System.out.println("年龄"+stu.getAge());
System.out.println("性别为"+stu.getSex());
if (objectInputStream!=null){
objectInputStream.close();
}
}
多个对象反序列化:
public static void main(String[] args) throws IOException, ClassNotFoundException {
//创建对象
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("writer.txt"));
//反序列化进行强制类型转换
ArrayList<Student> students = (ArrayList<Student>) objectInputStream.readObject();
// Student stu = (Student) objectInputStream.readObject();
//输出对象信息
for (Student stu :students){
System.out.println("姓名"+stu.getName());
System.out.println("年龄"+stu.getAge());
System.out.println("性别为"+stu.getSex());
}
}