Java-字节流、字符流、IO异常处理、属性集

一、字节流、

1、IO流的顶层父类

    字节流

        字节输出流: OutputStream

        字节输入流: InputStream

    字符流

        字符输出流: Writer

        字符输入流: Reader 

注意:IO流的顶层父类全是抽象类。

 

2、OutputStream 是字节输出流。 可以将Java程序中的数据写入到硬盘(文件)中。(以字节为单位)

    OutputStream 是所有字节输出流的顶层父类, 是一个抽象类, 要使用它的子类, 最常用的子类FileOutputStream

    FileOutputStream的构造方法

        FileOutputStream(File file): 参数需要传递一个File类型的文件。

        FileOutputStream(String name):参数需要传递一个字符串类型的文件路径

    其他成员方法:

        void write(int b):将一个字节写入到文件中

        void write(byte[] b):将整个的字节数组写入到文件中

        void write(byte[] b, int off, int len): 将字节数组的一部分写入到文件中。 参数off表示起始位置, 参数len表示个数.

        void close():关闭流, 释放资源

    步骤:

        1. 创建FileOutputStream对象, 并且传递一个文件路径

        2. 调用write方法,向文件中写数据。

        3. 调用close方法,释放资源

 

    注意:在java中一个字符占两个字节,但是如果这个字符是ASCII码表上的字符,那么在操作系统中是占一个字节的。

    所以可以使用一次写一个字节的方式写入到文件中。

 

    中文在操作系统中如果采用的是GBK编码,那么占两个字节,如果采用的是UTF-8编码,那么占三个字节。

    中文是占多个字节,所以不能采用一次写一个字节的方式写入中文

 

public class Demo02OutputStream {

    public static void main(String[] args) throws IOException {

        //创建FileOutputStream对象, 指定一个目的地

        /*

            创建对象代码做了以下三个事情

            1. 调用系统资源,在d盘下创建一个文件file01.txt。 如果文件已经存在,那么就会覆盖掉原来的文件。

            2. 会创建一个FileOutputStream字节输出流对象

            3. 将这个文件绑定到这个字节输出流对象上,以后通过这个对象操作的就是这个文件了。

         */

        OutputStream os = new FileOutputStream("day09\\file01.txt");

 

        //调用write方法,向文件中写数据。

        //void write(int b):将一个字节写入到文件中

        os.write(100); //d  因为100对应的ASCII码字符是d

        //os.write('a');

        //os.write('中');

 

        //调用close释放资源。 会解除资源被占用的问题

        os.close();

 

        //如果不释放资源,那么如果程序不结束,会导致这个文件一直处于被占用状态。

        while(true) {

 

        }

 

    }

}

3、 字符串 -> 字节数组

        byte[] getBytes(): 将字符串使用平台默认的编码(IDEA默认编码UTF-8)方式转成字节数组。

    字节数组 -> 字符串

        String(byte[] bytes): 将整个的字节数组转成一个字符串

        String(byte[] bytes, int offset, int length): 将字节数组的一部分转成字符串。 从offset位置开始转, 转length个

 

public class Demo03Parse {

    public static void main(String[] args) {

        //字符串 -> 字节数组

        String s1 = "abcde";

        byte[] bArr1 = s1.getBytes();

        System.out.println("bArr1:" + Arrays.toString(bArr1)); // [97, 98, 99, 100, 101]

 

        String s2 = "中国";

        byte[] bArr2 = s2.getBytes();

        System.out.println("bArr2:" + Arrays.toString(bArr2)); //[-28, -72, -83, -27, -101, -67]

 

        System.out.println("------------------------------");

 

        //字节数组 -> 字符串

        String str1 = new String(bArr1);

        System.out.println("str1:" + str1); //abcde

 

        //将字节数组的一部分转成字符串

        String str2 = new String(bArr1, 1, 3);

        System.out.println("str2:" + str2); //bcd

    }

}

4、使用字节输出流一次写入一个字节数组。

        void write(byte[] b):将整个的字节数组写入到文件中

        void write(byte[] b, int off, int len): 将字节数组的一部分写入到文件中。 参数off表示起始位置, 参数len表示个数.

 

 

public class Demo04OutputStream {

    public static void main(String[] args) throws IOException {

        //1. 创建FileOutputStream,指定一个目的地

        OutputStream os = new FileOutputStream("d:\\file02.txt");

        //2. 调用write方法,写数据

        //定义字节数组

        //byte[] bArr = "中文".getBytes();

        //os.write(bArr);

 

        //写入字节输入的一部分

        byte[] bArr = "abcde".getBytes();

        os.write(bArr, 1, 3); //bcd

 

        //3. 调用close方法,释放资源

        os.close();

    }

}

5、 字节输出流的追加写

 

    如果要续写,使用另一个构造方法创建FileOutputStream对象即可

    FileOutputStream(File file, boolean append): 第一个参数表示要写入到哪个文件, 第二个参数表示是否续写,如果为true表示续写

    FileOutputStream(String name, boolean append):第一个参数表示要写入到哪个文件, 第二个参数表示是否续写,如果为true表示续写

 

 

public class Demo05AppendWrite {

    public static void main(String[] args) throws IOException {

        //创建字节输出流,绑定一个目的地

        OutputStream os = new FileOutputStream("d:\\file02.txt", true);//true表示要续写,追加写

        //向文件中写入一句诗

        os.write("举头望明月".getBytes());

        //释放资源

        os.close();

    }

}

7、 换行写

        如果要实现换行效果,那么需要使用换行符

        window: \r\n

        linux: \n

        macOs: \r

 

public class Demo06WriteLine {

    public static void main(String[] args) throws IOException {

        //创建一个字节输出流绑定目的地

        OutputStream os = new FileOutputStream("d:\\file03.txt");

        //调用write方法,向文件中写入两句诗

        os.write("白日依山尽\r\n".getBytes());

        os.write("黄河入海流".getBytes());

 

        //释放资源

        os.close();

    }

}

二、字节输入流

1、InputStream表示字节输入流, 可以将文件中的数据读取到Java程序中。(以字节为单位)

    InputStream是所有字节输入流的顶层父类, 是一个抽象类, 如果要用需要使用子类,最常用子类: FileInputStream

    FileInputStream构造方法:

        FileInputStream(File file): 传递一个File类型的文件, 表示要从这个文件中读取数据。

        FileInputStream(String name):传递一个字符串类型的文件路径, 表示要从这个文件中读取数据。

 

    其他的成员方法:

        int read():读取一个字节并返回。 如果读取结束,返回-1

        int read(byte[] b): 读取一个字节数组,返回读取到的有效个数。 如果读取结束,返回值为-1.

    使用步骤:

        1. 创建字节输入流对象, 绑定一个数据源。

        2. 调用read方法,进行读取

        3. 释放资源.

 

    一次读取一个字节的方式不能读取中文,因为中文占多个字节.

 

public class Demo01InputStream {

    public static void main(String[] args) throws IOException {

        //1. 创建字节输入流对象, 绑定一个数据源。

        //创建字节输入流对象的时候如果文件不存在,那么就会抛出异常。

        InputStream is = new FileInputStream("day09\\source01.txt");

 

        //2. 调用read方法,从文件中一次读取一个字节数据

        //使用循环读取

 

        //定义一个变量,用来接收读取到的字节

        int i;

        //定义循环,开始读取

        while((i = is.read()) != -1) {

            /*

                条件位置做了三个事情

                1. 调用read方法读取了一个字节

                2. 把读取到的字节赋值给了变量i

                3. 判断变量i不等于-1吗,如果不等于-1表示读取到了数据,那么就在大括号中进行处理。

             */

            System.out.print((char)i);

        }

 

        /*

        int i = is.read(); //read方法会读取到一个字节,并且把这个字节返回赋值给变量i

        System.out.println(i);//97

 

        //继续读

        i = is.read();

        System.out.println(i);//98

 

        //还读

        i = is.read();

        System.out.println(i);//99

 

        //接着读

        i = is.read();

        System.out.println(i);//-1

        */

 

        //3. 释放资源

        is.close();

 

    }

}

2、使用字节输入流一次读取一个字节数组

 

            int read(byte[] b): 读取一个字节数组,返回读取到的有效个数。 如果读取结束,返回值                为-1.

    这种方式读取中文也会有问题

 

