IO流

IO流

File流

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

作用:

  • 获取文件的元数据(文件大小,文件类型,文件创建时间等)

  • 判断文件的类型

  • 创建文件/文件夹

  • 删除文件/文件夹

     

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

创建File类的对象

 

 

 

注意

  • File文件既可以代表文件也可以代表文件夹。

  • File封装的对象仅仅是一个路径,这个路径可以是存在的,也可以是不存在的。

     

绝对路径,相对路径

绝对路径:从盘符开始

 

 

 

相对路径:不带盘符,默认直接到当前工程路径下的目录寻找文件

 

 

 

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

 

 

 

代码演示:

//创建3个File对象【绝对路径(文件夹)/绝对路径(文件:存在)/相对路径(文件:不存在)】
        File fOne = new File("G:\\Hello");
        File fTwo = new File("G:\\Hello\\World.txt");
        File fThree = new File("chapter-09-io\\b.txt");
​
//boolean exists:判断调用者File对象表示的内容是否存在
    System.out.println("fTwo是否存在:" + fTwo.exists()); //T
    System.out.println("fThree是否存在:" + fThree.exists()); //F
//boolean isFile/isDirectory:判断调用者File对象表示的内容是否是文件/文件夹 【将结果作为if的判断条件】
    System.out.println("fOne是否是文件:" + fOne.isFile()); //F
    System.out.println("fTwo是否是文件:" + fTwo.isFile()); //T
    System.out.println("fThree是否是文件:" + fThree.isFile()); //F
    System.out.println("fOne是否是文件夹:" + fOne.isDirectory()); //T
    System.out.println("fTwo是否是文件夹:" + fTwo.isDirectory()); //F
    System.out.println("fThree是否是文件夹:" + fThree.isDirectory()); //F
//String getName:获取调用者表示的文件/文件夹的名称【包含后缀的】
    System.out.println("fOne的文件名称是:" + fOne.getName());
    System.out.println("fTwo的文件名称是:" + fTwo.getName());
​
    //long length:获取调用者表示的文件的大小【字节数】 文件夹不允许通过此方法获取内部文件大小
    System.out.println("fTwo的大小[字节数]:" + fTwo.length());
​
    //long lastModified:获取调用者表示的文件最后的修改时间
    long lastModifiedTime = fTwo.lastModified();
    Date lastModifiedDate = new Date(lastModifiedTime);
    System.out.println("fTwo最后的修改时间:" + lastModifiedDate);
​
    //String getPath:获取调用者表示的文件/文件夹创建时的参数路径【创建时传绝对获取绝对 创建时传相对获取相对】
    System.out.println("fTwo的创建时路径是:" + fTwo.getPath());
    System.out.println("fThree的创建时路径是:" + fThree.getPath());
​
    //String getAbsolutePath:获取获取调用者表示的文件/文件夹的绝对路径
    System.out.println("fTwo的绝对路径是:" + fTwo.getAbsolutePath());
    System.out.println("fThree的绝对路径是:" + fThree.getAbsolutePath());
}

 

 

File类创建文件的功能

 

 

 

public class FileDemo3 {
    public static void main(String[] args) throws IOException {
        //创建File对象表示当前模块下的单级不存在文件夹
        File fOne = new File("chapter-09-io\\a");
        //mkdirs:将调用者表示的路径创建为文件夹 【记住这一个方法就足够了】
        fOne.mkdirs();
​
        //创建File对象表示当前模块下的多级不存在文件夹
        File fTwo = new File("chapter-09-io\\a\\b\\c\\d");
        fTwo.mkdirs();
​
        //创建File对象表示当前模块下的不存在文件【路径存在】
        File fThree = new File("chapter-09-io\\美女.jpg");
        //createNewFile:将调用者表示的路径创建为文件
        fThree.createNewFile();
​
        //创建File对象表示当前模块下的不存在文件【路径不存在】如果创建文件,文件的上一级不存在,则会抛出IOException!
        File fFour = new File("chapter-09-io\\z\\z1\\z2\\z3\\z4\\美女.jpg");
        //处理方案:无论路径中是否存在,最终保证都可以创建出来 getParentFile:获取表示父路径的File对象
        File parentFile = fFour.getParentFile();
        parentFile.mkdirs();
        fFour.createNewFile();
    }
}

 

