Java-IO流(四)-字符流(FileReader、FileWriter)

字节流读取字符的问题

一次读一个字节。这样对中文是无法判断。怎么解决呢?一个中文默认是两个字节

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;

public class CharStreamDemo {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        
        /*
         * 需求1:通过流写一个篇文章,里面有中文。"你好你好"。indexOf('好');
         */
//      writeCNText();
        
        
        /*
         * 需求2:一篇文章中出现了多少个好字。读取数据。判断好字并计数。
         * 思路:读取一个文本,获取内容判断好字。
         */
        
         readCNText();
    }

    public static void readCNText() throws IOException {
        FileInputStream fis = new FileInputStream("tempfile/cn.txt");
        
        //一次读一个字节。这样对中文是无法判断。怎么解决呢?一个中文默认是两个字节。
        //读取所有的字节,存储起来(字节数组),变成字符串。然后找指定的字符。
        
//      byte[] buf = new byte[4];
//      int len = 0;
//      while((len=fis.read(buf))!=-1){
//          String str = new String(buf,0,len);
//          System.out.println(str);
//      }
        
//      int ch = 0;
//      while((ch=fis.read())!=-1){
//          System.out.println(ch);
//      }
        
        int ch = fis.read();
        System.out.println("读取一个字节:"+ch);
        int ch1 = fis.read();
        System.out.println("读取一个字节:"+ch1);
        fis.close();
        
    }

    public static void writeCNText() throws FileNotFoundException, IOException {
        FileOutputStream fos = new FileOutputStream("tempfile/cn.txt");
        
        fos.write("你好你好".getBytes());
        
        fos.close();
    }

}

编码表

编码表:其实就是生活中文件和计算机二进制的对应关系表。
1,ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx
2,iso8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx  负数。
3,GB2312:简体中文码表。6,7仟的中文和符号。用两个字节表示。两个字节都是开头为1 两个字节都是负数。
    GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,一部分文字,第一个字节开头是1,第二字节开头是0
    GB18030:
4, unicode:国际标准码表:无论是什么文字,都用两个字节存储。Java中的char类型用的就是这个码表。char c = 'a';占两个字节。
    在Java中,字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。
5,UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。
                
    能识别中文的码表:GBK  UTF-8  正因为识别中文码表不唯一,涉及到了编码解码问题。
    对于我们开发而言;常见的编码 GBK  UTF-8  ISO8859-1
    文字--->二进制(数字) :编码。
    二进制(数字)--->文字  : 解码。

FileReader读取字符流

之前都是FileInputStream 用于读取字节流,FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。

查阅FileInputStream api说明中是否有相关的提示呢?发现一个新名词。
字符流:之前用的都是字节流,用于操作的都是字节数据,字符流,专门用于操作字符数据的流对象。

索引了api中的提到的 FileReader对象。发现这个对象是一个操作字符文件的便捷类,内部类使用默认的字符集解码+默认的字节缓冲区。
    其中,提到了一个如果需要修改这些值(指定码表,或者缓冲区等)需要查阅InputStreamReader。
    目前为了解决当前问题,不需要,只需要使用默认即可。
    
    使用FileReader时,了解它的功能,看它所属的体系顶层。Reader。
    Reader:读取字符流的抽象超类。read():读取单个字符并返回, read(char[]):将数据读取到数组中,并返回读取的个数。
    
FileReader : 字节读取流+默认编码表。

字符流:为了便于操作数据中的字符数据。原理: 字节流+编码表。
字符流的两个基类。

    Reader:read()读取字符。
        |-
    
    Writer(Reader的另请参见):写入字符。
        |-
    
字节流操作的是字节数组(byte[]);字符流操作的是字符数组(char[])。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;

public class CharStreamDemo {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
       
        /*
         * 解决需求2问题:
         * 使用FileReader。
         * 
         */
         System.out.println("-----------读取字符-------------");
        readCNTextByReader();
        
    }

    public static void readCNTextByReader() throws IOException {

        //创建一个读取字符文件的读取流对象。FileReader。
        FileReader fr = new FileReader("tempfile/cn.txt");//这个流的底层使用的是FileInputStream
        
//      int ch = fr.read();
//      System.out.println("读取一个字符:"+ch);
//      int ch1 = fr.read();//一次读取一个中文,读取多个字节查表转成中文。
//      System.out.println("读取一个字符:"+(char)ch1);
        int ch = 0;
        int count = 0;
        while((ch=fr.read())!=-1){
            if(ch=='好'){
                count++;
            }
        }
        System.out.println("count="+count);
        fr.close();
    }
}

FileWriter写入字符文件

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

public class FileWriterDemo {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        //演示FileWriter 用于操作文件的便捷类。
        FileWriter fw = new FileWriter("tempfile/fw.txt");
        
        fw.write("你好谢谢再见");//这些文字都要先编码。都写入到了流的缓冲区中。
        
        fw.flush();
        
        fw.close();
        
        /*
         * flush()和close()的区别?
         * 
         * flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用。
         * close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。
         * 
         * 如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭。
         * 
         * 
         */
    }

}

你可能感兴趣的:(Java-IO流(四)-字符流(FileReader、FileWriter))