JavaIO BufferedReader和BufferedWriter使用及说明

目录
  • BufferedReader和BufferedWriter简介
  • BufferedReader
    • 构造方法
    • 成员方法
    • 读取文件实例
    • 乱码问题
  • BufferedWriter
    • 构造函数
    • 成员方法
    • 写文件实例
  • 应用:复制文本文件
    • 逐个字符复制文件
    • 逐个字符数组复制文件
    • 按行复制文件
    • 测试
    • bug:按行复制的时候多写换行符
    • bug:乱码问题
  • 总结

BufferedReader和BufferedWriter简介

为了提高字符流读写的效率,引入了缓冲机制,进行字符批量的读写,提高了单个字符读写的效率。

BufferedReader用于加快读取字符的速度,BufferedWriter用于加快写入的速度

BufferedReader和BufferedWriter类各拥有8192个字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并放满缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。

如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。

BufferedReader

BufferedReader是为了提供读的效率而设计的一个包装类,它可以包装字符流。可以从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

构造方法

方法 描述
BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。

成员方法

方法 描述
int read() 读取单个字符。
int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
String readLine() 读取一个文本行。
long skip(long n) 跳过字符。
boolean ready() 判断此流是否已准备好被读取。
void close() 关闭该流并释放与之关联的所有资源。
void mark(int readAheadLimit) 标记流中的当前位置。
boolean markSupported() 判断此流是否支持 mark() 操作(它一定支持)。
void reset() 将流重置到最新的标记。

读取文件实例

读取文件: 一个字符一个字符的读取

int read()方法,每次可以读取到一个字符(以int 类型表示),不过因为返回的是int类型的,所以要强制类型转换成char类型才能打印该字符。

public static void printByFileReader(String filePath) throws IOException
{
    BufferedReader reader=new BufferedReader(
            new FileReader(filePath)
            );
    if(!reader.ready())
    {
        System.out.println("文件流暂时无法读取");
        return;
    }
    int result=0;
    while((result=reader.read())!=-1)
    {
        //因为读取到的是int类型的,所以要强制类型转换
        System.out.print((char)result);
    }
    reader.close();
}

读取文件:一个数组一个数组的读取

int read(char[] cbuf, int off, int len)方法,每次读取len个字符放到字符数组cbuf中,从数组cbuf的下表off开始放,返回的是每次读取的字符个数。

public static void printByFileReaderChars(String filePath) throws IOException
{
    BufferedReader reader=new BufferedReader(
            new FileReader(filePath)
            );
    if(!reader.ready())
    {
        System.out.println("文件流暂时无法读取");
        return;
    }
    int size=0;
    char[] cbuf=new char[20];
    while((size=reader.read(cbuf, 0, cbuf.length))!=-1)
    {
        System.out.print(new String(cbuf,0,size));
    }
    reader.close();
}

读取文件:一行一行的读取

String readLine()这个方法一次可以读取一个文本行,返回的直接就是这一行的字符串,如果读到行尾了就返回null。

public static void printByFileReaderLine(String filePath) throws IOException
{
    BufferedReader reader=new BufferedReader(
            new FileReader(filePath)
            );
    if(!reader.ready())
    {
        System.out.println("文件流暂时无法读取");
        return;
    }
    int size=0;
    String line;
    while((line=reader.readLine())!=null)
    {
        System.out.print(line+"\n");
    }
    reader.close();
}

需要注意的是:reader.readLine()方法返回的一行字符中不包含换行符,所以输出的时候要自己加上换行符。

BufferedReader比FileReader高级的地方在于这个,FileReader能一次读取一个字符,或者一个字符数组。而BufferedReader也可以,同时BufferedReader还能一次读取一行字符串。同时,BufferedReader带缓冲,会比FileReader快很多。

但是FileReader使用项目的编码来读取解析字符,不能指定编码,可能会出现编码问题,如果要指定编码可以使用包装InputStreamReader的BufferedReader。这样兼顾效率和编码。

测试上述方法:

public static void main(String[] args) throws IOException
{
    String fileutf8="utf8.txt";
    String filegbk="gbk.txt";
    //一个字符一个字符的读取
    printByFileReader(filegbk);
    System.out.println("\n---------------------------------------");
    //一个字符数组一个字符数组的读取
    printByFileReaderChars(filegbk);
    System.out.println("\n---------------------------------------");
    //一行一行的读取
    printByFileReaderLine(filegbk);
    System.out.println("#########################################");
    //一个字符一个字符的读取
    printByFileReader(fileutf8);
    System.out.println("\n---------------------------------------");
    //一个数组一个数组的读取
    printByFileReaderChars(fileutf8);
    System.out.println("\n---------------------------------------");
    //一行一行的读取
    printByFileReaderLine(fileutf8);
}

运行结果:

gbk file
这里是一句中文
---------------------------------------
gbk file
这里是一句中文
---------------------------------------
gbk file
这里是一句中文
#########################################
utf-8 file
杩欓噷鏄竴鍙ヤ腑鏂?
---------------------------------------
utf-8 file
杩欓噷鏄竴鍙ヤ腑鏂?
---------------------------------------
utf-8 file
杩欓噷鏄竴鍙ヤ腑鏂?

可以看到包装FileReader的BufferedReader在读取文件时候如果文件的编码和项目的编码不一样的时候,会出现乱。

乱码问题

使用包装InputStreamReader的BufferedReader读取文件

String file = "utf8.txt";
BufferedReader reader = new BufferedReader(
        new InputStreamReader(new FileInputStream(file), "utf-8"));
char[] cbuf=new char[20];
int size;
while((size=reader.read(cbuf, 0, cbuf.length))!=-1)
{
    System.out.println(new String(cbuf,0,size));
}

运行结果:

utf-8 file
这里是一句中文

这里要弄清楚的是BufferedReader只负责读到它的内部缓冲区中,而解码的工作是InputStreamReader完成的。

BufferedWriter

BufferedWriter的API:

构造函数

方法 描述
BufferedWriter(Writer out) 创建一个缓冲字符输出流,使用默认大小的输出缓冲区
BufferedWriter(Writer out, int sz) 创建一个缓冲字符输出流,使用给定大小的输出缓冲区

成员方法

方法 描述
void write(int c) 写入单个字符。
void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(String s, int off, int len) 写入字符串的某一部分。
void newLine() 写入一个行分隔符。
void close() 关闭此流,但要先刷新它。
void flush() 刷新该流的缓冲。

写文件实例

使用上述三个写方法写文件:一个字符一个字符的复制文件

public static void main(String[] args) throws IOException
{
    BufferedWriter writer=new BufferedWriter(new FileWriter("静夜思.txt"));
    char ch='床';
    //写入一个字符
    writer.write(ch);
    String next="前明月光,";
    char[] nexts=next.toCharArray();
    //写入一个字符数组
    writer.write(nexts,0,nexts.length);
    //写入换行符
    writer.newLine();//写入换行符
    String nextLine="疑是地上霜。";
    //写入一个字符串。
    writer.write(nextLine);
    //关闭流
    writer.close();
}

运行结果,静夜思.txt:

床前明月光,
疑是地上霜。

应用:复制文本文件

逐个字符复制文件

static void copyByChar(String srcFile, String destFile) throws IOException
{
    BufferedReader reader = new BufferedReader(new FileReader(srcFile));
    BufferedWriter writer = new BufferedWriter(new FileWriter(destFile));
    int ch=0;
    //读取一个字符
    while ((ch = reader.read()) != -1)
    {
        //写入一个字符
        writer.write(ch);
    }
    reader.close();
    writer.close();
}

逐个字符数组复制文件

static void copyByCharArray(String srcFile, String destFile) throws IOException
{
    BufferedReader reader = new BufferedReader(new FileReader(srcFile));
    BufferedWriter writer = new BufferedWriter(new FileWriter(destFile));
    int size=0;
    char[] cbuf=new char[20];
    //读取一个字符数组
    while ((size = reader.read(cbuf)) != -1)
    {
        //读入多少写入多少
        writer.write(cbuf,0,size);
    }
    reader.close();
    writer.close();
}

按行复制文件

static void copyByLine(String srcFile,String destFile) throws IOException
{
    BufferedReader reader=new BufferedReader(new FileReader(srcFile));
    BufferedWriter writer=new BufferedWriter(new FileWriter(destFile));
    String line;
    //BufferedReader读取一行的时候返回的字符串中不包括换行符
    //如果有一行字符就返回该行字符串,没有就返回null
    while((line=reader.readLine())!=null)
    {
        writer.write(line);
        writer.newLine();//写换行符
    }
    reader.close();
    writer.close();
}

需要注意的是,BufferedReader的readLine()读取一行的时候返回的字符串没有换行符,所以,复制的时候写文件是我们好多写入一个换行符,使用writer.newLine()方法即可。

测试

public static void main(String[] args) throws IOException
{
    String from = "gbk.txt";
    String to = "gbk_copy.txt";
    String to1 = "gbk_copy1.txt";
    String to2 = "gbk_copy2.txt";
    copyByChar(from, to);
    copyByCharArray(from, to1);
    copyByLine(from, to2);
}

源文件gbk.txt:

运行结果:

gbk_copy.txt

gbk file
这里是一句中文

gbk_copy1.txt

gbk file
这里是一句中文

gbk_copy2.txt

gbk file
这里是一句中文

bug:按行复制的时候多写换行符

细心的朋友可能发现,按行复制的时候,复制的文件会莫名其妙的在文件后面多了一个换行符。这是因为我们每次都在读到的字符串后面写一个换行符。

解决办法:在读到的字符串前面写换行符,这样出现新的问题,就是在文件开头多出了一个空行,所以加入控制语句,在第一行不写入换行符,第二行后再写。

static void copyByLine(String srcFile,String destFile) throws IOException
{
    BufferedReader reader=new BufferedReader(new FileReader(srcFile));
    BufferedWriter writer=new BufferedWriter(new FileWriter(destFile));
    String line;
    //BufferedReader读取一行的时候返回的字符串中不包括换行符
    //如果有一行字符就返回该行字符串,没有就返回null
    boolean flag=false;
    while((line=reader.readLine())!=null)
    {
        if(!flag)
        {
            flag=true;
            writer.write(line);
        }
        else
        {
            writer.newLine();//写换行符
            writer.write(line);
        }

    }
    reader.close();
    writer.close();
}

这样复制的文件就不会多谢换行符了,保证复制的文件和源文件是一模一样的。

bug:乱码问题

因为我们使用的是包装FileReader的BufferedReader,包装FileWriter的BufferedWriter。所以读字符,写字符的时候使用的是默认的字符编码读写的。

所以读写文件的时候会出现乱码,可以使用包装InputStreamReader的BufferedReader,包装OutputStreamWriter的BufferedWriter来复制文件,这样就可以支持各种字符编码。

实例:gbk编码的文件复制到utf8编码的文件中:

static void copyByLineEncoding(String srcFile, String srcEncoding, String destFile,
        String destEncoding)
{
    BufferedReader reader = null;
    BufferedWriter writer = null;
    try
    {
        reader = new BufferedReader(new InputStreamReader(
                new FileInputStream(srcFile), srcEncoding));
        writer = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream(destFile), destEncoding));
        char[] charArray = new char[512];
        int size;
        while ((size = reader.read(charArray, 0, charArray.length)) != -1)
        {
            writer.write(charArray, 0, size);
        }

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

main方法:

public static void main(String[] args) throws IOException
{
    String from = "gbk.txt";
    String to = "copyto_utf8.txt";
    copyByLineEncoding(from,"gbk",to,"utf-8");
}

源文件gbk.txt(gbk编码):

gbk file
这里是一句中文

目标文件copyto_utf8.txt:

utf-8 file
杩欓噷鏄竴鍙ヤ腑鏂�

乱码是正常的,因为我们的工程目录用的gbk编码,把copyto_utf8.txt编码显示就好了:

utf-8 file
这里是一句中文

