io流的概述
首先说一下流的概念:流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出。
Java中对io流的使用类
数据输入输出流的概述:Java中对数据的输入流和输出流针对传输不同类型的数据有多个类
但最主要的还是分为字符流和字节流
-
数据输入输出流
数据输入流: DataInputStream
数据输出流: DataOutputStream特点: 可以写基本数据类型,可以读取基本数据类型
-
内存操作流
- 操作字节数组
ByteArrayOutputStream
ByteArrayInputStream
此流关闭无效,所以无需关闭 - 操作字符数组
CharArrayWrite
CharArrayReader - 操作字符串
StringWriter
StringReader
- 操作字节数组
-
序列化流和反序列化流(操作对象)
- 序列化流的概述
所谓的序列化:就是把对象通过流的方式存储到文件中.注意:此对象 要重写Serializable 接口才能被序列化 - 反序列化:就是把文件中存储的对象以流的方式还原成对象
- 序列化流的概述
-
为什么要做序列化?
①、在分布式系统中,此时需要把对象在网络上传输,就得把对象数据转换为二进制形式,需要共享的数据的 JavaBean 对象,都得做序列化。
②、服务器钝化:如果服务器发现某些对象好久没活动了,那么服务器就会把这些内存中的对象持久化在本地磁盘文件中(Java对象转换为二进制文件);如果服务器发现某些对象需要活动时,先去内存中寻找,找不到再去磁盘文件中反序列化我们的对象数据,恢复成 Java 对象。这样能节省服务器内存。 -
Java 怎么进行序列化?
①、需要做序列化的对象的类,必须实现序列化接口:Java.lang.Serializable 接口(这是一个标志接口,没有任何抽象方法),Java 中大多数类都实现了该接口,比如:String,Integer
序列化流: ObjectOutputStream
反序列化流: ObjectInputStream
注意:一个对象可以被序列化的前提是这个对象对应的类必须实现Serializable接口
②、底层会判断,如果当前对象是 Serializable 的实例,才允许做序列化,Java对象 instanceof Serializable 来判断。
③、在 Java 中使用对象流来完成序列化和反序列化
ObjectOutputStream:通过 writeObject()方法做序列化操作
ObjectInputStream:通过 readObject() 方法做反序列化操作
如果某些数据不需要做序列化,在字段面前加上 transient
实例:
创建一个类:
import java.io.Serializable;
public class Test implements Serializable {
private static String name="苏大强";
private static int age=67;
private static String hobby="要钱";
public Test() {
}
public Test(String name, int age, String hobby){
this.name=name;
this.age=age;
this.hobby=hobby;
}
public static String getName() {
return name;
}
public static void setName(String name) {
Test.name = name;
}
public static int getAge() {
return age;
}
public static void setAge(int age) {
Test.age = age;
}
public static String getHobby() {
return hobby;
}
public static void setHobby(String hobby) {
Test.hobby = hobby;
}
}
对该类进行序列化和反序列化
import java.io.*;
public class IODemo02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
xuliehua();//序列化方法
fanxuliehua();//反序列化方法
}
private static void fanxuliehua() throws IOException, ClassNotFoundException {
InputStream inputStream = new FileInputStream("test对象.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
Test test= (Test) objectInputStream.readObject();
//通过反序列化得到序列化的对象
System.out.println(test.getName());
System.out.println(test.getAge());
System.out.println(test.getHobby());
objectInputStream.close();
}
private static void xuliehua() throws IOException {
OutputStream outputStream = new FileOutputStream("test对象.txt");
//利用FileOutputStream 类创建存放对象字节码的文件
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(new Test("苏小强",12,"打苏大强"));
//写入对象
objectOutputStream.close();
//关闭流
}
}
结果:
操作文件流
FileInputStream 文件输入流
FileOutpuStream 文件输出流
可以将一个文件进行字节流的传送,包括对一个文件的复制
示例:
import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
import java.io.*;
public class IODemo01 {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("E:\\javaproject\\IoTest\\IOTest");
System.out.println(fileInputStream.read());
readmethod1();
//byte[] buf=new byte[ fileInputStream.available()];
// fileInputStream.read(buf);
// System.out.println(new String(buf));
// fileInputStream.close();
}
public static void readmethod1() throws IOException {
File file=new File("IOTest");
FileInputStream fileInputStream=new FileInputStream(file);
byte[] buf=new byte[ fileInputStream.available()];
//直接将整个文件的字节大小定位一个字节数组,直接一次性读取完整个文件,方法特殊只能对较小的文件进行读取,而大的文件就不适用,强行使用会内存溢出
fileInputStream.read(buf);
System.out.println(new String(buf));
fileInputStream.close();
// writemethod1();
writemethod2();
//readmethod2();
readmethod3();
}
private static void writemethod2() {
try {
FileOutputStream fileOutputStream = new FileOutputStream("余佳美我选你写一千遍.txt",true);
//这里将append设置成为一个true就是允许文件再尾部添加内容,而不覆盖原本的内容
for (int i= 0; i < 1000; i++) {
fileOutputStream.write("余佳美我喜欢你呀!\r".getBytes());
}
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void readmethod3() {
try {
FileInputStream fileInputStream = new FileInputStream("IoTest");
FileOutputStream fileOutputStream = new FileOutputStream("来一组杀一组.txt");
//同样定义一个字节数组
byte[] buf=new byte[1024*8];
int len;
while((len= fileInputStream.read(buf))!=-1)
{
fileOutputStream.write(buf);
}
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void readmethod2() {
//可以将文件进行字节流读取的时候我们可以读一个写一个
try {
FileInputStream fileInputStream = new FileInputStream("IoTest");
FileOutputStream fileOutputStream = new FileOutputStream("一个一个来.txt");
byte[] buf=new byte[1024*8];
//定义这个字节数组的目的就是将读取的字节先存入这个缓存区里,以这个数组的字节大小为单位进行读取
int len;
while((len=fileInputStream.read(buf))!=-1){
// while 循环里的条件是指只要还能再文件里读到字节就继续写否则停止
fileOutputStream.write(buf,0,len);
//写的时候也是一个一个来写从传入的每个字节数组的0索引直到后一个字节
}
fileInputStream.close();
fileOutputStream.close();
//关闭流
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writemethod1( ) throws IOException{
File file =new File("蔡徐坤.txt");
//新建一个文件,文件名为蔡徐坤.txt,未指定绝对路径则文件生成在idea的跟目录下
FileOutputStream fileOutputStream=new FileOutputStream(file);
//直接写入将字符转换为字节
fileOutputStream.write("别再黑坤坤了,你知道他有多菜吗!".getBytes());
fileOutputStream.close();
}
}
结果: