【Java的IO流之文件字符输入输出流 25】

一、FileReader:读取字符流;FileWriter:写入字符流

字符流可以读取和写入汉字和英文,字节流不能读取和写入汉字

二、FileReader流

1、常用的构造方法

FileReader(String filename)  -->从给定从中读取数据的文件名的情况下创建一个新的filename

2、常用的成员方法

|--  public int read() throws IOException

读取:读取单个字符。

返回:作为整数读取的字符,范围在0~65535之间(0x00-0xffff)。如果已达到流的末尾,则返回-1

抛出:IOException - 如果发生 I/O 错误
|-- public int read(char[] cbuf) throws IOException
读取:将字符读入数组

参数:cbuf目标缓冲区

返回:读取的字符数,如果已达到流的末尾,返回-1

抛出:IOException - 如果发生 I/O 错误

|-- public abstract int read(char[] cbuf,
                         int off,
                         int len)
                  throws IOException

读取:将字符读入数组的某一部分

参数:cbuf目标缓冲区

     off开始存储字符处的偏移量

     len要读取的最多字符数

返回:读取的字符数,如果已达到流的末尾,返回-1

抛出:IOException - 如果发生 I/O 错误

package com.JavaStudy.studyFileReader0629;

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

/**
 * @Author wufq
 * @Date 2020/6/29 17:43
 * 读取文件字符流
 * FileReader读取文件会出现乱码
 */