File类删除文件的功能

 

 

 

注意:delete方法默认只能删除文件和空文件夹,删除后的文件不会进入回收站

  public class FileDemo4 {
    public static void main(String[] args) throws IOException {
        //创建File对象表示当前模块下的文件夹
        File fOne = new File("chapter-09-io\\a"); //T
        File fTwo = new File("chapter-09-io\\美女.jpg"); //T
        File fThree = new File("chapter-09-io\\target"); //T 
    //boolean delete:删除调用者File对象表示的文件/文件夹【文件夹必须是空的】
    fOne.delete(); //a不是空文件夹所以无法删除
    fTwo.delete();
    fThree.delete();
}
}

 

File类提供的遍历文件夹的功能

 

 

 

    public class FileDemo5 {
    public static void main(String[] args) {
        File fOne = new File("G:\\a.txt");
    //File listFiles:将调用者File对象表示的文件夹下的所有一级内容【直系内容】,每一个内容都封装为一个File对象,放到File数组中返回。
    //如果调用者文件夹中有直系内容,则数组长度不为0,如果没有直系内容,则数组长度为0,【如果调用者表示的是一个文件,则方法方法不会报错!但是返回的数组是NULL值】
    File[] fileArray = fOne.listFiles();
    Arrays.stream(fileArray).forEach(file -> {
        System.out.println(file.getAbsolutePath());
        System.out.println(file.getName());
    });
}
}

 

使用listFiles方法时的注意事项:

  • 当主调是文件,或者路径不存在时,返回nulll。

  • 当主调是空文件时,放回一个长度为0的数组。

  • 当主调是一个有内容的文件夹时,将里面所有的一级文件和文件夹的路径放在File数组中返回。

  • 当主调是一个文价夹,且里面有隐藏文件时,将里面所有文件和问价夹的路径放在File数组中返回,包含隐藏文件

  • 当主调是一个文件夹,但是没有权限访问该文件夹时,返回null。

方法递归

什么是方法递归?

  • 递归是一种算法,在程序设计语言中广泛应用。

  • 从形式上说:方法调用自身的形式称为方法递归( recursion)。

递归的形式

  • 直接递归:方法自己调用自己。

  • 间接递归:方法调用其他方法,其他方法又回调方法自己。

使用方法递归时需要注意的问题:

  • 递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出错误(Exception in thread "main" java.lang.StackOverflowError)。

递归算法总结:

  • 递归的公式:f(n) = f(n-1) * n;

  • 递归的终结点:f(1)

  • 递归的方向必须走向终结点

案例:利用递归算法进行文件搜索

需求:从C:盘中,搜索“QQ.exe” 这个文件,找到后直接输出其位置。

分析

①先找出C:盘下的所有一级文件对象

②遍历全部一级文件对象,判断是否是文件

③如果是文件,判断是否是自己想要的

④如果是文件夹,需要继续进入到该文件夹,重复上述过程