public class Demo02InputStream {

    public static void main(String[] args) throws IOException {

        //创建一个字节输入流,用来读取

        InputStream is = new FileInputStream("day09\\source.txt");

 

 

        //使用循环,一次读取一个字节数组

        //定义一个字节数组,用来保存读取到的字节。

        byte[] bArr = new byte[1024]; //这个数组的大小一般是1024的整数倍,最快1024 * 8

        //定义变量len,用来保存每次读取到的字节个数.

        int len;

        //定义while循环,开始读取

        while((len = is.read(bArr)) != -1) {

            /*

                条件做了哪些事情:

                    1. 通过输入流调用read方法,进行读取,并且把读取到的数据放入到了参数bArr数组中

                    2. 返回读取到的字节个数,并且把这个个数赋值给变量len。

                    3. 判断len是否不等于-1,如果不等于-1,那么表示读取到了内容,那么就可以对读取到的内容进行处理。

 

                读取到的字节保存到了bArr数组中。   返回值为读取到的个数。

             */

            //读取到了几个内容,就把字节数组中的几个元素转成字符串,然后再打印

            System.out.print(new String(bArr, 0, len));

        }

 

        /*

        //调用read方法,一次读取一个字节数组

        byte[] bArr = new byte[2];

 

        //通过输入流进行读取,将数据读取到了bArr这个字节数组中。

        //数组的长度是几,那么就最多一次读取几个。

        //这个方法返回值为读取到的有效个数.

        int len = is.read(bArr);

        System.out.println(new String(bArr, 0, len)); //97 98

        System.out.println(len); // 2

 

        //接着读

        len = is.read(bArr);

        System.out.println(new String(bArr, 0, len));//99 100

        System.out.println(len); // 2

 

        //接着读

        len = is.read(bArr);

        System.out.println(new String(bArr, 0, len));//101 100

        System.out.println(len); // 1

 

        //接着读

        len = is.read(bArr);

        System.out.println(new String(bArr));//101 100

        System.out.println(len); //-1

    `

        */

        is.close();

 

 

    }

}

3、 文件复制。

    文件复制本质就是文件的读写。

    读取源文件中的字节,每读取一次,就把读取到的字节写入到目的地文件中。

    步骤:

        1. 创建字节输入流,用来读取。

        2. 创建字节输出流,用来写入。

        3. 使用字节输入流读取源文件中的字节,一次读取一个字节数组。

        4. 将读取到的字节数组写入到目的地中。

        5. 释放资源

 

public class Demo03CopyTest {

    public static void main(String[] args) throws IOException {

        //创建字节输入流,用来读取。

        InputStream is = new FileInputStream("day09\\aa.jpg");

        //创建字节输出流,用来写入

        OutputStream os = new FileOutputStream("day09\\bb.jpg");

        //使用字节输入流读取源文件中的字节,一次读取一个字节数组。

 

        //定义一个字节数组,用来保存读取到的字节

        byte[] bArr = new byte[1024];

        int len;

        //开始读取,每读取到一个字节数组,就将这个字节数组写入到目的地文件中

        while ((len = is.read(bArr)) != -1) {

            //把读取到的内容写入到目的地文件

            os.write(bArr, 0, len); //读取到几个内容,那么就写几个内容

        }

 

        //释放资源

        os.close();

        is.close();

    }

}

 

4、 Reader是字符输入流, 可以将文件中的数据读取到Java程序中。 (以字符为单位)

    Reader是字符输入流的顶层父类, 是一个抽象类。 如果要用,需要使用子类。

    最常用的子类是: FileReader

    FileReader构造方法:

        FileReader(File file):参数需要一个File类型的文件

        FileReader(String fileName):参数需要一个字符串类型的文件路径

    其他方法:

        int read(): 一次读取一个字符. 读取结束返回-1.

        int read(char[] cbuf):一次读取一个字符数组。 将读取出来的数据保存在字符数组中,返回值为读取到的个数。 如果读取结束返回-1

    字符输入流使用步骤:

        1. 创建

        2. 读取

3. 释放

 

public class Demo01Reader {

