(知识学习笔记)IO流与File文件

119 阅读10分钟

IO流与File文件

IO流


前置知识


常见字符集

ASCII :美国信息交换标准代码,包括了英文、符号等

标准ASCII使用一个字节存储一个字符,首位是0,总共可以表示128个字符

GBK(汉字内码扩展规范,国标)

GBK中一个中文字符编码成两个字节的形式存储 英文数字占一个字节

GBK兼容ASCII字符集

GBK规定:汉字的第一个字节的第一位必须是1

Unicode字符集(统一码,也叫万国码)

Unicode是国际组织制定的,可以容纳世界上所有的文字、符号的字符集

UTF-32 四个字节 奢侈! 占存储 通讯效率低

UTF-8 是Unicode字符集的一种编码方案,采取可变长编码方案,共分为四个长度区:1个字节,2个字节,3个字节、4个字节

英文字符、数字等只占一个字节(兼容标准ASCII编码),汉字字符占用了3个字节

对于所需不同字节的编码规则如下表所示:

image-20230818142501953.png

技术人员开发时应使用 UTF-8编码! 英文和数字一般不会出现乱码 (英文多种字符集的编码方案都是兼容ASCII编码的 )


字符集的编码、解码操作

Java代码完成对字符的编码

String提供了如下方法说明
byte[] getBytes()使用平台默认的字符集将该String编码为一系列字节,将结果存储到新的字节数组中
byte[]getBytes(String charsetName)使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中

Java代码完成对字符的解码

String提供了如下方法说明
String (byte[] bytes)通过使用平台的默认字符集解码指定的字节数组来构造新的String
String(byte[]bytes,String charsetName)通过指定的字符集解码指定的字节数组来构造新的String

IO流概述

I指Input,称为输入流:负责把数组读到内存中去 O指Output,称为输出流:负责写数据出去

总的来说:IO流就是输入输出流,读写数据的


IO流的分类

按流的方向分为:

graph TD;
IO流-->输入流
IO流-->输出流

按流中的数据的最小单位,分为:

graph TD
IO流-->字节流
IO流-->字符流
字节流-->适合操作所有类型的文件
适合操作所有类型的文件
字符流-->只适合操作纯文本文件

IO流总体看来有四大流

  1. ​ 字节输入流
  2. ​ 字节输出流
  3. ​ 字符输入流
  4. ​ 字符输出流

image-20230818153210853.png

image-20230818153459805.png


IO流---字节流

FileInputStream(文件字节输入流)

作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去

image-20230818154923314.png

运用字节流的一个实例

 public static void main(String[] args) throws IOException {
        //1、创建一个字节输入流管道与源文件进行接通
        InputStream is = new FileInputStream("D:\\Idea文档\\IO\\kj.txt");
        byte [] buffer=new byte[3]; // 创建 字节数组  每次输出几个字节

        int len=is.read(buffer);
        String s = new String(buffer);
        System.out.println(s);
    }

使用FileInputStream每次读取一个字节(使用read方法),读取性能较差,并且读取汉字会输出乱码。

使用FileInputStream每次读取多个字节,读取性能得到提升,但读取汉字输出还是容易会乱码

使用字节流读取中文,如何保证输出不乱码

:定义一个与文件一样大的字节数组,一次性读取完文件的全部字节

image-20230821090450000.png

存在的问题:如果文件过大,创建的字节数组也会过大,可能引起内存溢出

读取文本内容更适合用 字符流

字节流适合做数据的转移,如文件的复制等


FileOutputStream(文件字节输出流)

作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去

image-20230821091308309.png

image-20230821091320170.png

(getBytes()方法 将一个字符串转化为字节数组byte[]的方法)

默认是一个覆盖管道:覆盖之前的数据

public FileOutputStream(File file,boolean append) 当boolean append为true时,就是一个一个追加 不会清空原来的文件

释放资源的方式

防止出现在代码执行过程中出现异常导致无法进行后面的代码,使得流一直无法进行关闭 需要使用 try-catch-finally