所以使用包装InputStreamReader的BufferedReader,包装OutputStreamWriter的BufferedWriter来复制文件的好处就是可以指定复制文件的时候使用的字符编码,例如上面的复制操作,从gbk编码的文件中读取,然后写入到utf8编码的文件中去。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • JavaIO字符操作和对象操作示例详解

    目录 字符操作 编码与解码 String 的编码方式 Reader 与 Writer 实现逐行输出文本文件的内容 对象操作 序列化 Serializable transient 字符操作 编码与解码 编码就是把字符转换为字节,而解码是把字节重新组合成字符. 如果编码和解码过程使用不同的编码方式那么就出现了乱码. GBK 编码中,中文字符占 2 个字节,英文字符占 1 个字节: UTF-8 编码中,中文字符占 3 个字节,英文字符占 1 个字节: UTF-16be 编码中,中文字符和英文字符都占

  • 浅谈JavaIO之try with底层原理

    IO关闭的问题 最近写了一个例子,读取一个文件没有问题,但是读取很多个文件就会告诉我:"Can't open so many files",能帮我看看是什么问题吗?可能打开文件太多了吧,用两个命令,查看最大文件打开限制. 一个命令是 ulimit -a 第二个命令是 ulimit -n 256 看起来是最大文件限制太小了,只有256个,调大一点就可以了. 读文件都是一个一个读的,没有同时开这么多文件 好吧,看下写的代码吧: BufferedReader bufferedReader =

  • 一篇文章带你深入了解javaIO基础

    目录 一.认识IO 1.IO的分类 2.IO的方式 3.IO读写的方式 4.IO的特性 二.文件操作 1.文件的构成 2.文件的创建 3.文件操作的API使用 三.IO流 1.流的分类 2.流的创建 3.流的使用 <1>输入流 <2>输出流 <3>实例:文件的复制 总结 一.认识IO 1.IO的分类 (1)BIO:同步阻塞IO (2)NIO:同步非阻塞IO (3)AIO:异步阻塞IO 注意: 这里主要介绍BIO 2.IO的方式 IO本质就是对数据的操作 (1)网络IO

  • java io文件操作从文件读取数据的六种方法

    目录 1.Scanner 2.Files.lines (Java 8) 3.Files.readAllLines 4.Files.readString(JDK 11) 5.Files.readAllBytes() 6.经典管道流的方式 在上一篇文章中,我为大家介绍了<5种创建文件并写入文件数据的方法>,本节我们为大家来介绍6种从文件中读取数据的方法. 另外为了方便大家理解,我为这一篇文章录制了对应的视频:总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 Scanner(Ja

  • java io文件操作删除文件或文件夹的7种方法

    目录 本文是Java IO总结系列篇的第4篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇总结java创建文件夹的4种方法及其优缺点-JAVA IO基础总结第三篇 如果您阅读完成,觉得此文对您有帮助,请给我点个赞,您的支持是我不竭的创作动力. 为了方便大家理解,我特意制作了本文对应的视频:总结删除文件或者文件夹的7种方法 一.删除文件或文件夹的四种基础方法 下面的四个方法都可以删除文件

  • JavaIO模型中的BIO,NIO和AIO详解

    目录 一.I/O模型 1.1 I/O模型基本说明 1.2 Java支持的3种网络编程I/O模式 1.3 JavaBIO(同步阻塞) 1.4 JavaNIO (同步非阻塞) 1.5 JavaAIO(异步非阻塞) 二.BIO.NIO.AIO适用场景分析 2.1 BIO应用场景 2.2 NIO应用场景 2.3 AIO应用场景 总结 一.I/O模型 1.1 I/O模型基本说明 I/O模型的简单理解:I/O模型就是用什么样的通道进行数据的发送和接受,很大程度上决定了程序通信的性能 1.2 Java支持的3

  • Java中BufferedReader和BufferedWriter使用方式

    目录 FileWriter/FileReader BufferedReader/BufferedWriter FileWriter/FileReader 介绍:FileWriter 类从 OutputStreamWriter 类继承而来.该类按字符向流中写入数据. 构造:参数为 File 对象 FileWriter(File file) 参数是文件的路径及文件名(默认是当前执行文件的路径) FileWrite(String filename) 等价于: OutputStreamWriter ou

  • Java中BufferedReader与BufferedWriter类的使用示例

    BufferedReader BufferedReader 是缓冲字符输入流.它继承于Reader. BufferedReader 的作用是为其他字符输入流添加一些缓冲功能. 创建BufferReader时,我们会通过它的构造函数指定某个Reader为参数.BufferReader会将该Reader中的数据分批读取,每次读取一部分到缓冲中:操作完缓冲中的这部分数据之后,再从Reader中读取下一部分的数据. 为什么需要缓冲呢?原因很简单,效率问题!缓冲中的数据实际上是保存在内存中,而原始数据可能

  • Java BufferedWriter BufferedReader 源码分析

    一:BufferedWriter 1.类功能简介: BufferedWriter.缓存字符输出流.他的功能是为传入的底层字符输出流提供缓存功能.同样当使用底层字符输出流向目的地中写入字符或者字符数组时.每写入一次就要打开一次到目的地的连接.这样频繁的访问不断效率底下.也有可能会对存储介质造成一定的破坏.比如当我们向磁盘中不断的写入字节时.夸张一点.将一个非常大单位是G的字节数据写入到磁盘的指定文件中的.没写入一个字节就要打开一次到这个磁盘的通道.这个结果无疑是恐怖的.而当我们使用Buffered

  • 浅谈缓冲字符流 BufferedReader BufferedWriter用法

    缓冲字符流BufferedReader和BufferedWriter 问题: 之前的文件读写都是按照字节.字符或者数组来实现的,对于文本文件而言,能否按照行,一行行读写呢. 提供了BufferedReader和BufferedWriter实现按行读写 package com.bjsxt.ios3; import java.io.*; public class TestBufferedReaderWriter { public static void main(String[] args) thr

  • 自定义BufferedReader的实例

    缓冲区的建立目的就是增加传输性能,使我们传输数据更加快速 缓冲区的内部其实很简单 就是在内部封装了一个数组 用数组来存储数据 对外提供一些方法对数组进行访问 其中这些方法的操作就是对数组的指针(角标). 缓冲区的原理:从源中获取一批数据到缓冲区,再从缓冲区中一个一个取出 取完后用-1作为结束标记 在BufferedReader中我们读取数据方法有read() ,readLine() read() 其参数为char[],cbuf,int off,int len.其返回值为-1 readLine()

  • Java IO及BufferedReader.readline()出现的Bug

    目录 Java IO及BufferedReader.readline()的Bug IO流 BufferedReader.readline()方法Bug 源码 使用BufferReader类的readLine()方法注意问题 一.BufferReader类的readLine()方法 二.DataInputStream类的readUTF()方法 Java IO及BufferedReader.readline()的Bug IO流 流:流是一组有序的,有起点和终点的字节集合,是对计算机中数据传输的总称.

  • Java 中IO流字符流详解及实例

    Java-IO流 字符流 java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码). 文件是byte byte byte ... 的数据序列. 文本文件是文本(char)序列按照某种编码方案(uft-8.utf-16be.gbk)序列化为byte的存储结果. 字符流(Reader.Writer)-->操作的是文本.文本文件 1.字符的处理,一次处理一个字符 2.字符的底层仍然是基本的字节序列 3.字符流的基本实现: InputStreamReader是字节流通向字符

  • Java IO流学习总结之文件传输基础

    一.Java IO流总览 二.File类 2.1 常用API package pkg1; import java.io.File; import java.io.IOException; /** * @author Administrator * @date 2021/4/2 */ public class FileDemo { public static void main(String[] args) { // 了解构造函数,可查看API File file = new File("d:\\

  • Java输入输出流的使用详细介绍

    1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读写数据的标准方法.任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法. Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO. 流IO的好处是简单易用,缺点是效率较低.块IO效率很高,但编程比较

  • Java读写文件创建文件夹多种方法示例详解

    出现乱码请修改为 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path), "GBK")); 一.获得控制台用户输入的信息 复制代码 代码如下: public String getInputMessage() throws IOException...{    System.out.println("请输入您的命令∶");    byte buffe

随机推荐