字符流、IO资源异常处理、Properties集合、ResourceBundle工具类,打印流

时间:2021-08-17作者:klpeng分类:Java技术浏览:114评论:0

字符流

使用字节输入流去读包含中文的文件

/*
    使用字节输入流读取含有中文的文件
        文件的编码GBK:一个中文占用2个字节
        文件的编码UTF-8:一个中文占用3个字节
 */
public class Demo01FileInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("day15\\c.txt");//你好
        int len = 0;
        while ((len = fis.read())!=-1){
            System.out.print((char)len);//ä½ å¥½ 一次读取一个字节(1/3个中文),把中文的1/3转换为字符,乱码
        }
        fis.close();
    }
}

字符输入流

java.io.Reader:字符输入流
用于读取字符流的抽象类。
是所有字符输入流最顶层的父类,里边定义了所有字符输入流共性的成员方法,所有的字符输入流都可以使用
共性的成员方法:
- public void close() :关闭此流并释放与此流相关联的任何系统资源。
- public int read(): 从输入流读取一个字符。
- public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。
java.io.FileReader:文件字符输入流 extends InputStreamReader(转换流) extends Reader
作用:
把文件以字符的方式读取到内存中
构造方法:
FileReader(File file)
FileReader(String fileName)
参数:传递要读取的数据源
File file:数据源是一个文件
String fileName:数据源是一个文件路径

/*
    使用字符输入流读取文件的步骤(重点):
        1.创建FileReader对象,构造方法中绑定要读取的数据源
        2.使用FileReader对象中的方法read,以字符的方式读取文件
        3.释放资源
    String类的构造方法:
        String(char[] value) 把字符数组转换为字符串
        String(char[] value, int offset, int count) 把字符数组的一部分转换为字符串
                int offset:数组的开始索引
                int count:转换个数
 */
public class Demo02Reader {
    public static void main(String[] args) throws IOException {
        //1.创建FileReader对象,构造方法中绑定要读取的数据源
        FileReader fr = new FileReader("day15\\c.txt");
        //2.使用FileReader对象中的方法read,以字符的方式读取文件
        //public int read() 一次读取一个字符并返回
        /*int len = 0;
        while ((len = fr.read())!=-1){
            System.out.print((char)len);
        }*/

        //public int read(char[] cbuf)使用字符数组缓冲一次读取多个字符
        char[] chars = new char[1024];
        int len = 0;
        while ((len =fr.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }

        //3.释放资源
        fr.close();
    }
}

字符输出流

java.io.Writer:字符输出流
写入字符流的抽象类。
是所有字符输出流最顶层的父类,里边定义字符输出流共性的成员方法,所有的字符输出流都可以使用
共性的成员方法:
- public abstract void close() :关闭此输出流并释放与此流相关联的任何系统资源。
- public abstract void flush() :刷新此输出流并强制任何缓冲的输出字符被写出。
- public void write(int c) :写出一个字符。
- public void write(char[] cbuf):将cbuf.length字符从指定的字符数组写出此输出流。
- public abstract void write(char[] b, int off, int len) :从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。
- public void write(String str) :写出一个字符串。
- void write(String str, int off, int len) 写入字符串的某一部分。
java.io.FileWriter:文件字符输出流 extends OutputStreamWriter(转换流) extends Writer
作用: 把内存中的字符,写入到文件中
构造方法:
FileWriter(File file)
FileWriter(String fileName)
参数:写入数据的目的地
File file:目的地是一个文件
String fileName:目的地是一个文件路径
构造方法的作用:
1.创建FileWriter对象
2.会根据构造方法中传递的文件|文件的路径,创建一个新的空白的文件
3.会把FileWriter对象,指向空白的文件

/*
    使用字符输出流基本步骤(重点):
        1.创建FileWriter对象,构造方法中绑定写入数据的目的地
        2.使用FileWriter对象中的方法write,把数据写入到内存缓冲区中(字符-->字节)
        3.使用FileWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中
        4.释放资源(会先调用flush方法,把内存缓冲区中的数据刷新到文件中)
 */
public class Demo01Writer {
    public static void main(String[] args) throws IOException {
        //1.创建FileWriter对象,构造方法中绑定写入数据的目的地
        FileWriter fw = new FileWriter("day15\\d.txt");
        //2.使用FileWriter对象中的方法write,把数据写入到内存缓冲区中(字符-->字节)
        //- public void write(int c) :写出一个字符。
        fw.write(100);
        //3.使用FileWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中
        //fw.flush();
        //4.释放资源(会先调用flush方法,把内存缓冲区中的数据刷新到文件中)
        fw.close();
    }
}

关闭和刷新的区别

/*
    关闭和刷新的区别
        - flush :刷新缓冲区,把内存缓冲区中的数据刷新到文件中,刷新完后,流对象可以继续使用。
        - close :关闭流,释放系统资源。关闭前会刷新缓冲区。把内存缓冲区中的数据刷新到文件中,流关闭之后就不能在使用了
     问题:
        1.程序执行完毕e.txt中有什么? ABC
        2.程序的执行会抛出异常吗? 会
 */
public class Demo02Writer {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("day15\\e.txt");
        fw.write(65);//A
        fw.write(66);//B
        fw.flush();//把内存缓冲区中的数据刷新到文件中,刷新完后,流对象可以继续使用
        fw.write(67);//C
        fw.close();//把内存缓冲区中的数据刷新到文件中,流关闭之后就不能在使用了
        fw.write(68);//D  抛出异常  IOException: Stream closed
    }
}