public class FileReaderTest01 {
    public static void main(String[] args){
        FileReader fr = null;
        String file = "/Users/wufq/Desktop/copy.txt";

        try {
            fr = new FileReader(file);

            char[] chars = new char[512];
            int temp=0;
            while ((temp=fr.read(chars))!=-1){
                String msg = new String(chars,0,temp);
                System.out.println(msg);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e){
           e.printStackTrace();
        } finally {
            if (fr != null) {
                try {
                    //谁先定义后关闭谁
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
===执行结果===
�Һ��ҵ����abc123

上面的代码发现读取文件内的中文,返回了乱码

如何解决乱码:

引入InputStreamReader类、BufferedReader类

1、InputStreamReader是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

为了达到更高的效率,可要考虑在BufferedReader内包装InputStreamReader   例如:BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

2、BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符,数组和行的高效读取。

两个构造方法:BufferedReader(Reader in)   默认大小,默认值就足够大了,BufferedReader(Reader in, int sz)指定缓冲区的大小
主要构造方法:read():读取单个字符,readLine():读取一个文本行

package com.JavaStudy.studyFileReader0629;

import java.io.*;

/**
 * @Author wufq
 * @Date 2020/6/30 09:45
 * 解决乱码
 */
public class FileReaderTest02 {
    public static void main(String[] args){
        String file = "/Users/wufq/Desktop/copy.txt";
        InputStreamReader isr = null;
        BufferedReader bReader = null;
        String temp;

        try {
            //字节流转换成字符流的通道
            isr = new InputStreamReader(new FileInputStream(file),"GBK");
            bReader = new BufferedReader(isr);
            while ((temp=bReader.readLine())!=null){
                System.out.print(temp);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(bReader !=null){
                try {
                    bReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
====执行结果====
我和我的祖国abc123

三、FileWriter流:用于写入字符流

1、两个常用构造方法:

FileWriter(String fileName) :覆盖掉原先文件的内容

FileWriter(String fileName,boolean append)  :不会覆盖掉原先文件的内容,会在原先文件的后面追加文本。

2、继承Writer类的方法:write

|--  public void write(char[] cbuf)  throws IOException写入字符数组。
参数:
cbuf - 要写入的字符数组
抛出:
IOException - 如果发生 I/O 错误

|-- public abstract void write(char[] cbuf,int off, int len)  throws IOException写入字符数组的某一部分。
参数:
cbuf - 字符数组
off - 开始写入字符处的偏移量
len - 要写入的字符数
抛出:
IOException - 如果发生 I/O 错误


|-- public void write(String str) throws IOException写入字符串。
参数:
str - 要写入的字符串
抛出:
IOException - 如果发生 I/O 错误


|-- public void write(String str,int off, int len) throws IOException写入字符串的某一部分。
参数:
str - 字符串
off - 相对初始写入字符的偏移量
len - 要写入的字符数
抛出:
IndexOutOfBoundsException - 如果 off 或 len 为负,或者 off+len 为负或大于给定字符串的长度
IOException - 如果发生 I/O 错误

package com.JavaStudy.studyFileReader0629;

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

/**
 * @Author wufq
 * @Date 2020/6/30 14:55
 * 写入字符流
 */
public class FileWriterTest01 {
    public static void main(String[] args){
        FileWriter fw = null;
        String file = "/Users/wufq/Desktop/paste.txt";


        try {
            //fw = new FileWriter(file);
            fw= new FileWriter(file,true);

            //各个成员方法的作用
            fw.write(5);

            fw.write("中国万岁");

            fw.write("万岁",0,2);

            String msg = "中华人民共和国";
            char[] chars = msg.toCharArray() ;//把字符串转换成char类型的数组
            fw.write(chars);
            fw.write(chars,0,3);
            fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fw !=null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

上面的代码写入txt文件后,导致原文件的编码格式改变了(或者是写入的内容出现了乱码)

如何解决:

引入OutputStreamWriterBufferedWriter

1、OutputStreamWriter:是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集

每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给 write() 方法的字符没有缓冲。

为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如:

 Writer out
   = new BufferedWriter(new OutputStreamWriter(System.out));
 代理对 是一个字符,它由两个 char 值序列表示:高 代理项的范围为 '\uD800' 到 '\uDBFF',后跟范围为 '\uDC00' 到 '\uDFFF' 的低 代理项。
2、BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入

可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。

package com.JavaStudy.studyFileReader0629;

import java.io.*;

/**
 * @Author wufq
 * @Date 2020/6/30 15:27
 * 解决写入文件改变编码格式或者乱码问题
 */
public class FileWriterTest02 {
    public static void main(String[] args){
        String file = "/Users/wufq/Desktop/paste.txt";
        OutputStreamWriter osw;
        BufferedWriter bufferW = null;

        try {
            osw = new OutputStreamWriter(new FileOutputStream(file,true),"GBK");
            bufferW = new BufferedWriter(osw);
            String msg = "1、中国";
            bufferW.write(msg);
            bufferW.newLine();//自动根据系统的不同选择换行符
            bufferW.write(msg);
            bufferW.flush();

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        } finally {
            if(bufferW!=null){
                try {
                    bufferW.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
====执行结果====
1、中国
1、中国

四、练习题

1、把A文件内的中文复制到B文件内(并且不能覆盖掉B文件内的原有数据)

package com.JavaStudy.studyFileReader0629;

import java.io.*;

/**
 * @Author wufq
 * @Date 2020/6/30 15:49
 * 把A文件内的中文复制到B文件内(并且不能覆盖掉B文件内的原有数据)
 */
public class FileReadWriteTest01 {
    public static void main(String[] args){
        String file1 = "/Users/wufq/Desktop/copy.txt";
        String file2 = "/Users/wufq/Desktop/paste.txt";
        InputStreamReader inputStreamReader;
        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        String temp;


        try {
            inputStreamReader = new InputStreamReader(new FileInputStream(file1),"GBK");
            bufferedReader = new BufferedReader(inputStreamReader);
            while ((temp = bufferedReader.readLine())!=null) {
                bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file2, true), "GBK"));
                bufferedWriter.write(temp);
                bufferedWriter.newLine();

                bufferedWriter.flush();
            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch(IOException e){
            e.printStackTrace();
        } finally{
            if(bufferedReader != null&&bufferedWriter!=null){
                try {
                    bufferedWriter.close();
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

2、使用BufferReader实现用户键盘的输入

package com.JavaStudy.studyFileReader0629;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;

/**
 * @Author wufq
 * @Date 2020/6/30 17:07
 * BufferReader实现键盘的输出
 */
public class BufferReader {
    public static void main(String[] args)throws Exception{
        /*
        利用Scanner实现
         */
        Scanner s = new Scanner(System.in);
        //执行到此处停下来等待输入
        String username = s.next();
        System.out.println("用户名:"+username);

        /*
        利用BufferReader实现键盘的输出
         */
        BufferedReader bu = new BufferedReader(new InputStreamReader(System.in));
        //执行到此处停下来等待输入
        String username1 =bu.readLine();
        System.out.println("用户名是:"+username1);
        bu.close();

    }
}

 

posted @ 2020-06-29 17:42  尘封~~  阅读(264)  评论(0编辑  收藏  举报