- 下方,标红为重点,蓝底为掌握。
- ">
- 流的分类(重点):1.从存取方向上讲:所有流被分为输入流和输出流。2.从编码上讲,流分为字节流和字符流。3. 从类的实现上讲:节点流(或称文件流)分为4个基类(即,(输入 or 输出) & (字节 or 字符)共4种组合),而这4个基类的子类属于处理流(如缓冲流、转换流、等等)。
- ">
- “字节流、字符流、缓冲流”(个人观点)
- IO流的实现代码一般4个步骤:
- 拷贝文件:文件流(节点流) vs 缓冲流(更快)
- 字符缓冲流: 在读写方式上,对文本数据做了补充,比如readLine()方法。
- 转换流: 属于字符流,它提供字节流与字符流之间的转换
- 对象流: 1.(反)序列化: 对象与字节数据的转换。2. 类可序列化3点要求:1.实现Serializable接口、 2.并提供static final long serialVersionUID属性、3. 内部属性满足可序列化、3. 开发上,一般不直接序列化对象为字节数据,而是先序列化为String,并用json格式来保存字符串。
- 随机存取文件流: 1.继承Object类,2.同时实现DataInput、DataOutput接口(由构造器的mode参数控制),3.文件记录指针:long getFilePointer(), void seek(long pos)。
- 方法补充:”abc”.getBytes()
- Java NIO(先了解,以后再展开): 1. jdk1.4推出的(Non-Blocking IO)。2. NIO面向缓冲区的(原IO面向流)、基于通道的IO操作。3. NIO有两套,分别针对标准IO、网络编程。4. jdk1.7推出NIO.2。
下方,标红为重点,蓝底为掌握。
流的分类(重点):1.从存取方向上讲:所有流被分为输入流和输出流。2.从编码上讲,流分为字节流和字符流。3. 从类的实现上讲:节点流(或称文件流)分为4个基类(即,(输入 or 输出) & (字节 or 字符)共4种组合),而这4个基类的子类属于处理流(如缓冲流、转换流、等等)。
“字节流、字符流、缓冲流”(个人观点)
- 关于字节流和字符流:从机器的角度讲,字节流就够了,但是对于人而言,字符是字节编码而来的,为了适应这种编码机制,专门提供了处理字符数据的字符流。
- 缓冲流并非字节流和字符流的并行概念,它是对字节流和字符流的“赋能”(即继承自节点流,属于处理流的一种),它提供一个额外的缓冲区(默认8kb)及配套方法,增强了读写速度。所以在开发中,一般都用字节缓冲流、字符缓冲流。
IO流的实现代码一般4个步骤:
拷贝文件:文件流(节点流) vs 缓冲流(更快)
如下代码的结论:
fileStream copy 完成.平均耗时:256
bufferStream copy 完成.平均耗时:76
可见,缓冲流更快,关键原因其实它内部额外提供来一个比较大的缓冲区: buffer流额外提供了默认大小为DEFAULT_BUFFER_SIZE=1024*8 (即8kb) 的缓冲区。
注意:下方代码里也定义了 byte[] bbuf = new byte[1024] 来读写字节数据,也是算是简单的缓冲区,所以如果将文件流这里的bbuf设置大一些,文件流的速度也会很快。 但是注意,缓冲流中的缓冲区额外还有 flush()方法来刷新缓冲区等机制。
代码
package xj.java;
import org.junit.jupiter.api.Test;
import java.io.*;
/**
* @author jia
* @create 2021-12-01 6:16 下午
*/
public class CopyFile {
@Test
public void copyTest(){
String src = "/Users/xujia/Desktop/bigdata/1.尚硅谷大数据学科--核心基础/尚硅谷Java核心基础/v.avi";
String des = "/Users/xujia/Desktop/bigdata/1.尚硅谷大数据学科--核心基础/尚硅谷Java核心基础/v-filecopy.avi";
String bufferdes = "/Users/xujia/Desktop/bigdata/1.尚硅谷大数据学科--核心基础/尚硅谷Java核心基础/v-buffercopy.avi";
long a;
long file_total = 0;
long buffer_total = 0;
int times = 10;
for (int i=0 ; i < times;i++){
a = System.currentTimeMillis();
filecopy(src,des);
file_total += (System.currentTimeMillis() - a);
a = System.currentTimeMillis();
buffercopy(src,bufferdes);
buffer_total += (System.currentTimeMillis() - a);
}
System.out.println("fileStream copy 完成.平均耗时:" + (file_total / times));
System.out.println("bufferStream copy 完成.平均耗时:" + (buffer_total / times));
}
public static void buffercopy(String src,String des){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(src));
bos = new BufferedOutputStream(new FileOutputStream(des));
byte[] bbuf = new byte[1024];
int bbuf_size = 0;
while ((bbuf_size = bis.read(bbuf)) != -1){
bos.write(bbuf,0,bbuf_size);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bis != null)
bis.close();
if (bos != null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void filecopy(String src,String des){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// make stream
fis = new FileInputStream(src);
fos = new FileOutputStream(des);
// copy
byte[] bbuf = new byte[1024];
int bbuf_size = 0;
while ((bbuf_size = fis.read(bbuf)) != -1){
fos.write(bbuf,0,bbuf_size);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符缓冲流: 在读写方式上,对文本数据做了补充,比如readLine()方法。
转换流: 属于字符流,它提供字节流与字符流之间的转换
对象流: 1.(反)序列化: 对象与字节数据的转换。2. 类可序列化3点要求:1.实现Serializable接口、 2.并提供static final long serialVersionUID属性、3. 内部属性满足可序列化、3. 开发上,一般不直接序列化对象为字节数据,而是先序列化为String,并用json格式来保存字符串。
关于序列化中的 serialVersionUID属性: 可唯一标识类,即使在序列化后对类进行了修改,那么反序列化依然能进行。反之,如果不提供该属性,虽然序列化依然可进行,一旦类进行了修改,则反序列化失败。
(代码)将Person对象序列化
package xj.java;
import org.junit.jupiter.api.Test;
import java.io.*;
/**
* @author jia
* @create 2021-12-01 10:46 下午
*/
public class Serialize {
@Test
public void SerialTest(){
Person person = new Person("jia", 12306,1000);
OutputStream os = null;
ObjectOutputStream objectOutputStream = null;
// 1. 序列化
try {
os = new FileOutputStream("person.bin");
objectOutputStream = new ObjectOutputStream(os);
objectOutputStream.writeObject(person);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (objectOutputStream != null){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 2. 反序列化
InputStream is = null;
Person person2 = null;
ObjectInputStream objectInputStream = null;
try {
is = new FileInputStream("person.bin");
objectInputStream = new ObjectInputStream(is);
try {
person2 = (Person) objectInputStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (objectInputStream != null)
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 测试 原对象和反序列化对象
System.out.println("原对象: " + person);
System.out.println("反序列化对象: " + person2);
}
}
class Acount implements Serializable{
@java.io.Serial
private static final long serialVersionUID = -6849794470712367710L;
float balance;
public Acount(float balance) {
this.balance = balance;
}
@Override
public String toString() {
return "balance=" + balance ;
}
}
class Person implements Serializable {
// 1. 实现Serializable接口
// 2. 唯一化标识
@java.io.Serial
private static final long serialVersionUID = -6821941230754667710L;
String name;
int carId;
Acount acount; // 3. 所有属性要可序列化
public Person(String name, int carId, float acount) {
this.name = name;
this.carId = carId;
this.acount = new Acount(acount);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", carId=" + carId +
", acount=" + acount +
'}';
}
}
随机存取文件流: 1.继承Object类,2.同时实现DataInput、DataOutput接口(由构造器的mode参数控制),3.文件记录指针:long getFilePointer(), void seek(long pos)。
seek: 比如实现多线程断点下载。
方法补充:”abc”.getBytes()
Java NIO(先了解,以后再展开): 1. jdk1.4推出的(Non-Blocking IO)。2. NIO面向缓冲区的(原IO面向流)、基于通道的IO操作。3. NIO有两套,分别针对标准IO、网络编程。4. jdk1.7推出NIO.2。
- NIO.2 : 引入Path类替代原Files类,提供Files工具类来操作文件或目录