public class RecursionDemo3 {
​
    //(1)查找指定文件 (2)统计文件夹大小 (3)统计文件夹文件个数 (4)作业:统计文件夹中不同类型文件的个数 HashMap<类型,个数>
    private static final File TARGET_DIRECTORY = new File("D:\\");
    private static final String TARGET_FILE_NAME = "QQ.exe"; //指定文件
    private static Long fileLengthSum = 0L;
    private static Integer fileCount = 0;
​
    public static void main(String[] args) {
        findFile(TARGET_DIRECTORY);
        getFileLengthSum(TARGET_DIRECTORY);
        getFileCount(TARGET_DIRECTORY);
        System.out.println(TARGET_DIRECTORY + "中所有文件的总大小是:" + fileLengthSum + "字节!");
        System.out.println(TARGET_DIRECTORY + "中所有文件的总数量是:" + fileCount + "个!");
    }
​
    //定义一个方法,方法可以用于统计指定File对象表示的文件中所有文件的个数
    public static void getFileCount(File targetDirectory) {
        //(1)获取参数File对象表示的文件夹下的所有一级文件对象组成的数组
        File[] fileArray = targetDirectory.listFiles();
        if (fileArray == null) {
            return;
        }
        //(2)遍历fileArray获取到每一个一级文件,判断一级文件是否是一个文件
        for (File targetFile : fileArray) {
            if (targetFile.isFile())
                fileCount++;
            else
                getFileCount(targetFile);
        }
    }
​
    //定义一个方法,方法可以用于统计指定File对象表示的文件中所有文件的总大小
    public static void getFileLengthSum(File targetDirectory) {
        //(1)获取参数File对象表示的文件夹下的所有一级文件对象组成的数组
        File[] fileArray = targetDirectory.listFiles();
        if (Objects.isNull(fileArray)) {
            return;
        }
        //(2)遍历fileArray获取到每一个一级文件,判断一级文件是否是一个文件
        for (File targetFile : fileArray) {
            if (targetFile.isFile())
                fileLengthSum += targetFile.length();
            else
                getFileLengthSum(targetFile);
        }
    }
​
​
    //定义一个方法,可以去指定File对象表示的文件夹中查询指定的文件路径 参数:File directory
    public static void findFile(File targetDirectory) {
        //(1)获取参数File对象表示的文件夹下的所有一级文件对象组成的数组
        File[] fileArray = targetDirectory.listFiles();
        //编写原因:盘符有系统自带的隐藏文件夹【会出现一些错误的情况 可能会导致返回的一级文件数组为NULL】
        if (Objects.isNull(fileArray)) {
            return;
        }
        //(2)遍历fileArray获取到每一个一级文件,判断一级文件是否是一个文件
        for (File targetFile : fileArray) {
            if (targetFile.isFile() && targetFile.getName().equals(TARGET_FILE_NAME)) {
                System.out.println("找到了目标文件" + TARGET_FILE_NAME + "地址在:" + targetFile.getAbsolutePath());
            } else {
                //如果一级文件不是一个文件,而是一个文件夹【目标文件】,继续递归调用findFile方法,将targetFile作为参数传递
                findFile(targetFile);
            }
        }
    }
}
​

 

Java代码完成对字符的编码

 

 

 

Java代码完成对字符的解码

 

 

 

public class CodeDemo1 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        //getBytes:按照UTF-8对调用者内容进行编码 【基于String字符串】
        byte[] bytesOne = "我爱你".getBytes();
        System.out.println(Arrays.toString(bytesOne));
​
        //getBytes:按照GBK对调用者内容进行编码
        byte[] bytesTwo = "我恨你".getBytes("GBK");
        System.out.println(Arrays.toString(bytesTwo));
​
        //String(byte[] bytes):基于UTF-8对参数数组进行解码 【基于String字符串的构造方法】
        String strOne = new String(bytesTwo);
        System.out.println("strOne:" + strOne);
​
        //String(byte[] bytes,String charsetName):基于指定字符集对参数数组进行解码 【基于String字符串的构造方法】
        String strTwo = new String(bytesTwo, "GBK");
        System.out.println("strTwo:" + strTwo);
​
        //明确结论:如何编码就如何进行解码
        String strThree = new String("  ".getBytes(),"GBK");
        System.out.println(strThree);
    }
}

 

认识IO流

输入输出流,是用来读写数据的

  • I是指Input,称为输入流:负责把数据读到内存中去

  • O是指Output,称为输出流:负责把数据从内存中写出去

IO流的分类

 

 

 

IO流总体来看就有四大流