    public static void main(String[] args) throws IOException {

        //创建字符输入流对象

        Reader r = new FileReader("day09\\source02.txt");

        //读取

 

        //int read(): 一次读取一个字符.

        /*

        int i; //定义变量,表示读取到的每一个字符

        //开始读取

        while((i = r.read()) != -1) {

            System.out.print((char)i);

        }

        */

 

        //int read(char[] cbuf):一次读取一个字符数组。 将读取出来的数据保存在字符数组中,返回值为读取到的个数。 如果读取结束返回-1

        //定义一个字符数组,用来保存读取到的数据

        char[] cArr = new char[2];

        //len用来接收读到的长度

        int len;

        //使用循环进行读取

        while ((len = r.read(cArr)) != -1) {

            //将读取到的内容进行打印, 读取到了几个人内容,就把几个内容打印

            System.out.print(new String(cArr, 0, len));

        }

 

 

 

        //释放资源

        r.close();

    }

}

三、字符输出流

    

1、字符输出流 Writer, 可以将Java程序中的数据写入到文件中。(以字符为单位)

    Writer 是所有字符输出流的顶层父类, 如果要用需要使用子类。 常用子类FileWriter

    FileWriter 构造方法:

        FileWriter(File file): 参数需要File类型的文件。

        FileWriter(String fileName): 需要传递String类型的文件路径。

    其他方法:

        void write(String str): 向文件中写入一个字符串。

        void flush(): 刷新流。 将内存缓冲区中的数据刷新到文件中

        void close(): 关闭流

    字符输出流的使用步骤:

        1. 创建字符输出流对象, 绑定一个目的地

        2. 调用write方法,向文件中写入数据

        3. 刷新。 (只有 [字符][输出]流,才需要刷新)

        4. 释放资源

 

public class Demo01FileWriter {

    public static void main(String[] args) throws IOException {

        //创建FileWriter对象

        Writer w = new FileWriter("day09\\file01.txt");

        //调用write方法,写一个字符串

        w.write("你好"); //并没有将数据直接写入到文件中,而是放到了内存中的字符缓冲区。

 

        //如果要把内存缓冲区中的数据放入到文件中,需要刷新。

        w.flush();

        //释放资源

        w.close();

 

    }

}

 

2、字符输出流中的其他写的方法

    void write(char[] cbuf): 向文件中写入字符数组。

    void write(char[] cbuf, int off, int len):向文件中写入字符数组的一部分。 从off 开始写, 写len个

    void write(int c):写一个字符数据

    void write(String str): 写入一个字符串

    void write(String str, int off, int len): 写入字符串的一部分

    字节流一般处理非文本文件: 图片, MP3, 视频

    字符流用于处理文本文件: 使用windows默认记事本打开能够看得懂的就是文本文件。

 

public class Demo02FileWriter {

    public static void main(String[] args) throws IOException {

        //创建一个字符输出流对象

        FileWriter fw = new FileWriter("day09\\file02.txt");

        //调用write方法,写入

 

        //void write(char[] cbuf): 向文件中写入字符数组。

        //char[] cArr = {'h', 'e', 'l', 'l', 'o'};

        //fw.write(cArr);

 

        //void write(char[] cbuf, int off, int len):向文件中写入字符数组的一部分。

        //char[] cArr = {'h', 'e', 'l', 'l', 'o'};

        //fw.write(cArr, 1, 3);

 

        //void write(int c):写一个字符数据

        //fw.write(100); //d

 

        //void write(String str): 写入一个字符串

        //fw.write("你好");

 

        //void write(String str, int off, int len): 写入字符串的一部分

        fw.write("你好吗今天", 1, 3);

 

        //刷新

        fw.flush();

        //关闭

        fw.close();

 

    }

}

 

3、字符输出流中刷新方法和关闭方法的区别

 

            flash: 刷新。 仅仅是做的刷新操作。 流刷新之后还可以使用

    close: 关闭。 先刷新,然后关闭流  流关闭之后就不能使用了

 

public class Demo03FlushAndClose {

    public static void main(String[] args) throws IOException {

        //创建字符输出流

        Writer w = new FileWriter("day09\\file03.txt");

        //调用write方法,写数据

        w.write("你好");

        w.flush();

        w.write("我好");

 

        //释放资源

        w.close();

 

        w.write("大家好"); //java.io.IOException: Stream closed

    }

}

 

