Bootstrap

Java - IO流

IO流的概述

内存:短暂存储,进程结束后停止,所以需要一个暂时储存的地方

IO流:存储和读取数据的解决方案

File:表示系统中的文件或者文件夹的路径

image-20231225132528272

注意:File类只能对文件本身进行操作,不能读写文件里储存的数据

IO流:可以把数据保存到本地文件当中(output),也可以把文件中的数据加载到程序当中(input)

程序作为执行对象,也就是主语,程序到文件就是输出,文件到程序就是输入

写入程序,写出程序

IO流的作用:

用于读写数据(本地文件、网络)

IO流的分类:

image-20231225133208877

纯文本文件:txt、md、xml、lrc

image-20231225133252949

IO流的体系和字节输入流的基本用法:

image-20231225134952532

FileOutputStream

操作本地文件的字节输出流,可以把系统中的数据写到本地文件中

书写步骤:

1.创建字节输出流对象

2.写数据

3.释放资源

 public class test1 {
     public static void main(String[] args) throws IOException {
         FileOutputStream fileOutputStream = new FileOutputStream("src/IO1/txt");
         fileOutputStream.write(97);
         fileOutputStream.close();
 ​
     }
 }

image-20231225162314252

字节输出流写出数据的细节:

1.创建字节输出流对象

细节1:参数是字符串表示的路径或者File对象都是可以的

细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的

细节3:如果文件已经存在,那么会清空文件

2.写数据

write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符

写数字的时候写数字对应的整数就可以

3.释放资源

如果不释放则显示一直使用中

字节输出流写出数据的方法:

 public class test1 {
     public static void main(String[] args) throws IOException {
         FileOutputStream fileOutputStream = new FileOutputStream("src/IO1/txt");
         //普通写入,一次只写入一个数据
         fileOutputStream.write(97);
         //数组整个写入
         byte[] byte1 = {97,98,99,100,101};
         fileOutputStream.write(byte1);
         //数组部分输入
         fileOutputStream.write(byte1,0,2);
         fileOutputStream.close();
 ​
     }
 }

换行和续写:

 public class test1 {
     public static void main(String[] args) throws IOException {
         FileOutputStream fileOutputStream = new FileOutputStream("src/IO2/txt");
         String str = "李宇航";
         byte[] bytes = str.getBytes();
         fileOutputStream.write(bytes);
         fileOutputStream.close();
     }
 }

在java中\r\n单独写一个就可以换行,但是最好还是写全,

linux系统中,写\n是换行的意思,

在苹果系统中则是\r换行

换行的时候写到想要换的内容的中间就行,不用再重复写什么字符串和数组了

 
public class test1 {
     public static void main(String[] args) throws IOException {
         FileOutputStream fileOutputStream = new FileOutputStream("src/IO2/txt");
         String str = "李宇航\r\n123";
         byte[] bytes = str.getBytes();
         fileOutputStream.write(bytes);
         fileOutputStream.close();
     }
 }

续写,不删除原内容的方式

 
public class test1 {
     public static void main(String[] args) throws IOException {
         FileOutputStream fileOutputStream = new FileOutputStream("src/IO2/txt",true);
         String str = "李宇航\r\n123";
         byte[] bytes = str.getBytes();
         fileOutputStream.write(bytes);
         fileOutputStream.close();
     }
 }

字节输入流的基本用法

 public class test1 {
     public static void main(String[] args) throws IOException {
         FileInputStream fileInputStream = new FileInputStream("src/IO3/txt");
         int contain = fileInputStream.read();
         System.out.println((char)contain);
         fileInputStream.close();
     }
 }

字节输入流读取数据的细节

1.创建字节输入流对象

细节1:如果文件不存在,直接报错

2.读取数据

细节1:一次读一个字节,读出来的是数据在ASCII上对应的数字

细节2:读到文件末尾了,read方法返回-1

空格对应也有ASCII整数

3.释放资源

每次使用完必须释放资源

字节输入流循环读取

 public class test1 {
     public static void main(String[] args) throws IOException {
         FileInputStream fileInputStream = new FileInputStream("src/IO3/txt");
         int a;
         while((a = fileInputStream.read()) != -1){
             System.out.print((char)a);
         }
         fileInputStream.close();
     }
 }

.read方法使用一次指针向后移动一位,若使用两次则移动两位,所以就可以实现跳跃阅读

 
public class test1 {
     public static void main(String[] args) throws IOException {
         FileInputStream fileInputStream = new FileInputStream("src/IO3/txt");
         while((fileInputStream.read()) != -1){
             System.out.print(fileInputStream.read()+"\r\n");
         }
         fileInputStream.close();
     }
 }

image-20231225183432575

文件拷贝的基本代码

适用于小文件的转移

 public class test1 {
     public static void main(String[] rgs) throws IOException {
         //创建输入流对象
         FileInputStream fileInputStream = new FileInputStream("src/IO3/txt");
         FileOutputStream fileOutputStream1 = new FileOutputStream("src/IO4/txt1");
         //边读边写
         int middle;
         while((middle = fileInputStream.read()) != -1){
             fileOutputStream1.write(middle);
         }
         fileInputStream.close();
         fileOutputStream1.close();
     }
 }