字节输入流 字节输出流 字符输入流 字符输出流

  • 字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流。

  • 字节输出流:以内存为基准,把内存中的数据以字节的形式写出到磁盘文件或者网络中去的流。

  • 字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流。

  • 字符输出流:以内存为基准,把内存中的数据以字符的形式写出到磁盘文件或者网络介质中去的流。

IO流的体系

 

 

 

IO字节流

FilenputStream(文件字节输入流)

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

 

 

 

 

   public class InputStreamDemo1 {
    public static void main(String[] args) throws Exception{
        //封装File对象用于和文件字节输入流进行绑定读取
        File targetFile = new File("chapter-09-io\\a.txt");
   
   //创建文件字节输入流FileInputStream并且将要读取的文件的File对象作为参数传递
    FileInputStream fis = new FileInputStream(targetFile);
    System.out.println("[fis]:" + fis);
​
    //创建文件字节输入流FileInputStream并且将要读取的文件的路径作为参数传递【不需要封装File直接传递路径也可以】
    FileInputStream fisTwo = new FileInputStream("chapter-09-io\\a.txt");
    System.out.println("[fisTwo]:" + fisTwo);
​
    //注意事项(1):既然要绑定文件读文件,文件必须得存在[java.io.FileNotFoundException: chapter-09-io\b.txt (系统找不到指定的文件。)]
    FileInputStream fisThree = new FileInputStream("chapter-09-io\\b.txt");
​
    //★注意事项(2):任何输入流绑定的只能是文件,不能是文件夹[chapter-09-io\target (拒绝访问。)]
    FileInputStream fisFour = new FileInputStream("chapter-09-io\\target");
}
}

 

注意事项:

  1. 既然要绑定文件读文件,文件必须得存在。不然会报[java.io.FileNotFoundException: chapter-09-io\b.txt (系统找不到指定的文件。)]

  2. 任何输入流绑定的只能是文件,不能是文件夹

    [chapter-09-io\target (拒绝访问。)]

     

  3. 使用FileInputStream每次读取一个字节,读取性能较差,并且读取汉字输出会乱码。

     

 

 

 

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

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

2,每次读取一个字节数组有什么好处? 存在什么问题?

  • 读取的性能得到了提升

  • 读取中文字符并输出仍然存在乱码问题

文件字节输入流:一次读取完全部字节

方式一:自己定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节。

 

 

 

   public class InputStreamDemo3 {
    public static void main(String[] args) throws Exception {
        //封装File对象用于和文件字节输入流进行绑定读取
        File targetFile = new File("chapter-09-io\\a.txt");
        FileInputStream fis = new FileInputStream(targetFile);
   //int read(byte[] bytes) : 一次尝试读取一个字节数组的数据【字节数组的长度是多少就会尝试读取几个字节】
    //返回值int:本次读取到的有效字节数
    byte[] bytes = new byte[3]; //准备byte[]数组用于保存每次读取到的数据
    int len; //用于保存每次读取到的有效字节数
    while ((len = fis.read(bytes)) != -1) {
        //可以基于String提供的一个方法,new String(byte[] bytes,int off,int len):将参数一数组中从off索引开始进行解码,解码len个
        String str = new String(bytes, 0, len);
        System.out.println(str);
    }
     //END:释放流资源
    fis.close();
}
}

 

方式二:Java官方为InputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回。

 

 

 

   public class InputStreamDemo4 {
    public static void main(String[] args) throws Exception {
        //封装File对象用于和文件字节输入流进行绑定读取
        File targetFile = new File("chapter-09-io\\a.txt");
        FileInputStream fis = new FileInputStream(targetFile); 
    //byte[] readAllByte:将文件中的所有内容读取到一个字节数组中返回 弊端:如果文件过大,则数组也会过大!
    byte[] bytes = fis.readAllBytes();
    String str = new String(bytes);
    System.out.println(str);
​
    //END:释放流资源
    fis.close();
}
}

 

