IO流的笔记(一)

为什么要学习IO流:
    之前保存数据使集合或数组, 集合用或数组保存在内存中的.内存一旦断点,就没有了.(内存是临时性存储)
    ArrayList<String> list = new ArrayList();
    list.add("张三");
    list.add("李四");
    如果想将数据永久存储.可以存储在文件中.
    通过IO流我们可以将数据写入到文件中,也可以将文件中的数据读取到程序中

IO流的分类:
    按照流向:
        输入流:将文件的内容读取到程序中
        输出流:通过程序往文件中写入内容

    按操作的类型:
        计算机存储任何数据都是使用二进制 0,1
        什么是字节? 8个二进制位就是一个字节.字节是计算机的最小存储单元
        视频,音频,图片,文字...全都是二进制,都是以字节位单位

        字节流:
            操作的单位是字节,可以操作任何类型的文件(叼)

        字符流: 操作的单位是字符(方便操作文字的)

IO流的顶级父类:
                    字节流                             字符流
    输入流      InputStream                            Reader
                字节输入流                           字符输入流

    输出流     OutputStream                            Writer
                字节输出流                           字符输出流

    特点:这四个类都是抽象类

首先下列的就是字节输入流

字节输出流父类OutputStream抽象类
OutputStream:
    void write​(int b) 将一个字节写入文件中(一次性写一个)
    void write​(byte[] b) 将一个字节数组写入文件中(一次性写多个)
    void write​(byte[] b, int off, int len) 将字节数组的一部分写入文件中(一次性写多个)

当操作结束是,一定要关闭文件close

子类FileOutputStream:
    构造方法:
        FileOutputStream​(String name) 通过文件的路径名创建FileOutputStream​对象
            文件不存在,会创建文件,文件存在会删除,创建新的文件.并且会打开对应的文件
        FileOutputStream​(File file) 通过File对象创建FileOutputStream​对象

1.1    写入文件一个字节

File file = new File("路径/abc/2.txt");
FileOutputStream fos = new FileOutputStream(file);

// 写输入到文件void write​(int b) 将一个字节写入文件中
fos.write(97); // 97是一个字节

1.2    写入文件一个数组

 FileOutputStream fos = new FileOutputStream("路径/abc/3.txt");
        //             0   1   2    3   4
        byte[] buf = {97, 98, 99, 100, 101};
        // void write​(byte[] b) 将一个字节数组写入文件中(一次性写多个)
        fos.write(buf);
        // void write​(byte[] b, int off, int len) 将字节数组的一部分写入文件中(一次性写多个)
        // int off: 从哪个位置开始
        // int len: 写多少个
        fos.write(buf, 2, 3);
        // 现在没有关闭文件
//        while (true) {
//            Thread.sleep(1000);
//        }
        // 必须要做的
        fos.close();

FileOutputStream​(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream​(String name, boolean append) 创建文件输出流以指定的名称写入文件。

当append设置为true时,会追加写入,在windows中: "\r\n"表示换行

FileOutputStream fos = new FileOutputStream("../12.txt", true);

byte[] bytes = "\r\n".getBytes();
fos.write(bytes);
fos.write(65);

fos.close();

字节输入流

InputStream: 输入字节流
    int read​() 从输入流读取数据的下一个字节。
    int read​(byte[] b) 从输入流中读取一些字节数,将读取到内容保存byte数组中。

子类FileInputStream:
    FileInputStream​(String name) 通过文件的路径字符串创建FileInputStream​对象.
    FileInputStream​(File file) 通过File对象创建FileInputStream​对象.
    创建FileInputStream​对象时,会打开这个文件.相当于有一根管子连接到文件

注意:如果文件不存在会报错:FileNotFoundException(系统找不到指定的文件)

读取一个字节

FileInputStream fis = new FileInputStream("路径\\abc\\a.txt");
// 使用循环,次数不确定使用while循环

int ch; // 表示读取到的数据
// 1.执行fis.read()读取到数据
// 2.将读取到的数据赋值给ch
// 3.拿ch和-1进行比较,当ch=-1跳出循环
while ((ch = fis.read()) != -1) {
    System.out.print((char) ch);
}

fis.close();

转型      byte[]转String使用哪个方法?      byte[] buff=new byte[]{97,98,99};            String string=new String(buff);

String转byte[]使用哪个方法?                String str = "你好,约吗?";           byte[] buf = str.getBytes();

读取字节数组

1.FileInputStream一次一个字节数组的数据使用哪个方法?
    int read(byte[] b)

2.如何循环读取一个字节的数组?
    byte[] buf = new byte[1024 * 4];
    int len;
    while ((len = fis.read(buf)) != -1) {
        System.out.println(new String(buf, 0, len));
    }

3.一次读取一个字节数组的好处?
    读取文件是耗时的操作(IO操作是耗时的)
    读取一个字节的方式,读取的次数很多.效率低
    读取字节数组的方式,读取的次数减少.效率高

FileInputStream fis = new FileInputStream("路径/abc/b.txt");
// 使用循环:终止条件读取到的长度等于-1就结束了
byte[] buf = new byte[1024];
int len;
// 1.fis.read(buf),调用read方法,将读取的内容保存到buf数组中
// 2.将read返回值赋值给len,读取内容的长度
// 3.让len和-1比较
while ((len = fis.read(buf)) != -1) {
    System.out.println(new String(buf, 0, len));
}

fis.close();

复制一张图片

 FileInputStream fis = new FileInputStream("路径/abc/xyz.png");
        FileOutputStream fos = new FileOutputStream("c:/MyFileTest/xyz22.png");

        // 复制一个字节数组的方式
        byte[] buf = new byte[1024];
        int len;
        while ((len = fis.read(buf)) != -1) {
            fos.write(buf, 0, len);
        }

        fos.close();
        fis.close();
关闭资源(先开的后关)

字节流读取文字不方便,所以下列就介绍方便读取文字内容的流--------字符流

Reader: 字符输入的父类
    int read​() 读一个字符
    int read​(char[] cbuf) 读取多个字符保存在char数组中

子类FileReader:从文件中读入字符数据
    FileReader​(String fileName) 创建一个新的 FileReader ,给定要读取的文件的名称。
    FileReader​(File file) 创建一个新的 FileReader ,给出 File读取。

FileReader fr2 = new FileReader(new File("f:/e.txt"));
char[] chs = new char[1024];//[]里面可以是乘以1024的整数倍,一般最大为8倍
int len;
while ((len = fr2.read(chs)) != -1) {
    System.out.println(new String(chs, 0, len));       
}

fr2.close();

/ 字符流write时内容并没有写入到文件,而是将内容写入到字符流的缓冲区
        // 只有刷新缓冲区,内容才会到文件中
        // flush和close的区别:
        //      flush刷新缓冲区后,可以接着再写内容 (保存)
        //      close后不能再写内容,close也会刷新缓冲区 (关闭)
//        fw.flush();
//        fw.write("约吗?");
//        fw.flush();

        fw.close(); // 关闭流, 刷新缓冲区.

一旦关闭了输入流就不可以再继续write内容,程序报错

IO异常的处理

分为JDK7之前和JDK7之后的内容不同

JDK7以前的:
        FileReader fr = null;
        try {
            fr = new FileReader("路径/abc/e.txt");

            int ch = fr.read();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // null不能去调用方法
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    System.out.println("关闭流失败...");
                }
            }
        }

    JDK7的处理方式:
        try (FileReader fr = new FileReader("路径/abc/e.txt");
            FileWriter fw = new FileWriter("路径/abc/eee.txt")
        ) {
            int ch = fr.read();
            System.out.println(ch);
        } catch (FileNotFoundException e) {
            System.out.println("文件没有找到");
        } catch (IOException e) {
            System.out.println("IO异常");
        }

