目录
4.1FileInputStream FileOutputStream
4.2 BufferedInputStream BufferedOutputStream
4.3 ObjectInputStream ObjectOutputStream
5.2 BufferedReader BufferedWriter
5.3 InputStreamReader OutputStreamWriter
1、IO的概念
I:input 输入 读文件
O:output输出 写文件
开发中我们可能会遇见1、将程序中的数据保存到外部磁盘文件上永久的保存
2、还可能从外部磁盘文件中读取内容到程序当中去
I/O技术流就是用来实现JAVA程序【内存】和外部磁盘进行互相的数据传输,让数据在管道中按照指定的方向进行流通,称此为流技术。
2、流的分类
在Java中,流(Stream)可以分为以下几类:
1. 输入流(InputStream):用于从源(如文件、网络连接)读取数据。
2. 输出流(OutputStream):用于向目标(如文件、网络连接)写入数据。
3. 字符输入流(Reader):用于以字符为单位从源读取数据。
4. 字符输出流(Writer):用于以字符为单位向目标写入数据。
5. 字节流(Byte Stream):以字节为单位读写数据,包括InputStream和OutputStream。
6. 字符流(Character Stream):以字符为单位读写数据,包括Reader和Writer。
7. 缓冲流(Buffered Stream):对其他输入流和输出流添加缓冲功能,提高读写效率。
8. 对象流(Object Stream):用于读写Java对象,包括ObjectInputStream和ObjectOutputStream。
9. 数据流(Data Stream):用于读写基本数据类型和字符串,包括DataInputStream和DataOutputStream。
10. 字符编码流(Charset Stream):用于进行字符编码和解码的流,如InputStreamReader和OutputStreamWriter。
这些流的分类可以根据使用的数据类型、功能和处理方式来进行划分,每种流都有不同的用途和适用场景。在使用流时,根据具体需求选择正确的流类型能够使代码更加简洁和高效。
3、流的四大家族
所有流相关的类都是定义在java.io包中。
1. 输入流(InputStream):用于从源(如文件、网络连接)读取数据。
2. 输出流(OutputStream):用于向目标(如文件、网络连接)写入数据。
3. 字符输入流(Reader):用于以字符为单位从源读取数据。
4. 字符输出流(Writer):用于以字符为单位向目标写入数据。
这四个顶级的父类都是抽象类,并且都实现了Closeable接口。
此次本文张着重12中具体的流:
字节流:凡是类名中带Stream的都是字节流
·FileInputStream FileOutputStream [基本流:new完之后可以直接使用]
`BufferdeInputStream BufferedOutputStream [包装流:提升读写速率]
`ObjectInputStream ObjectOutputStream [包装流:为了让程序员更方便的以对象为单位进行读写]
字符流:凡是类名中带Reader或Writer都是字符流
·FileReader FileWriter [基本的字符流:以字符为单位进行文件的读写,按照固定的编码进行字节到字符的自动转换]
`BufferedReader BufferedWriter [包装流:提升效率,以行为单位]
`InputStreamReader OutputSreamWriter [包装:实现从字节到字符的转换,转换流]
4、字节流
在Java中,字节流由两个基本抽象类来表示:InputStream和OutputStream。这两个类都是抽象类,提供了一些用于读取和写入字节数据的方法。
InputStream类用于从字节流中读取数据,它的常用子类包括FileInputStream(用于从文件读取字节数据),ByteArrayInputStream(用于从字节数组读取数据)等。
OutputStream类用于向字节流中写入数据,它的常用子类包括FileOutputStream(用于向文件写入字节数据),ByteArrayOutputStream(用于向字节数组写入数据)等。
4.1FileInputStream FileOutputStream
FileInputStream
类用于从文件中读取字节数据。它继承自InputStream
类,可以以字节为单位读取文件中的数据。
FileOutputStream
类用于向文件中写入字节数据。它继承自OutputStream
类,可以以字节为单位将数据写入文件。
使用FileInputStream
和FileOutputStream
时,可以将它们与其他字节流进行组合,以实现更复杂的读写操作。例如,可以使用BufferedInputStream
和BufferedOutputStream
来提高读写性能,或者使用DataInputStream
和DataOutputStream
来读写基本数据类型。
需要注意的是,在处理文本文件时,通常会使用FileReader
和FileWriter
等字符流类,因为它们具有更方便的字符操作方法。而FileInputStream
和FileOutputStream
适用于处理二进制文件或不需要进行字符编码解码的操作。
在使用这些类的时候,要小心处理IO操作的异常,确保正确关闭流以释放资源。可以使用try-with-resources
语句来自动处理资源的关闭。
`FileInputStream
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.imageio.stream.*;
public class FileInputStreamTry {
public static void main(String[] args) {
// TODO Auto-generated method stub
//需求:编写一个程序从HelloWorld.txt文件中读取它的所有内容并保存到一
// 个变量str中
String str;
FileInputStream fis= null;//创建 FileInputStream 对象,用于读取文件
try {
fis = new FileInputStream("C:/Users/HP/Desktop/HelloWorld.txt");
//在这块需要注意:文件名之间需要用‘/’来分隔,并且需要用到双引号,并且后面要添加想要读取的文件
//调用输入流对象的read方法来以字节的方式读取文件的内容
//无参方式:直接读取文件中的一个字节
//每个文件内容的最后默认都有一个-1
//将文件中所有的字节读取出来统一存入一个
byte[] bytes = new byte[fis.available()];//获取当前文件中剩余的字节数,即尚未被读取的字节数量
int b,i = 0;
while ((b=fis.read())!=-1) {
bytes[i] = (byte)b;
i++;
// System.out.println(fis);
//字节数组转换成字符串
str = new String(bytes);
System.out.println(str);
// System.out.println(str.length());
}
}
catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("文件未找到!");
}finally {//关闭文件流,释放资源
try {
if (fis!=null) {
fis.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
在这块代码中,如果.txt中存储的是英文则可以完整展示出来,当换成中文之后就很容易出现乱码,即便添加指定字符编码UTF-8输出还是乱码。这块我没有解决,希望有大佬能帮一下。
`FileOutputStream
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTry {
//以字节的方式进行文件的输出,即写文件
public static void main(String[] args) {
// TODO Auto-generated method stub
String s = "你好!";
FileOutputStream fos = null;
try {
fos = new FileOutputStream("C:/Users/HP/Desktop/HelloWorld.txt",true);
// System.out.println(fos);
fos.write(97);
fos.write(98);
fos.write(99);
byte[] bytes = s.getBytes("utf-8");
fos.write(bytes);
} catch (Exception e) {//Exception处理的范围更大
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
4.2 BufferedInputStream BufferedOutputStream
BufferedInputStream
是用于在字节输入流上提供缓冲功能的类。它以更高效的方式从底层输入流中读取字节数据,并将其存储在内部缓冲区中。这样,在每次读取字节时,可以减少对底层输入流的实际访问次数,从而提高读取性能。
BufferedOutputStream
是用于在字节输出流上提供缓冲功能的类。它将要写入的字节数据存储在内部缓冲区中,并以更高效的方式将其写入到底层输出流中。这样,在每次写入字节时,可以减少对底层输出流的实际访问次数,从而提高写入性能。
这些类的主要作用是通过使用缓冲区,减少对底层输入流和输出流的访问次数,从而提高读写性能。它们是处理大规模字节数据时常用的工具类。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BISAndBOS {
public static void main(String[] args) {
BufferedInputStream buff = null;
BufferedOutputStream bos = null;
try {
buff = new BufferedInputStream(new FileInputStream("D:/Key.txt"),8192);//用于读取文件中的内容
bos= new BufferedOutputStream(new FileOutputStream("C:/Users/HP/Desktop/HelloWorld.txt"));//用于把内容写入文件中
int b;
while ((b=buff.read())!=-1) {//将从第一个文件中读出的文件写入第二个文件中
bos.write(b);
}
} catch (Exception e) {//报错就写Exception
// TODO Auto-generated catch block
System.out.println("处理异常!");
}finally {//释放资源
try {
buff.close();
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// bos= new BufferedOutputStream(new FileOutputStream("D:/Key.txt"));
}
}
4.3 ObjectInputStream ObjectOutputStream
ObjectInputStream和ObjectOutputStream是Java中的两个特殊流,用于在Java应用程序中读取和写入对象。
ObjectInputStream用于从输入流中读取java对象。它可以用于反序列化对象,将二进制数据转换为Java对象。要使用ObjectInputStream,需要先将输入流与文件或网络连接相关联,然后使用该流读取对象。
ObjectOutputStream用于将Java对象写入输出流。它可以用于序列化对象,将Java对象转换为二进制数据。要使用ObjectOutputStream,您需要首先将输出流与文件或网络连接相关联,然后使用该流写入对象。
请注意,要使对象可序列化,该对象类必须实现java.io.Serializable接口。
//创建Car类
import java.io.Serializable;
public class Car implements Serializable{
public String name;
public int speed;
@Override
public String toString() {
return "Car [name=" + name + ", speed=" + speed + "]";
}
public Car() {
super();
}
public Car(String name, int speed) {
super();
this.name = name;
this.speed = speed;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
}
//创建Person类
import java.awt.CardLayout;
import java.io.Serializable;
//对象默认是不能被序列化的,如果想要被序列化必须实现一个接口:Serizlizable接口
//否则抛出NotSerializableException 不可序列化的异常
//该接口是一个空接口 里面没有定义任何方法
//空接口的作用就相当于是一个标记,将来序列化程序会检查是否存在这个标记
//需求:将对象保存到磁盘文件中
public class Person implements Serializable{
private static final long serialversionUID = 234234234234L;
private String name;
private int age;
private char gender;
private String mobile;
private transient int money;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
private Car car;
public Person(String name, int age, char gender, Car car) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.car = car;
}
public Person() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", gender=" + gender + ", mobile=" + mobile + ", car=" + car
+ "]";
}
}
import java.awt.List;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
//import java.util.ArrayList;
public class OISAndOOS {
public static void main(String[] args) throws IOException {
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
Person person = new Person("张三",18,'男',new Car("宝马",30));
try {
//将创建的对象写入HelloWorld.dat中
// oos = new ObjectOutputStream(new FileOutputStream("C:/Users/HP/Desktop/HelloWorld.dat"));
// oos.writeObject(person);
// System.out.println("文件已经成功写入文件中!");
// 使用ois将.dat中的内容读出
// ois = new ObjectInputStream(new FileInputStream("C:/Users/HP/Desktop/HelloWorld.dat"));
// Person person2 = (Person) ois.readObject();
// System.out.println("姓名:" + person2.getName());
// System.out.println("年龄:" + person2.getAge());
// System.out.println("性别:" + person2.getGender());
// System.out.println("车辆:" + person2.getCar().getName());
// System.out.println("车速:" + person2.getCar().getSpeed());
//反序列化过程:
ois = new ObjectInputStream(new FileInputStream("C:/Users/HP/Desktop/HelloWorld.dat"));
Person person2 = (Person) ois.readObject();
System.out.println(person2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
ois.close();
// oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
在这一块需要注意要写入的文件不能是.txt类型,否则打开会出现乱码,这是因为写入文件乱码的问题可能是由于文件的扩展名不正确引起的。将文件命名为"HelloWorld.txt",但实际上写入的是一个Java对象,而不是纯文本。所以,应该使用一个具有正确扩展名的文件名。可以将文件类型转换为数据类型,即.dat。
5、字符流
字符流本质上还是字节流,只是它在底层自动的以字符为单位进行了字节的组合。
在Java中,字符流由两个基本抽象类来表示:Reader和Writer。这两个类都是抽象类,提供了一些用于读取和写入字符数据的方法。
Reader类用于读取字符流,它的常用子类包括FileReader(用于从文件读取字符数据),InputStreamReader(用于从输入流读取字符数据)等。
Writer类用于写入字符流,它的常用子类包括FileWriter(用于向文件写入字符数据),OutputStreamWriter(用于向输出流写入字符数据)等。
5.1 FileReader FileWriter
FileReader
和FileWriter
是Java中用于读取和写入文本文件的类。
FileReader
类用于读取字符文件。它继承自Reader类,可以读取一个字符一个字符或一行一行地读取文本数据。
FileWriter
类用于写入字符文件。它继承自Writer类,可以将字符数据写入到文件中。
当创建FileReader
或FileWriter
时,可以选择使用其他的Reader
或Writer
的实现类,来设置字符集编码、缓冲区大小等参数。例如,可以使用BufferedReader
和BufferedWriter
对FileReader
和FileWriter
进行包装,以提高读写性能。
需要注意的是,在使用FileReader
和FileWriter
时,要确保处理的是文本文件,而不是二进制文件。对于二进制文件,应使用字节流(例如FileInputStream
和FileOutputStream
)进行读写操作
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
public class FRAndFW {
public static void main(String[] args) throws Exception {
//测试字符流
//读取HelloWorld.txt中的内容并进行输出
//用字节流的方法读取
// FileInputStream fisFileInputStream = new FileInputStream("C:/Users/HP/Desktop/HelloWorld.txt");//用fisFileInputStream指向将要读取的文本
// InputStreamReader isr = new InputStreamReader(fisFileInputStream, "UTF-8");
// int b;
// while (true) {//读取文本操作
// b = fisFileInputStream.read();
// if(b==-1) break;
// System.out.println((char)b);
//
// }
//用字符流的方法读取
FileReader reader = new FileReader("C:/Users/HP/Desktop/HelloWorld.txt");
while (true) {
int c = reader.read();
if (c==-1) {
break;
}System.out.print((char)c);
}
//使用字节流的方式进行写操作
//FileOutputStream fileOutputStream = new FileOutputStream("C:/Users/HP/Desktop/HelloWorld.txt");
//String string = "HelloJack";
//byte[] bytes = string.getBytes("utf-8");
//fileOutputStream.write(bytes);
//使用字符流的方式进行写操作
FileWriter wrierFileWriter = new FileWriter("C:/Users/HP/Desktop/HelloWorld.txt");
String s ="helloAnna";
wrierFileWriter.write(s);
wrierFileWriter.close();
System.out.println("添加成功!");
}
}
5.2 BufferedReader BufferedWriter
InputStreamReader
和OutputStreamWriter
是Java中的类,用于在字节流和字符流之间进行转换。
InputStreamReader
是一个用于将字节输入流转换为字符输入流的桥梁。它读取字节并将其解码为字符,使用指定的字符集。它可以从各种输入源(如文件、网络连接、标准输入等)读取字节。
OutputStreamWriter
是一个用于将字符输出流转换为字节输出流的桥梁。它将字符转换为字节,并使用指定的字符集编码。它可以将字符流写入各种输出目标(如文件、网络连接、标准输出等)。
这些类的主要作用是在字节流和字符流之间进行字符编码和解码的转换。它们是处理文本数据时常用的工具类。
`BufferedReader
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class BufferedReaderTest {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader("D:/Workspace/FileStream/src/Person.java"));
while (true) {
String line = br.readLine();//表示一次性读取一行的内容
if (line == null) {
break;
}
System.out.println(line);
}
br.close();
}
}
` BufferedWriter
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class BufferedWriterTest {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
BufferedWriter bw = new BufferedWriter(new FileWriter("C:/Users/HP/Desktop/HelloWorld.txt"));
while (true) {
String line = scanner.next();
if(line.equals("quit")) {
break;
}
bw.write(line);
bw.newLine();//写一个换一行
}
bw.close();
}
}
5.3 InputStreamReader OutputStreamWriter
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class ISRAndOSW {
public static void main(String[] args) throws Exception {
//使用字节流写入
String str = "周杰伦";
FileWriter fw = new FileWriter("C:/Users/HP/Desktop/HelloWorld.txt");
fw.write(str);
fw.close();
//使用字符流写入
// OutputStreamWriter Writer = new OutputStreamWriter(new FileOutputStream("C:/Users/HP/Desktop/HelloWorld.txt"),"gbk");
// Writer.write(str);
// Writer.close();
//使用字节流进行读取
// InputStreamReader reader = new InputStreamReader(new FileInputStream("C:/Users/HP/Desktop/HelloWorld.txt"),"utf-8");
// while (true) {
// int r = reader.read();
// if(r!=-1) {
// System.out.println((char)r);
// }else {
// break;
// }
// }
// reader.close();
//使用字符流进行读取
InputStreamReader reader2 = new InputStreamReader(new FileInputStream("C:/Users/HP/Desktop/HelloWorld.txt"),"utf-8");
while (true) {
int c = reader2.read();
if (c==-1) {
break;
}System.out.println((char)c);
}
}
}