弊端:byte[] readAllByte:将文件中的所有内容读取到一个字节数组中返回 弊端:如果文件过大,则数组也会过大!可能引起内存溢出。

小总结:读写文本内容使用字符流更好

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

FileOutputStream(文件字节输出流)

 

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

 

 

 

 2     public class OutputStreamDemo1 {
 3     public static void main(String[] args) throws FileNotFoundException {
 4         //基于FileOutStream写数据绑定文件【特点:(1)文件可以是不存在的!如果文件不存在,自动创建出来!】
 5         FileOutputStream fos = new FileOutputStream(new File("chapter-09-io\\b.txt"));
 6         //【特点:(2)如果文件是存在的,那么绑定文件之后,默认会清空文件中的所有内容】
 7     //如果说想要基于绑定文件的原有内容的基础上继续写入内容【不想让原有内容清空】
 8     FileOutputStream fosTwo = new FileOutputStream(new File("chapter-09-io\\c.txt"), true);
 9 }
10 }

 

 

特点:

  1. 基于FileOutStream写数据绑定文件【特点:(1)文件可以是不存在的!如果文件不存在,自动创建出来!

  2. 如果文件是存在的,那么绑定文件之后,默认会清空文件中的所有内容

字节输出流写数据的方法

 

 

 

 

 1     public class OutputStreamDemo2 {
 2     public static void main(String[] args) throws Exception {
 3         FileOutputStream fos = new FileOutputStream(new File("chapter-09-io\\b.txt"));
 4     //write(int c):写一个字节
 5     fos.write('a'); //'a' char -> int 【根据码表中对应的码点】
 6     fos.write('b');
 7     fos.write('c');
 8     //fos.write('我'); //× 一次只能写一个字节.[3个字节]
 9 10     //write(byte[] bytes):写一个字节数组 【可以基于String类型的字符串调用getBytes方法将要写入的内容先转换字节数组(中文)】
11     //会和输入流的方法搭配起来进行使用
12     String str = "HelloWorld 你好,世界!";
13     byte[] bytes = str.getBytes();
14     fos.write(bytes);
15 16     //write(byte[] bytes,int off,int len):写一个字节数组的一部分 从off索引开始写,写len个元素【不是写到len索引】
17     //会和输入流的方法搭配起来进行使用
18     fos.write(bytes, 0, 5);
19 20     fos.write("\r\n换行了吗?".getBytes());
21 22     fos.close();
23 }
24 }

 

文件复制

 

 

 

 1    
 2    public class CopyDemo3 {
 3     public static void main(String[] args) {
 4         //(1)准备源文件与目标文件
 5         File srcFile = new File("C:\\Users\\SHINIAN\\Pictures\\坤坤.jpg");
 6         File targetFile = new File("chapter-09-io\\iKun.jpg"); 
 7     //(2)创建文件字节输入流【绑定源文件】 / 创建文件字节输出流【绑定目标文件】
 8     //Jdk7:try-with-resource的写法可以所有流资源的声明放在try的()中,当try的代码/catch的代码执行完了,会自动对流进行释放。
 9     //try()中只需要声明实现了AutoCloseable接口的实现类资源
10     try (FileInputStream fis = new FileInputStream(srcFile);
11          FileOutputStream fos = new FileOutputStream(targetFile)) {
12         //(3)准备byte数组用于保存每次读取到的内容,再声明一个int类型len用于保存每次读取到的有效字节数【避免脏数据】
13         byte[] bytes = new byte[1024];
14         int len;
15         //(4)使用字节输入流循环读取源文件内容,如果读取到的源文件的有效内容,则通过字节输出流写出到目标文件.
16         while ((len = fis.read(bytes)) != -1) {
17             fos.write(bytes, 0, len); //必须从0索引开始写,写len个有效数据。【就有可能在最后一次出现脏数据被写入】
18         }
19     } catch (IOException e) {
20         e.printStackTrace();
21     }
22 }
23 }

 

