IO流、常见输入输出流区别、内存缓冲区、 IO异常的处理、 Properties

本文详细介绍了Java中的IO流,包括字节流和字符流的使用,以及FileInputStream和FileReader的区别。同时,文章讲解了FileOutputStream和FileWriter在写入文件时的步骤,强调了flush和close方法的区别。此外,文章还深入探讨了Properties类,如何使用它来读取和存储键值对,以及处理中文字符的问题。内容涵盖了异常处理、文件读写以及Properties集合的操作方法。

一、IO概念

IO流就是联系硬盘跟内存的,分为字节流和字符流在这里插入图片描述

1.1 文件存储的原理和记事本打开文件的原理

在这里插入图片描述

UTF-8三个字节表示一个汉字,而GBK两个字节表示一个汉字
在文件中显示100,要写3个字节,一个数字代表一个字节

1.2常见输入输出流区别( 4个)

1.字节输入流和字符输入流使用步骤差别不大(硬盘–>内存(java程序输出到控制台上))

  • FileInputStream字节输入流使用步骤:

1.创建FileInputStream对象,构造方法中绑定要读取的数据源
2.使用FileInputStream对象中的方法read,读取文件
3.释放资源

  • FileReader字符输入流使用步骤:

1.创建FileReader对象,构造方法中绑定要读取的数据源
2.使用FileReader对象中的方法read读取文件
3.释放资源

2.FileOutputStream和 FileWriter有差别的(内存(java程序写)–>硬盘)

  • .FileOutputStream字节输出流使用步骤:

1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
2.调用FileOutputStream对象中的方法write,把数据写入到文件中
3.释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)

  • FileWriter字符输出流使用步骤:
    1.创建FileWriter对象,构造方法中绑定要写入数据的目的地
    2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
    3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中(如果后面没有close则一定要flush刷新到缓冲区保存!!!
    4.释放资源(会先把内存缓冲区中的数据刷新到文件中)(就是你不使用flush只使用close是可以的

区别:FileOutputstream是直接写进文件(直接write就行,不close也行);而FileWriter这个write完后,一定要使用flush或者close不然写不了),这个是先写到内存缓冲区再刷新到内存中去。

总体来说:FileWriter可以直接写入字符串进硬盘,而FileOutputstream要先转为字节数组再写入硬盘(相对麻烦),而且中文会乱码。所以还是字符流不会中文乱码(只有中文在utf-8不会乱码,在GBK还是会乱码的,得用转换流),比较香。

1.3 flush和close区别

  • flush :刷新缓冲区,流对象可以继续使用
  • close: 先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了(再用就报异常)。
import java.io.FileWriter;
import java.io.IOException;
public class Demo02CloseAndFlush {
    public static void main(String[] args) throws IOException {
        //1.创建FileWriter对象,构造方法中绑定要写入数据的目的地
        FileWriter fw = new FileWriter("09_IOAndProperties\\e.txt");
        //2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
        //void write(int c) 写入单个字符。
        fw.write(97);
        //3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
        fw.flush();
        //刷新之后流可以继续使用
        fw.write(98);
        //4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
        fw.close();
        //close方法之后流已经关闭了,已经从内存中消失了,流就不能再使用了
        //fw.write(99);//IOException: Stream closed
    }
}

1.4 IO异常的处理

局部变量(在main中也是局部变量)在定义的时候,可以没有值,但是使用的时候必须有值(定义为null)
null是不能调用方法的,会抛出NullPointerException,需要增加一个判断,不是null再把资源释放

import java.io.FileWriter;
import java.io.IOException;

/*
    在jdk1.7之前使用try catch finally 处理流中的异常
    格式:
        try{
            可能会产出异常的代码
        }catch(异常类变量 变量名){
            异常的处理逻辑
        }finally{
            一定会指定的代码
            资源释放
        }
 */
public class Demo01TryCatch {
    public static void main(String[] args) {
        //提高变量fw的作用域,让finally可以使用
        //变量在定义的时候,可以没有值,但是使用的时候必须有值
        //fw = new FileWriter("09_IOAndProperties\\g.txt",true); 执行失败,fw没有值,fw.close会报错
        FileWriter fw = null;
        try{
            //可能会产出异常的代码
            fw = new FileWriter("w:\\09_IOAndProperties\\g.txt",true);
            for (int i = 0; i <10 ; i++) {
                fw.write("HelloWorld"+i+"\r\n");
            }
        }catch(IOException e){
            //异常的处理逻辑
            System.out.println(e);
        }finally {
            //一定会指定的代码
            //创建对象失败了,fw的默认值就是null,null是不能调用方法的,会抛出NullPointerException,需要增加一个判断,不是null在把资源释放,这样好点,不然上面异常,下面会变红的
            if(fw!=null){
                try {
                    //fw.close方法声明抛出了IOException异常对象,所以我们就的处理这个异常对象,要么throws,要么try catch
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

二、 Properties(是唯一和IO有关的Map集合的子类)

java.util.Properties集合 extends Hashtable<k,v> implements Map<k,v>
Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
Properties集合是一个唯一和IO流相结合的集合
可以使用Properties集合中的方法store,把集合中的临时数据(java写的集合会存储再内存里,关闭就删除了),持久化写入到硬盘中存储

重点)可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用

load和store一般都使用字符流,因为字节流遇到中文会乱码
属性列表中每个键及其对应值都是一个字符串。(默认是字符串,所以不用写泛型了
Properties集合是一个双列集合,key和value默认都是字符串

Properties集合有一些操作字符串的特有方法
Object setProperty(String key, String value) 调用 Hashtable 的方法 put。
String getProperty(String key) 通过key找到value值,此方法相当于Map集合中的get(key)方法
Set stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,此方法相当于Map集合中的keySet方法(遍历时用

下面还有遍历的具体的方法,看代码(show01是读取自己put进去的数据,而show03是读取本地硬盘的文件到java控制台上):

package com.itheima.demo07.Prop;

import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;

public class Demo01Properties {
    public static void main(String[] args) throws IOException {
        show03();
    }

    /*
        可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
        void load(InputStream inStream)
        void load(Reader reader)
        参数:
            InputStream inStream:字节输入流,不能读取含有中文的键值对
            Reader reader:字符输入流,能读取含有中文的键值对
        使用步骤:
            1.创建Properties集合对象
            2.使用Properties集合对象中的方法load读取保存键值对的文件
            3.遍历Properties集合
        注意:
            1.存储键值对的文件中,键与值默认的连接符号可以使用=,空格(其他符号)
            2.存储键值对的文件中,可以使用#进行注释,被注释的键值对不会再被读取
            3.存储键值对的文件中,键与值默认都是字符串,不用再加引号
     */
    private static void show03() throws IOException {
        //1.创建Properties集合对象
        Properties prop = new Properties();
        //2.使用Properties集合对象中的方法load读取保存键值对的文件
        prop.load(new FileReader("09_IOAndProperties\\prop.txt"));
        //prop.load(new FileInputStream("09_IOAndProperties\\prop.txt"));
        //3.遍历Properties集合
        Set<String> set = prop.stringPropertyNames();
        for (String key : set) {
            String value = prop.getProperty(key);
            System.out.println(key+"="+value);
        }
    }

    /*
        可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
        void store(OutputStream out, String comments)
        void store(Writer writer, String comments)
        参数:
            OutputStream out:字节输出流,不能写入中文(一般不用它,因为键有中文就乱码了)
            Writer writer:字符输出流,可以写中文
            String comments:注释,用来解释说明保存的文件是做什么用的
                    不能使用中文,会产生乱码,默认是Unicode编码
                    一般使用""空字符串

        使用步骤:
            1.创建Properties集合对象,添加数据
            2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
            3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
            4.释放资源
     */
    private static void show02() throws IOException {
        //1.创建Properties集合对象,添加数据
        Properties prop = new Properties();
        prop.setProperty("赵丽颖","168");
        prop.setProperty("迪丽热巴","165");
        prop.setProperty("古力娜扎","160");

        //2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
        FileWriter fw = new FileWriter("09_IOAndProperties\\prop.txt");

        //3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
        prop.store(fw,"save data");

        //4.释放资源
        fw.close();

        //一般别用,会乱码,用上面那个
        //prop.store(new FileOutputStream("09_IOAndProperties\\prop2.txt"),"");
    }

    /*
        使用Properties集合存储数据,遍历取出Properties集合中的数据
        Properties集合是一个双列集合,key和value默认都是字符串
        Properties集合有一些操作字符串的特有方法
            Object setProperty(String key, String value) 调用 Hashtable 的方法 put。
            String getProperty(String key) 通过key找到value值,此方法相当于Map集合中的get(key)方法
            Set<String> stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,此方法相当于Map集合中的keySet方法
     */
    private static void show01() {
        //创建Properties集合对象
        Properties prop = new Properties();
        //使用setProperty往集合中添加数据
        prop.setProperty("赵丽颖","168");
        prop.setProperty("迪丽热巴","165");
        prop.setProperty("古力娜扎","160");
        //prop.put(1,true);

        //使用stringPropertyNames把Properties集合中的键取出,存储到一个Set集合中
        Set<String> set = prop.stringPropertyNames();

        //遍历Set集合,取出Properties集合的每一个键
        for (String key : set) {
            //使用getProperty方法通过key获取value
            String value = prop.getProperty(key);
            System.out.println(key+"="+value);
        }
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值