四、IO中的异常处理

1、IO流中的异常处理(JDK7之前的处理方式)

            流创建出来之后无论如何都一定要关闭。

    所以要把close关闭流的代码放在finally代码块

 

public class Demo01Exception {

    public static void main(String[] args)  {

        Writer w = null;

        try {

            w = new FileWriter("day09\\file04.txt");

            w.write("你好");

        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            try {

                //非空判断,如果w不是null,那么表示这个输出流对象已经创建了,那么才释放资源

                if(w != null) {

                    w.close();

                }

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

 

    }

}

2、 在JDK7的时候,多了一种异常的处理方式, try...with...resource。其实就是一种特殊的try...catch语句

    格式

        try(创建流对象的代码) {

            //操作语句

        } catch(要捕获的异常 变量名) {

 

        }

    try...with...resource 语句的作用是 ,在小括号中创建的对象,无论如何都会调用它的close方法。

    并且这个close方法不需要我们自己去调用,系统会自动帮我们去调用

 

public class Demo02Exception {

    public static void main(String[] args) {

        try(Writer fw = new FileWriter("day09\\file05.txt"); ) {

            fw.write("你好");

        } catch (IOException e) {

            System.out.println("出现异常啦");

        }

    }

}

3、  jdk9 try...with...resource的优化

 

public class Demo04Exception {

    public static void main(String[] args) throws IOException {

        //创建FileWriter对象

        Writer w = new FileWriter("day09\\file06.txt");

 

        try(w) {

            w.write("你好");

        } catch (Exception e) {

 

        }

    }

}

 

五、属性集(properties)

1、Properties的概念:

    Properties是一个双列集合, 是Hashtable的子类。

    Properties的特点:

        1. Properties实现了Map接口。 所以拥有Map接口中的所有的功能。

        2. 这个集合没有泛型,键和值都是String

        3. 这个集合支持对流的操作。 可以从流中加载键值对。

 

    常见方法:

        (常用)Object setProperty(String key, String value): 将键值对添加到Properties集合

       (常用)String getProperty(String key): 根据键获取对应的值。

        Set<String> stringPropertyNames():获取Properties集合中所有的key放入到Set集合返回.

 

public class Demo01Properties {

    public static void main(String[] args) {

        //创建一个Properties集合

        Properties p = new Properties();

        //调用setProperty方法,添加键值对

        p.setProperty("it001", "王宝强");

        p.setProperty("it002", "贾乃亮");

        p.setProperty("it003", "陈羽凡");

 

        System.out.println("p:" + p);

 

        //根据key获取指定的value

        System.out.println(p.getProperty("it002"));

        System.out.println("=========================");

 

        // Set<String> stringPropertyNames():获取Properties集合中所有的key放入到Set集合返回.

        Set<String> set = p.stringPropertyNames();

        //遍历这个set集合,获取每一个键,根据键获取Properties集合的值

        for(String key : set) {

            String value = p.getProperty(key);

            System.out.println(key + "--" + value);

        }

    }

}

 

2、Properties与流相关的方法

    void load(InputStream inStream): 参数需要传递一个字节输入流。

    void load(Reader reader): 参数需要传递一个字符输入流。 

    load方法中需要传递一个输入流, 这个输入流会绑定一个文件, load方法可以从该文件中读取键值对。

    文件要求:

        1. 文件一般以.properties结尾(软性规定)

        2. 里面的键值对存储方式必须按照规则 (硬性规定)

            键=值

            键=值

            键=值

            ...

    步骤:

        1. 创建一个输入流对象,绑定一个文件。

        2. 创建Properties集合对象

        3. 调用load方法,传递输入流,就可以将文件中的键值对加载到Properties集合中

        4. 释放流的资源

 

public class Demo02Properties {

    public static void main(String[] args) throws IOException {

        //创建一个输入流对象,绑定一个文件。

        InputStream is = new FileInputStream("day09\\config.properties");

        //创建Properties集合对象

        Properties p = new Properties();

        //调用load方法,就可以将文件中的键值对加载到Properties集合中

        p.load(is);

        //释放流的资源

        is.close();

 

        //打印Properties集合

        System.out.println(p);

    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值