IO字符流

FileReader(文件字符输入流)

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

 

 

 

 

 1     public class ReaderDemo1 {
 2     public static void main(String[] args) throws IOException {
 3         //封装要读取的文件File对象【读取文件:必须存在】
 4         File targetFile = new File("chapter-10-io\\出师表.txt");
 5     //创建FileReader文件字符输入流对象并且传递要读取的文件
 6     try (FileReader fr = new FileReader(targetFile)) {
 7         //方式(2):int read(char[] chars):一次尝试读取一个字符数组的数据,将读取到的内容保存到字符数组参数中,并且返回读取到的有效字符数,返回-1读取到了末尾.
 8         char[] chars = new char[1024];
 9         int len; //用于保存每次读取的有效字符数
10         while ((len = fr.read(chars)) != -1) {
11             //基于String类的构造方法将char[]数组作为参数传递,自动将数组中的内容转换为一个字符串,还可以传递从哪个索引开始转换,转换多少个元素
12             String str = new String(chars, 0, len);
13             System.out.print(str);
14         }
15     }
16 }
17 18 private static void readByOneChar(File targetFile) throws IOException {
19     //创建FileReader文件字符输入流对象并且传递要读取的文件
20     try (FileReader fr = new FileReader(targetFile)) {
21         //方式(1):int read:将读取到的完整字符作为返回值返回,返回-1读到了末尾
22         int i; //保存每次读取到的字符
23         while ((i = fr.read()) != -1) {
24             System.out.print((char) i);
25         }
26     }
27 }
28 }

 

1.使用文件字符输入流,有什么好处?

可以避免读取中文乱码问题

2.每次读取一个字符,每次读取多个字符的方法是什么?它们各有什么特点?

 

 

 

 

FileWriter(文件字符输出流)

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

 

 

 

 

 

 

 

 

 1     public class WriterDemo1 {
 2     public static void main(String[] args) throws IOException {
 3         //声明目标文件【写:存在与否均可】 存在:清空 不存在:创建 字符流用于操作文本文件
 4         File targetFile = new File("chapter-10-io\\info.txt");
 5     //创建文件字符输出流【指定为默认模式:清空/创建】
 6     FileWriter fw = new FileWriter(targetFile);
 7     //write(int i):一个写一个字符数据 【char->int 直接传递字符常量】
 8     fw.write('a');
 9     fw.write('0');
10     fw.write('我');
11     //如果想要马上将缓冲区的数据写入到文件中,可以刷新flush【不建议write一次就刷新一次(保证流被释放)】
12     fw.flush();
13 14     //write(String str):一次写一个字符串
15     String str = "今天天气不错,风和日丽,适合出去钓鱼!";
16     fw.write(str);
17 18     //write(String str,int off,int len):一个写一个字符串一部分
19     fw.write(str, 2, 4);
20 21     //write(char[] chars):一次写一个字符数组
22     char[] chars = new char[]{'1', 'i', 'a', '我'};
23     fw.write(chars);
24 25     //write(char[] chars,int off,int len):一次写一个字符数组的一部分
26     fw.write(chars, 2, 2);
27     fw.close();
28 }
29 }

 

注意事项:

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

     

 

 

★IO缓存流

 

 

 

缓存流:对原始流经行包装,以调高原始流读写数据的性能。

原理:自己缓存输入流和字节缓存输出流自带8kb缓存池。

 

 

 

 

BufferedInputStream(字节缓存输入流)

BufferedOutputStream(字节缓存输出流)

1.字节缓冲流如何使用?

  • public BufferedOutputStream(OutputStream os)

  • public BufferedInputStream(InputStream is)

  • 功能上并无很大变化,性能提升了。

BufferedReader(字符缓存输入流)

BufferedWriter(字符缓存输出流)

 

 

 

 

 

 

 

字符缓存输入流新增的功能:按照行读取字符

 

 

 

 

 

 

 

