华杉研发九学习日记22
IO流
一, 缓冲流
两对流:BufferedInputstream和BufferedOutputstream 以及BufferedReader和BufferedWriter。这两对流能为文件输入输出流增强缓冲区的功能。
缓冲区:在之前的代码中,我们每调用一次read或者write方法,都会触发一次I/O操作。读写硬盘的速度是读写内存速度的千分之一。为了让程序的效率得到提升,我们引入了缓冲机制。
我们会在内存中开辟一块空间,当调用read或者write方法时,并不真正进行I/O操作,而是对内存中的这块空间进行操作。我们以write操作为例,使用了缓冲机制之后,我们调用write方法时,并不真正把数据写入到文件中,而是先把数据放到缓冲区里。等到缓冲区满了之后,再一次性把数据写入文件中。
二, BufferedInputStream 字节缓冲输入流
BufferedInputStream是对InputStream的包装,为字节输入流增加缓冲功能.
它的存在是为了减少读取文件的次数.BufferedlnputStream会一次性从文件
里读取若干字节(默认8KB)的数据存入缓存,以后每次读取是从缓存中读取,缓
存中的数据读完之后,又会一次性从文件里读取若干字节.
缓存:就是一个字节数组.文件中的数据会先读到这个数组里,以后从这个数组里读取数据
// 1.创建节点流,同时把节点流包裹到缓冲流中
FileInputStream fis = new FileInputStream("file/cc.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
// 2.获取
byte[] buf = new byte[1024];
int len;
while ((len = bis.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
// int n=0;
// while((n=bis.read())!=-1){
// System.out.print((char)n);
// }
// 3.释放资源
bis.close();
fis.close();
三, BufferedOutputStream 字节缓冲输出流
BufferedOutputStream是对OutputStream的包装,为字节输出流增加缓冲功能.它的存在是为了减少写入文件的次数.BufferedOutputstream会把要写入文件的数据先写入缓存(默认8KB),当缓存满了之后,会一次性把缓存里的数据写入文件里.
// 1.创建节点流和缓冲流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("file/aa.txt",true));
// 2.写入文件
String mess = "上午好,今天周四,明天周五然后就可以休息啦!!!";
bos.write(mess.getBytes());
// 3.释放资源
bos.close();
带有缓冲的拷贝:
注意:使用缓冲写入后一定要释放资源.close()方法,或者使用.flush()方法清空缓存区,否则会出现拷贝文件出错
// 带有缓冲的拷贝
public static void copy(String from, String to) {
// 1.创建缓冲流
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(from));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(to));
// 2.读取
byte[] buf = new byte[1024];
int len;
while((len=bis.read(buf))!=-1){
bos.write(buf, 0, len);
}
// 3.释放资源
bos.flush();
bos.close();
bis.close();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
copy("C:\\Users\\86155\\Videos\\Counter-strike 2\\Counter-strike 2 2024.03.13 - 00.07.08.01.mp4","C:\\...\\cs.mp4");
long end = System.currentTimeMillis();
System.out.println("拷贝时间:"+(end-start));
}
四, BufferedReader 字符缓冲输入流
// 1.创建
BufferedReader br = new BufferedReader(new FileReader("file/littleApple"));
// 2.读取
String str=null;
while((str=br.readLine())!=null){
System.out.println(str);
}
// 3.释放资源
br.close();
五, BufferedWriter 字符缓冲输出流
/ 1.创建
BufferedWriter bw = new BufferedWriter(new FileWriter("file/aa.txt",true));
// 2.写入
bw.write(" dAWd FAWfawfAAFaFFwaf");
bw.newLine();
bw.write("wAWrwdawdahdiuhfiuonoiuvneoinowuidw");
// 3.释放资源
bw.flush();//如果缓存空间没有满时,想要直接写入文件,则使用flush
bw.close();
六, try-with-resource
大量的异常捕获代码使得以上代码变得十分臃肿难看,好在java7提供了TWR (try-with-resource)语法糖,由于很多外部资源类都间接的实现了AutoCloseable接口,因此可以利用TWR语法在 try结束的时候通过回调的方式自动调用外部资源类的close()方法,避免书写冗长的finally代码块。|
// 使用TWR语法糖,来实现try中的对象自动调用close方法关闭资源的功能
try(BufferedReader br = new BufferedReader(new FileReader("file/littleApple"))) {
// 读取
String s = null;
while((s = br.readLine()) != null) {
System.out.println(s);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
七, ObjectOutputStream(序列化)重点
ObjectOutputStream是对象输出流,继承于OutputStream,它的主要作用是把对象写入到文件中。需要写入到文件的**对象必须是可序列化的,即对象要实现Serializable接口。**Objectoutputstream除了能把对象写入文件之外,还能把基本数据类型写入文件。
// 语法糖实现自动释放资源
try(FileOutputStream fos = new FileOutputStream("file/ps.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);) {
// ObjectOutputStream : 对象流,可以把基本数据类型和对象都写入到文件中
oos.writeByte(12);
oos.writeShort(1);
oos.writeInt(1);
oos.writeDouble(1.0);
oos.writeBoolean(Boolean.TRUE);
oos.writeUTF("中国");
// 写入对象,必须将对象序列化 -- 实现一个序列化接口Serializable
Person p = new Person("小孤鸡",18);
oos.writeObject(p);
} catch (IOException e) {
throw new RuntimeException(e);
}
八, ObjectInputStream(反序列化)重点
ObjectInputStream是对象输入流,它是字节输入流,继承于InputStream。它的主要作用是从文件中读取对象类型的数据。ObjectInputStream不但能从文件中读取对象类型,还能读取基本数据类型数据。
注意:从文件读取数据一定要和存入数据的顺序保持一致
try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file/ps.txt"));) {
// 读取
// --从文件读取数据一定要和存入数据的顺序保持一致
byte b = ois.readByte();
System.out.println(b);
short s = ois.readShort();
System.out.println(s);
int i = ois.readInt();
System.out.println(i);
double d = ois.readDouble();
System.out.println(d);
boolean bo = ois.readBoolean();
System.out.println(bo);
String str = ois.readUTF();
System.out.println(str);
//
Person p = (Person)ois.readObject();
System.out.println(p);
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
九, 字符编码
计算机底层只能识别0101这样的二进制序列(二进制可以与十进制相互转换)无法识别字符,汉字;特殊符号等.为了能够让计算机识别字符,汉字;符号等内容,科学家用一个整型数表示一个字符,而且为每一个字符对应了一个唯一的整数.这就是字符编码.
当然也可以通过这种唯一的对应关系对文字进行解码.
常见的字符编码方式有: ASCIl,GBK,GB18030,GB2312,UTF-8, Unicode等
当文件编码方式和解析环境的编码方式不同时,会出现乱码的情况
需要进行解决
9.1 InputStreamReader
InputStreamReader是输入转换流,它继承于Reader(即它是一个字符输入流),它能把一个字节输入流转换为字符输入流,而且可以在转换的时候指定字符输入流的编码格式.
try(
FileInputStream fis = new FileInputStream("file/bm.txt");
// 再次包裹,两个参数,一个为字节流对象,一个为解析的编码方式
InputStreamReader isr = new InputStreamReader(fis, "GBK");
// 变成字符输入流 在后续需要使用到char数组接收对象
) {
// 读取文件
// byte[] b = new byte[1024];
char b[] = new char[1024];
int len;
while ((len = isr.read(b)) != -1) {
System.out.println(new String(b, 0, len));
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
9.2 OutputStreamWriter
// 环境 UTF-8 文件 GBK
FileOutputStream fos = new FileOutputStream("file/bm.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
//
String s = "你干嘛哈哈哎哟";
//fos.write(s.getBytes());
osw.write(s);
//
osw.close();
fos.close();
十, PrintWriter
PrintWriter pw = new PrintWriter(new FileWriter("file/aa.txt"));
pw.println(true);
pw.println(100);
pw.println("Hello World");
pw.flush();
pw.close();
十一,PrintStream
PrintStream和PrintWriter类似,也是一个比较特殊的过滤流,PrintStream作为过滤流,增强的功能有以下几个:
1、缓冲区的功能
2、写八种基本类型和字符串
3、写对象
我们所熟知的向屏幕输出数据的对象:System.out对象,这就是一个PrintStream类型的对象。
PrintStream ps = new PrintStream(new FileOutputStream("file/log.txt"),true);
System.setOut(ps);
System.out.println("下课啦!");
System.out.println("今天的作业很少!");
System.out.println("明天讲解多线程!");
ps.close();