转换流和系统缓冲流的使用——基本使用

编码集的问题

在传输中文文本文件的时候,字节流显然不如字符流有优势,会出现乱码问题,这主要是在编码汉字的时候出现了问题。

当直接通过windows自带的记事本.txt文件编写汉字的时候,默认存储编码格式是ANSI,即中文状态下的GBK,而我们开发常用的是utf-8编码集,所以在读取或者写入的时候会出现问题,一般的解决办法就是更改记事本的编码存储格式,另存为修改即可,还有就是通过转换流解决。

编码集的分类

  • GB2312:中国简体文字和一部分少数民族的文字(1995年)
  • GBK(ANSI在中文状态下指的是GBK): windows操作系统,默认的中文模式的编码集,新国标,包含所有的简体文字和少数民族文字(GB2312升级版)
  • GB18030 :GBK的升级版本
  • BIG5:中文繁体字的编码,台湾地区使用
  • UTF-8 :万国码,开发中统一使用的编码集,中文占位3字符,其他占位1个字符
  • UTF-16(unicode): 所有字符都是2个字节,对于英文和数字浪费空间,但是对世界各国语言的包容性最大
  • ASCII :最简单的编码集128个

记事本的BOM头问题

BOM(Byte Order Mark)微软记事本独有标识,字节序列标记,用来标识文件的编码类型。只有utf-8和unicode会出现这个问题,明面无法查看,需要通过EditPlus,使用十六进制打开才能看到,出现在编码的开头位置。
注意事项
(1)utf-8的BOM头是 EF BB BF
(2)unicode 的BOM头是 FF FE ,末尾的 FE比 FF小,属于小端
(3)unicode big endian 的 BOM头是 FE FF 属于大端
(4)如果文本内容是由程序写入的,则没有BOM头
(5)BOM头可能导致XML文件解析出现问题,且问题不可见

转换流

字节转字符输入流:InputStreamReader

该类流是字符输入流FileReader的父类,将字节输入流转换为字符输入流,获取硬盘上的字节,根据编码转为字符读取到内存

//代码演示
public class Demo4 {
    public static void main(String[] args) throws IOException {
        //创建字节输入流,获取硬盘的字节
        FileInputStream fis = new FileInputStream("D:\\Java\\md2.txt");

        //创建转换流,将字节流导入,并确定编码格式
        InputStreamReader isr = new InputStreamReader(fis, "GBK");

        //和FileReader一样,字符读取
        int len = -1;
        char[] buffer = new char[1024 * 4];
        while ((len = isr.read(buffer)) != -1) {
            System.out.println(new String(buffer, 0, len));
        }

        //字节流已经被包装到转换通道中,所以只需要关闭外层即可
        isr.close();
    }
}

字符转字节输出流:OutputStreamWriter

该类流是字符输出流FileWriter的父类,将内存中的字符转成字节保存到硬盘中,使用方式与InputStreamWriter一样,最后的方法也于FileWriter一样。

系统缓冲流

一种缓冲机制,将读取的数据临时保存到一个缓冲区间,区间填满后再写入或输出。
(1)减少对硬盘的操作次数,程序运行效率会提高
(2)有效保护硬盘
(3)自带缓冲区,默认是8KB,可以通过构造方法自己设置大小

字节缓冲流

  • 构造方法
//字节缓冲输入流
BufferedInputStream(InputStream in);
BufferedInputStream(InputStream in, int size); 

//字节缓冲输出流
BufferedOutputStream(OutputStream out);
BufferedOutputStream(OutputStream out, int size);
  • 方法流程
  1. 找到源文件
  2. 判断
  3. 确定目标文件(拷贝使用)
  4. 准备输入缓冲和输出缓冲流对象
  5. 准备缓冲区,读取数据,写入数据
  6. 关闭资源,先开后关,只关缓冲流

缓冲流其实就是【装饰者设计模式】,其使用方法同一般的输入输出流类似,只不过其构造器需要将节点流类对象导入,实现功能处理。

//字节缓冲流拷贝文件的代码演示:
public class Demo1 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("D:\\Java\\流.png");
        FileOutputStream fos = new FileOutputStream("D:\\Java\\流3.png");

        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        int len = -1;
        byte[] buffer = new byte[1024 * 8];
        while ((len = bis.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
            bos.flush();
        }
        
        bos.close();
        bis.close();
    }
}

字符缓冲流

字符缓冲流默认的缓冲区是一个char类型的数组,元素格式为8192(8个字节大小)。

构造方法

//字符缓冲输入流
BufferedReader(Reader in);
BufferedReader(Reader in, int sz);

//字符换缓冲输出流
BufferedWriter(Writer out);
BufferedWriter(Writer out, int sz); 

普通方法流程同字节流,字符缓冲流提供了两种新的常用读写方法:

  • 一种是可以直接读取一行的方法 readLine(),返回结果为字符串
  • 一种是用于写入的换行方法 newLine()
  • 【转换流】的结果也可以被装饰到缓冲流中,以实现这两种方法
//读取
public class Demo5 {
    public static void main(String[] args) throws IOException {
        //匿名调用形式,将文件输入流转为字符流,然后导入字符缓冲流
        BufferedReader br = new BufferedReader(new InputStreamReader(
        new FileInputStream("D:/Java/Blog/Demo.txt"), "GBK"));

        String str = null;
        while ((str = br.readLine()) != null) {
            System.out.println(str);
        }
		br.close();
    }
}

//写入
public class Demo5 {
    public static void main(String[] args) throws IOException {
        //匿名调用形式
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream("D:/Java/Blog/Demo.txt", true), "GBK"));

        bw.newLine();	//换行
        bw.write("宝剑埋冤狱,忠魂绕白云————胡宗宪");
        bw.flush();
        bw.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值