JDK7以前的


    1.创建FileReader会有异常
    2.try...catch处理异常
    3.IO流一定要关闭,在finally里面关闭流
    4.发现fr作用域不够,将fr在外面声明
    5.如果路径不存在fr是null,null不能调用方法
    6.在finally中先判断fr不是null,才去调用close方法
    7.fr.read()有异常,多添加一个异常分支

Properties类:


    我们发现Properties实现了Map接口,是一个集合,存储键值对的数据,可以理解为Map接口的一样使用
    Properties的每键值都是一个字符串
    Properties内的数据可以很方便的保存到文件中

Properties类特有方法:
    getProperty​(String key) 获取数据。
    setProperty​(String key, String value) 添加数据。

 // 创建Properties
        Properties pp = new Properties();

        // 保存数据
        // setProperty​(String key, String value) 添加数据。
        pp.setProperty("name", "唐僧");
//        pp.setProperty("name", "唐僧222");
        pp.setProperty("age", "20");
        pp.setProperty("address", "东土大唐");
        System.out.println(pp);

        // 获取数据
        // getProperty​(String key) 获取数据。
        String age = pp.getProperty("age");
        String name = pp.getProperty("name");

        System.out.println(name + ":" + age);

        System.out.println("--------");
        // 键找值遍历:
        // Set<String> stringPropertyNames​(): 获取所有的键
        Set<String> keys = pp.stringPropertyNames();
        // 遍历所有的键获取每个键
        for (String key : keys) {
            // 通过一个键,找到一个对应值
            String value = pp.getProperty(key);
            System.out.println(key + "::" + value);
        }
 Properties特有方法:
        void store​(OutputStream out, String comments): 将Properties中的数据保存到流中
        void load​(InputStream inStream): 将文件中的数据读取到Properties对象中

小结:
    1.将Properties集合数据写入流中使用哪个方法?

    2.将文件中的数据读取到Properties中使用哪个方法?
 */
public class Demo092 {
    public static void main(String[] args) throws IOException {
//        testStore();
        testLoad();
    }

    // 将文件中的数据读取到Properties对象中
    public static void testLoad() throws IOException {
        Properties pp = new Properties();
        System.out.println(pp);
        FileInputStream fis = new FileInputStream("day09_课堂代码/abc/info.properties");
        pp.load(fis);
        System.out.println(pp); // {password=6666, name=张三, age=18}
    }

    // 将Properties中的内容保存到文件
    public static void testStore() throws IOException {
        Properties pp = new Properties();
        pp.setProperty("name", "张三");
        pp.setProperty("password", "123456");

        // void store​(OutputStream out, String comments): 将Properties中的数据保存到流中
        FileOutputStream fos = new FileOutputStream("day09_课堂代码/abc/info.properties");
        pp.store(fos, "这是Properties中的内容");
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40932406/article/details/87884658