字符输出流写数据的其他方法

/*
    字符输出流写数据的其他方法:
        - public void write(char[] cbuf):将 b.length字符从指定的字符数组写出此输出流。
        - public abstract void write(char[] b, int off, int len) :从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。
        - public void write(String str) :写出一个字符串。
        - void write(String str, int off, int len) 写入字符串的某一部分。
 */
public class Demo03Writer {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("day15\\f.txt");

        //- public void write(char[] cbuf) 写字符数组中的多个字符
        char[] chars = {'a','b','c','1','2','3','中','国'};
        fw.write(chars);//abc123中国

        /*
            - public abstract void write(char[] b, int off, int len) 写字符数组的一部分
                int off:数组的开始索引
                int len:写的个数
         */
        fw.write(chars,6,2);//中国

        //- public void write(String str) :写出一个字符串。
        fw.write("我是一个中国人,我骄傲!");

        //- void write(String str, int off, int len) 写入字符串的某一部分。
        fw.write("我是一个中国人,我骄傲!",0,7);

        fw.close();
    }
}

字符输出流的续写和换行

/*
    字符输出流的续写和换行
        1.续写(追加写):使用两个参数的构造方法
            FileWriter(File file, boolean append)
            FileWriter(String fileName, boolean append)
            参数:
                File file,String fileName:写入数据的目的地
                boolean append:续写开关
                    true:可以续写,使用构造方法创建对象,不会覆盖之前的文件,会往文件的末尾继续写数据
                    false:不可以续写,使用构造方法创建对象,会创建一个新的空白文件,覆盖之前的文件,在新的文件中写数据
        2.换行:使用换行符号
            windows:\r\n
            linux: /n
            mac: /r  从Mac OS X开始与linux统一
 */
public class Demo04Writer {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("day15\\g.txt",true);
        for (int i = 1; i <= 10; i++) {
            fw.write("hello"+i+"\r\n");
        }
        fw.close();
    }
}

IO资源的处理

jdk7前异常处理

/*
    JDK7前异常处理:使用try...catch...finally处理异常
    格式:
        try{
            可能产生异常的代码
        }catch(定义一个异常变量,接收异常对象){
            异常的处理逻辑
        }finally{
            一定会执行的代码,一般用于资源释放
        }
    添加语句的快捷键: ctrl+alt+t
 */