文件拷贝的弊端和解决方案

缺点:一个字节一个字节读,所以读取的速度很慢

解决办法:

一次读一个字节数组的数据,每次读取会尽可能把数组装满

创建数组一般使用1024的整数倍,推荐使用1024 * 1024 * 5(5兆)

使用数组读取文件内容时,读取到的内容会把数组内的原有内容做一个覆盖,但是要是原有内容不足以覆盖的话,就会有原有数据在数组内的残留,但是读取的长度只能是存入数组的长度

 public class test {
     public static void main(String[] args) throws IOException {
         FileInputStream fileInputStream = new FileInputStream("src/IO5/txt");
         byte[] bytes = new byte[2];
         int middle;
         middle = fileInputStream.read(bytes);
         String str = new String(bytes);
         System.out.println(str);
         System.out.println(middle);
 ​
         int middle1;
         middle = fileInputStream.read(bytes);
         String str1 = new String(bytes);
         System.out.println(str1);
         System.out.println(middle);
 ​
         int middle2;
         middle = fileInputStream.read(bytes);
         String str2 = new String(bytes);
         System.out.println(str2);
         System.out.println(middle);
         fileInputStream.close();
     }

image-20231225193059996

修正:

 public class test1 {
     public static void main(String[] args) throws IOException {
         byte[] bytes = new byte[2];
         FileInputStream fileInputStream = new FileInputStream("src/IO5/txt");
         int len;    
         len = fileInputStream.read(bytes);
         String string = new String(bytes,0,len);
         System.out.println(string);
 ​
     }
 }

文件的快速拷贝

 
public class test {
     public static void main(String[] args) throws IOException {
         long start = System.currentTimeMillis();
         FileInputStream fileInputStream = new FileInputStream("src/IO5/txt");
         FileOutputStream fileOutputStream1 = new FileOutputStream("src/IO4/txt1");
         byte[] bytes = new byte[1024 * 1024 *5];
         int len;
         while((len = fileInputStream.read(bytes)) != -1){
             fileOutputStream1.write(bytes,0,len);
         }
         fileInputStream.close();
         fileOutputStream1.close();
         long end = System.currentTimeMillis();
         System.out.println(end - start);
     }
 }

最后end - start 的出的结果就是运行时间的毫秒值

IO流中不同版本捕获异常的方式

finally中的代码一定会被执行到

image-20231225200903703

image-20231225200921421

字符集详解ASCII、GBK

在计算机中,任意数据都是以二进制数据存储的

image-20231225202717275

以上就是汉字的“ASCII表”,GBK完全兼容ASCII表,ASCII对应的数组在GBK中也存在

image-20231225202949994

image-20231225203134256

以1还是0开头其实就是为了区分英文和汉字,英文是不足用0补齐

字符集详解Unicode

image-20231225203634565

image-20231225204020933

image-20231225204532861

image-20231225204643291

UTF-8是编码表的一种格式

image-20231225205024482

乱码出现的原因

原因1:读取数据时未读完整个汉字

比如说汉字只读了三分之一

原因2:编码和解码的方式不统一

image-20231225205518495

改正方式:

1.不要用字节流读取文本文件

2.编码解码时使用的同一个码表,同一个编码形式

扩展:

字节流读取中文会乱码,但是为什么拷贝不会乱码呢?

在拷贝的时候是一个字节一个字节拷贝的

所以记事本应该和编码工具保持一致

编码和解码

 public class test {
     public static void main(String[] args){
         //编码
         String string = "李宇航";
         byte[] bytes = string.getBytes();
         System.out.println(Arrays.toString(bytes));
         //解码
         String string1 = new String(bytes);
         System.out.println(string1);
     }
 }

image-20231225221859543

字符输入流空参read

字符流:

字符流的底层其实就是字节流

image-20231225222233562

特点:

输入流:一次读一个字节,遇到中文时,一次读多个字节

输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中

使用场景:

对于纯文本文件进行读写操作

image-20231225222628080

1.创建字符输入流对象

和字节流类似

2.读取数据

细节1:按字节进行读取,遇到中文,一次读多个字节,读取后解码,返回一个整数

细节2:读到文件末尾了,read方法返回-1

3.释放资源

read的底层方法是读取文件将其转换为二进制文件,再转换成十进制作为返回值

 public class test {
     public static void main(String[] args) throws IOException {
         FileReader fileReader = new FileReader("src/IO8/txt");
         int ch;
         while((ch = fileReader.read()) != -1){
             System.out.print((char) ch);
         }
         fileReader.close();
     }
 }

image-20231225223929904

带参read方法

 public class test {
     public static void main(String[] args) throws IOException {
         FileReader fileReader = new FileReader("src/IO8/txt");
         int len;
         char[] chars = new char[2];
         while((len = fileReader.read(chars)) != -1){
             System.out.print(new String(chars,0,len));
         }
         fileReader.close();
     }
 }

字符输出流

image-20231225224919596

 public class test {
     public static void main(String[] args) throws IOException {
         FileWriter fileWriter = new FileWriter("src/IO9/txt");
         fileWriter.write("李宇航");
         fileWriter.close();
     }
 }

字符流可以直接向文本内写入文字类型

image-20231225225646119

;