1.两种字符缓冲流如何使用?各自新增了什么功能?

  • public BufferedReade (Reader r)

  • 性能提升了,多了readLine()按照行读取的功能

  • public BufferedWriter(Writer w)

  • 性能提升了,多了newLine()换行的功能

 

★IO转换流

InputStreamReader(字符输入转换流)

自定义字符编码方式:

 

 

需求:基于GBK的方式将a.txt中的内容解码读取出来 "GBK"

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

  
 1    public class ReaderDemo2 {
 2     public static void main(String[] args) throws IOException {
 3         //需求:基于GBK的方式将a.txt中的内容解码读取出来 "GBK"
 4         //InputStreamReader(InputStream is,String charset):基于传递绑定文件的原始字节流与字符集名称创建字符输入转换流
 5         try (InputStreamReader isr = new InputStreamReader(new FileInputStream(new File("chapter-10-io\\a.txt")), "GBK")) {
 6             //基于isr按照GBK的方式解码文件中的内容 【按照实际的字符集的字节个数来读取内容进行解码】
 7             int i = isr.read();
 8             System.out.println((char) i);  
 9         i = isr.read();
10         System.out.println((char) i);
11     }
12 13     //只有按照指定的字符集对文本文件进行解码的时候才需要使用InputStreamReader,如果默认的解码方式是UTF-8【使用FileReader】
14 }
15 }

 

OutputStreamWriter(字符输出转换流)

 

 

需求:按照GBK的字符集将文本内容写入到文件中【FileWriter ×(UTF-8)】

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

 

 1 public class WriterDemo2 {
 2     public static void main(String[] args) throws IOException {
 3         //需求:按照GBK的字符集将文本内容写入到文件中【FileWriter ×(UTF-8)】
 4         //OutputStreamWriter(OutputStream os,String charsetName):根据传递原始字节输出流和字符集名称创建字符输出转换流
 5         try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(new File("chapter-10-io\\target.txt")), "GBK")) {
 6             //OutputStreamWriter可以使用的成员方法就是字符输出流的写数据的方法.
 7             osw.write("HelloWorld 你好世界!");
 8         }
 9     }
10 }
11  

 

IO打印流

 

 

PrintStream/PrintWriter(打印流)

作用:打印流可以更方便、更高效的把数据打印出去,能实现将指定的内容原封不动地打印出去的功能。

PrintStream提供的答应数据的方案

 

 

PrintWriter提供的打印数据的方案

 

 

PrintStream和PrintWriter的区别

  • 打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)

  • PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。

  • PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。

打印流的一种应用:输出语句的重定向

可以把输出语句的打印位置改到某个文件中去。

 

 

IO数据流

 

 

DataOuputStream(数据输出流)

允许把数据和其他类型一并写出去

 

 

DataInputStream(数据输入流)

用于读取数据输出流写出去的数据

 

 

 

IO序列化流

 

 

ObjectOutputStream(对象字节输出流)

作用:可以把Java对象进行序列化:把Java对象存入到文件夹中去。

注意:对象如果要参与序列化,必须实现序列化接口(Java.io.Serializable)

 

 

ObjectInputStream(对象字节输入流)

作用:可以把Java对象反序列化:把存储在文件中的Java对象读入到内存中来。

 

 

如果要一次序列化多个对象,怎么办?

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

注意:ArrayList集合已经实现了序列化接口!

 

IO框架

Commons-io

Commons-io是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率。

使用步骤

①从官网下载commons-io的jar包:https://commons.apache.org/proper/commons-io/download_io.cgi

②在项目中创建一个文件夹:lib

③将第一步解压后的commons-io-2.11.0.jar文件复制到lib文件夹中

④在jar文件上点右键,选择 Add as Library -> 点击OK

⑤在类中导包使用

FileUtils类提供的部分方法展示

 

 

 
posted @ 2023-03-06 17:09  好学的耀耀  阅读(111)  评论(0编辑  收藏  举报