public class Demo01JDK7Before {
    public static void main(String[] args) {
        /*
            把fis.close();放在finally中:无论是否有异常,都 释放资源
            Cannot resolve symbol 'fis':提高变量的作用域
            Variable 'fis' might not have been initialized:变量fis没有一个初始化的值
         */
        FileInputStream fis= null;
        try {
            //使用FileInputStream读取文件
            fis = new FileInputStream("day15\\1.txt");
            int len = 0;
            while ((len = fis.read())!=-1){
                System.out.println((char)len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //增加一个非空判断,防止空指针异常,流对象的值是null,就不需要关闭
            if(fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

JDK7后异常处理(重点)

/*
    JDK7后异常处理:使用try...catch处理异常
    格式:
        try(
            //定义流对象,只能定义流对象
            AAA aaa = new AAA(读);
            BBB bbb = new BBB(写);
        ){
            //可能产生异常的代码
            aaa.read();
            bbb.write();
        }catch(定会一个异常变量,接收异常对象){
            异常的处理逻辑
        }
   在try的后边增加一个(),在()中定义了流对象
   那么这些流对象的作用域,就在try中有效,执行完try中的代码,会自动帮助我们把流对象释放
   省略了finally
 */
public class Demo02JDK7After {
    public static void main(String[] args) {
       try(
               FileInputStream fis = new FileInputStream("day15\\a.txt");
               FileOutputStream fos = new FileOutputStream("day15\\copya.txt");
       ){
            //一读一写复制文件
           byte[] bytes = new byte[1024];
           int len = 0;
           while ((len = fis.read(bytes))!=-1){
               fos.write(bytes,0,len);
           }
       }catch (Exception e){
           e.printStackTrace();
       }
    }
}

Properties集合(重点)

Properties集合的基本使用

/*
    java.util.Properties集合 extends Hashtable<k,v>集合
    Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
        Properties集合是一个唯一和IO流相结合的集合
        我们可以使用Properties集合中的方法store,把集合中的临时数据,持久化到硬盘中存储(内存-->硬盘)
        我们可以使用Properties集合中的方法load,把硬盘中保存键值对的文件,读取到内存中使用(硬盘-->内存)

    属性列表中每个键及其对应值都是一个字符串。
        Properties集合是一个双列集合,可以不用写泛型,默认key和value都是String类型
 */
public class Demo01Properties {
    public static void main(String[] args) {
        show01();
    }

    /*
        Properties集合的基本使用:使用Properties集合存储数据,遍历Properties集合
        Properties集合健和值默认都是String类型,有一些和String相关的特有方法
            Object setProperty(String key, String value)  往Properties集合中添加元素,相当于Map集合中的put方法
            String getProperty(String key)  根据key获取value,相当于Map集合中的get(key)方法
            Set<String> stringPropertyNames() 返回此属性列表中的键集,相当于Map集合中的keySet方法
     */
    private static void show01() {
        //创建Properties集合对象
        Properties prop = new Properties();
        //使用Properties集合中的方法setProperty往集合中添加键值对
        prop.setProperty("迪丽热巴","168");
        prop.setProperty("古力娜扎","165");
        prop.setProperty("赵丽颖","160");
        prop.setProperty("唐嫣","172");
        //使用Properties集合中的方法stringPropertyNames,获取集合中所有的键,把键存储到一个Set集合中
        Set<String> set = prop.stringPropertyNames();
        //遍历Set集合,获取Properties集合中的每一个key
        for (String key : set) {
            //使用Properties集合中的方法getProperty,根据key获取value值
            String value = prop.getProperty(key);
            System.out.println(key+"\t"+value);
        }
    }
}

Properties集合中的store方法

/*
    我们可以使用Properties集合中的方法store,把集合中的临时数据,持久化到硬盘中存储(内存-->硬盘)
        void store(OutputStream out, String comments)
        void store(Writer writer, String comments)
        方法的参数:
            OutputStream out:字节输出流,不能写中文,可以传递OutputStream任意子类对象
            Writer writer:字符输出流,可以写中文,可以传递Writer任意子类对象
            String comments:注释,解释说明我们保持的文件是做什么的,一般都传递""
                不能写中文,默认使用Unicode编码,会出现乱码
   使用步骤:
        1.创建Properties集合对象,往集合中添加数据
        2.使用Properties集合中的方法store,把集合中的临时数据,持久化到硬盘中存储
 */
private static void show02() throws IOException {
    //1.创建Properties集合对象,往集合中添加数据
    Properties prop = new Properties();
    prop.setProperty("迪丽热巴","168");
    prop.setProperty("古力娜扎","165");
    prop.setProperty("赵丽颖","160");
    prop.setProperty("唐嫣","172");
    //2.使用Properties集合中的方法store,把集合中的临时数据,持久化到硬盘中存储
    /*FileOutputStream fos = new FileOutputStream("day15\\prop1.txt");
    prop.store(fos,"save data");
    fos.close();*/
    prop.store(new FileOutputStream("day15\\prop1.txt"),"save data");
    prop.store(new FileWriter("day15\\prop2.txt"),"save data");
    //使用的存储键值对的文件,叫配置文件,结尾一般都使用properties
    prop.store(new FileWriter("day15\\prop.properties"),"save data");
}

Properties集合中的load方法

/*
    我们可以使用Properties集合中的方法load,把硬盘中保存键值对的文件,读取到内存中使用(硬盘-->内存)
        void load(InputStream inStream) 字节输入流,不能读取含有中文的文件
        void load(Reader reader)  字符输入流,可以读取含有中文的文件
    使用步骤:
        1.创建Properties集合对象
        2.使用Properties集合对象中的方法load,把硬盘中保存键值对的文件,读取到内存中使用
        3.遍历Properties集合
    注意:
        1.在Properties集合的配置文件中,可以使用#进行注释,被注释的键值对不会被读取
        2.在Properties集合的配置文件中,健和值之间可以使用=,空格,冒号等一些符号作为键与值的分割符号
        3.在Properties集合的配置文件中,健和值默认都是字符串类型,不需要添加引号,否则会画蛇添足
 */
private static void show03() throws IOException {
    //1.创建Properties集合对象
    Properties prop = new Properties();
    //2.使用Properties集合对象中的方法load,把硬盘中保存键值对的文件,读取到内存中使用
    //prop.load(new FileInputStream("day15\\prop.properties"));
    prop.load(new FileReader("day15\\prop.properties"));
    //3.遍历Properties集合
    Set<String> set = prop.stringPropertyNames();
    for (String key : set) {
        String value = prop.getProperty(key);
        System.out.println(key+"\t"+value);
    }
}

ResourceBundle工具类(重点)

前面我们了解了Properties工具类,它能够读取资源文件,当资源文件是以.properties结尾的文件时,

我们可以使用JDK提供的另外一个工具类ResourceBundle来对文件进行读取,使得操作更加简单。

ResourceBundle类对象的创建

/*
    java.util.ResourceBundle:工具类
    作用:
        可以简化使用Properties集合中load方法读取文件
    ResourceBundle它是一个抽象类,无法直接创建对象,我们可以使用静态方法获取ResourceBundle的子类对象
        static ResourceBundle getBundle(String baseName)
        参数:
            String baseName:传递以.properties文件的名称 prop.properties==>prop
            注意:
                  .properties文件必须放在当前模块的src下边
 */
public class Demo01ResourceBundle {
    public static void main(String[] args) {
        //getBundle方法返回的是ResourceBundle的子类对象  ResourceBundle(父类) 变量 = PropertyResourceBundle(子类对象)
        //多态
        ResourceBundle prop = ResourceBundle.getBundle("prop");
        System.out.println(prop);//java.util.PropertyResourceBundle@74a14482
    }
}

ResourceBundle类中的getString方法

/*
    ResourceBundle类中提供了一个方法getString,用于读取配置文件
        String getString(String key)  根据key读取配置文件中的value值
    注意:
        使用ResourceBundle读取配置文件的时候,key不能是中文,不支持,会抛出异常
        使用ResourceBundle读取配置文件的时候,value可以使用中文,但是读取出来会出现乱码
 */
public class Demo02ResourceBundle {
    public static void main(String[] args) {
        //获取ResourceBundle对象
        ResourceBundle bundle = ResourceBundle.getBundle("prop");
        //使用ResourceBundle对象中的方法getString,根据key获取value值
        String v1 = bundle.getString("tangyan");
        System.out.println("v1:"+v1);
        System.out.println("----------------------------------");
        ResourceBundle bundle2 = ResourceBundle.getBundle("data");
        String username = bundle2.getString("username");
        System.out.println(username);
        String password = bundle2.getString("password");
        System.out.println(password);
    }
}

打印流

/*
    java.io.PrintStream:字节打印流 extends OutputStream
    特点:
        1.PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
            PrintStream流中有两个特有的方法:print,println
        2.与其他输出流不同,PrintStream 永远不会抛出 IOException,可能会抛出其他异常
        3.PrintStream打印流,只负责打印(输出),不能读取
    构造方法:
        PrintStream(File file) 打印流的目的地是一个文件
        PrintStream(OutputStream out)打印流的目的地是一个字节输出流
        PrintStream(String fileName) 打印流的目的地是是一个文件的路径
    成员方法:
        1.继承自父类OutputStream的共性成员方法:write方法写数据,查看的时候,会查询编码表
            - public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
            - public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
            - public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
            - public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
            - public abstract void write(int b) :将指定的字节输出流。
        2.自己特有的方法:print,println写的数据,原样输出
            void print(Object obj)  可以写任意类型的数据,不换行
            void println(Object x)  可以写任意类型的数据,换行
 */

基本使用

/*
    使用步骤(重点):
        1.创建PrintStream对象,构造方法中绑定要输出的目的地
        2.使用PrintStream对象中的方法write,print,println,把数据写入到文件中
        3.释放资源
 */
public class Demo01PrintStream {
    public static void main(String[] args) throws FileNotFoundException {
        //System.out.println(97);//a
        //1.创建PrintStream对象,构造方法中绑定要输出的目的地
        PrintStream ps = new PrintStream("day15\\1.txt");
        //2.使用PrintStream对象中的方法write,print,println,把数据写入到文件中
        //继承自父类OutputStream的共性成员方法:write方法写数据,查看的时候,会查询编码表
        ps.write(97);//a

        //自己特有的方法:print,println写的数据,原样输出
        ps.println(97);//97
        ps.println('@');//97
        ps.println(true);//97
        ps.println(1.1);//97
        ps.println("aaa");//97

        //3.释放资源
        ps.close();
    }
}

修改输出语句的目的地为打印流的目的地

/*
    使用System类中的方法setOut可以修改输出语句的目的地
        static void setOut(PrintStream out)  参数传递打印流对象,把输出语句的目的地由控制台改成打印流的目的地
 */
public class Demo02PrintStream {
    public static void main(String[] args) throws FileNotFoundException {
        System.out.println("输出语句的目的地是在控制台输出!");

        //创建打印流对象
        PrintStream ps = new PrintStream("day15\\2.txt");
        System.setOut(ps);//把输出语句的目的地由控制台改成打印流的目的地

        System.out.println("输出语句的内容写到PrintStream的目的地2.txt中");
    }
}

总结

字符流和字节流的区别

1.字节流读取的和写入都是字节;字符流读取的和写入的都是字符

2.所有的数据(文本,音乐,视频,图片…),都是以字节的方式存储的,使用字节流可以读写任意的文件

3.使用字节流读取的文件中包含中文,如果一次读取一个字节(1/2GBK,1/3UTF-8个中文),使用起来不方便

4.使用字符流读取含有中文文本文件,一次读取一个字符(中文,英文,数字,符号…),使用起来很方便

什么时候使用字符流:读写文本文件(使用记事本打开能看懂)

什么时候使用字节流:读写非文本文件(图片,视频,音频…)

打赏
文章版权声明:除非注明,否则均为彭超的博客原创文章,转载或复制请以超链接形式并注明出处。
相关推荐

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

猜你喜欢