image-20230821094531467.png

finallu代码区的特点:无论try中的程序是正常执行了,还是出现异常,最后都一定会执行finally区,除非JVM终止

千万不要在finally中返回数据!!!

try-with-resource 更简单的资源释放方式

把所要用到的资源都放在try()小括号里面,和上面的相比就可以把finally去掉了 流的关闭都是自动完成 简单了很多

注:try()小括号里面只能放置资源对象

**资源:**都会实现AutoCloseable()接口。资源都会有一个close方法,并且资源放到这里后,用完之后,会被调用其close方法完成资源的释放操作


IO流---字符流


FileReader(文件字符输入流)-读字符数据进来

作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去

image-20230821102907620.png

代码示例:读取我的文件的一个内容 并且输出

public class FileReaderTs1 {
    public static void main(String[] args) throws Exception {
        try (   //1、创建一个文件字符输入流管道与源文件进行接通
                Reader reader = new FileReader("D:\\Idea文档\\IO\\kj.txt")) {
            //2、读取文本文件的内容  
            //每次读一个字节的形式  性能较差
            
            int c;    //记住每次读取的字符编号
            while((c=reader.read())!=-1){
                System.out.print((char)c);
            }
            
            //3、每次读取多个字符  //性能比较不错
            char []buffer=new char[3];
            int len;
            while((len==reader.read(buffer))!=-1){
                System.out.print(new String(buffer,0,len));
            }
            
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

FileWriter(文件字符输出流)-写字符数据到文件中去

public static void main(String[] args) {
        try (   //1、创建一个文件字符输出流管道与源文件进行接通
                Writer fw = new FileWriter("D:\\Idea文档\\IO\\kj2.txt")) {
            //2、public void writer(int c) :写一个字符出去
            fw.write('a');
            fw.write('b');
            fw.write('c');
            fw.write("\r\n"); //换行

            //3、public void writer(String c) :写一个字符串出去
            fw.write("come on!");

            //4、public void writer(String c) :写一个字符数组出去
            char [] buffer={'会','变','好','哒'};
            fw.write(buffer);
            //5、public void write(char [] buffer,int pos,int len)写字符数据一部分出去
            fw.write(buffer,2,2);

        } catch (Exception e) {
           e.printStackTrace();
        }


    }

字符输出流的注意事项

字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效

flush() 刷新流

close()关闭流,关闭流包含刷新流


IO流---缓冲流


字节缓冲流

字节缓冲流作用:提高字节流读写数据的性能

原理:字节缓冲输入流自带了8kb缓冲池;字节缓冲输出流也自带了8kb缓冲池

image-20230821141627825.png


字符缓冲流

BufferedReader(字符缓冲输入流)

:自带8k的字符缓冲池,可以提高输入流读取字符数据的性能

小例子:

public static void main(String[] args) throws Exception {
        try (   //1、创建一个文件字符输入流管道与源文件进行接通
                Reader reader = new FileReader("D:\\Idea文档\\IO\\kj.txt");
                BufferedReader br = new BufferedReader(reader);
        ) {
            char []buffer=new char[3];
            int len;

            while((len=br.read(buffer))!=-1){
                System.out.print(new String(buffer,0,len));
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

readline() 读取一行的内容的方法


BufferedWriter(字符缓冲输出流)

:自带8k的字符缓冲池,可以提高输出流写字符数据的性能

image-20230821152023994.png


IO流---转换流


InputStreamReader(字符输入转换流)

解决 不同编码读取出现乱码的问题

思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不会乱码。

image-20230821172352091.png

OutputStreamWriter(字符输出转换流)(了解)

解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出取得字符就会用该字符集编码了

image-20230822085441590.png


IO流---打印流


作用:实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去

image-20230822091247812.png

image-20230822091324243.png

image-20230824091719152.png

image-20230824091920498.png

打印流的一种应用:输出语句的重定向 setOut把系统默认的打印流对象改成自己设置的位置


序列化流

对象如果需要序列化,必须实现序列化接口!

image-20230824095843495.png transient 修饰成员变量 可以将其不序列化

ArrayList存储多个对象,然后直接对集合进行序列化

ArrayList集合已经实现了序列化接口


IO框架


解决某类问题,编写的一套类、接口等,可以理解为半成品,多数框架由第三方研发

image-20230824102742986.png

image-20230824103457828.png


File文件


File是java.io包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件或者文件夹)

File:代表文本


创建File类的对象方法

image.png

主要都使用第一种方法 后面两种比较少见

下面是一个创建File类的对象的小案例 存储的路径是我设置的 D盘里面的Idea文档里面

 //创建一个File对象,指代某个具体的文件
 //  写路径位置的时候,可以用/ 或者 \\
 File f1=new File("D:\\Idea文档\\Test.txt");
 ystem.*out*.println(f1.length());
 File f2=new File("D:\\Idea文档");
 System.*out*.println(f2.length());

绝对路径与相对路径

绝对路径:带盘符号的,比如C盘 有前缀 C: 等等 注:带盘号一定不要忘记了

相对路径:不带盘符,默认是直接去工程下面去找文件

        //注意:File对象可以指代一个不存在的文件路径
        //exists()可以用于判断目录是否存在
        System.out.println(f2.exists());

        //绝对路径:带盘符号的
        File f4=new File("D:\\Idea文档\\oop\\src\\File_Study\\kj.txt");
		
        System.out.println(f4.getName());
        //相对路径:不带盘符,默认是直接去工程下面去找文件
        File f3=new File("oop\\src\\File_Study/Tes2");
        System.out.println(f4.length());

File提供的判断文件类型、获取文件信息功能

image.png


创建文件和删除文件的常用方法

代码块中有以下四种方法

        //1、public boolean creatNewFile(): 创建一个新文件(文件内容为空),创建成功则返回true,否则反之
        File f1=new File("D:\\Tes1.txt");
        System.out.println(f1.createNewFile());

        //2、public boolean mkdir(): 用于创建一级文件夹
        File f2=new File("D:/a");
        //3、public boolean mkdirs():用于创建文件夹,可以创建多级文件夹
        File f3=new File("D:\\aaa\\bb\\cc");
        System.out.println(f3.mkdirs());
        // public boolean delete():删除文件,或者空文件,注意不能删除非空文件夹
        System.out.println(f1.delete());

遍历文件夹

        // 1、 public  String[] list(): 获取当前目录下所有的一级文件名称到一个字符串数组中去返回
        File f1=new File("D:\\software");
        String[] name = f1.list();
        for (String s : name) {
            System.out.println(s);
        }

        // 2、public File[] listFiles(): 获取当前目录下所有的一级文件对象到一个文件对象数组中去返回
        File [] files =f1.listFiles();
        for (File file : files) {
            System.out.println(file.getAbsoluteFile());
        }

image.png


方法递归 (算是一个先导知识)

直接或者间接的调用自己本身的方法

递归有三个要素


  1. 递归的公式 : f(n)=f(n-1)*n; //这里只是举了个例子 并非公式单一
  2. 递归的一个终结节点 f(1) //这里也只是举个例子 终结点根据具体情况而定
  3. 递归的方向必须是走向终结

特殊文件


properties文件(属性文件)


特点:都只是键对值

键不能重复

文件后缀一般是.properties

Propertise :一个Map集合,但是一般不当集合使用

核心作用:Properties是用来代表属性文件的,通过Properties可以读写属性文件里的内容

image-20230824114820388.png


XML文件(EXtensible Markup Language,可扩展标记语言)


本质:是一种数据结构,可以用来存储复杂的数据结构,和数据关系

image-20230824140139599.png

XML语法规则

image-20230824140656676.png

XML的应用场景:经常用来作为系统的配置文件,或者作为一种特殊的数据结构,在网络中进行传输。

Dom4j是比较好用的解析XML的框架

但是在把数据写入到XML文件中 不用Dom4j框架。 推荐直接把程序里的数据拼接成XML格式,然后用IO流写出去。