一、字符流和字节流的区别

拿一下上一篇文章的例子:

 package com.demo.io;

 import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer; public class FileReaderWriterTest { public static void main(String[] args) throws Exception{
File file = new File("D:/Files/writer.txt");
Writer out = new FileWriter(file);
// 声明一个String类型对象
String str = "Hello World!!!";
out.write(str);
out.close(); //读文件操作
Reader in = new FileReader(file);
// 开辟一个空间用于接收文件读进来的数据
char c0[] = new char[1024];
int i = 0;
// 将c0的引用传递到read()方法之中,同时此方法返回读入数据的个数
i = in.read(c0);
in.close();
if(i==-1){
System.out.println("文件中无数据");
}else{
System.out.println(new String(c0,0,i));
}
}
}

第17行"out.close()"注释掉可以看一下效果,"writer.txt"一定是空的,控制台上输出的是"文件中无数据",说明一下原因。

字符流和字节流非常相似,但也有区别,从网上找了一张图:

从图上看,字符流和字节流最大的区别在于,字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流操作时使用了缓冲区,通过缓冲区再操作文件。这也解释了上面程序的那个问题,为什么不对资源进行close()就无法写入文件的原因。因为在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果没有关闭,缓冲区中的内容是无法输出的

什么是缓冲区?简单理解,缓冲区就是一块特殊的内存区域。为什么要使用缓冲区?因为如果一个程序频繁操作一个资源(文件或数据库),则性能会很低,为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域读取数据即可,因为读取内存的速度要快于读取磁盘中文件内容的速度。

在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区。

如果不想在关闭时再输出字符流的内容也行,使用Writer的flush()方法就可以了。

二、字符流的原理

Java支持字符流和字节流,字符流本身就是一种特殊的字节流,之所以要专门有字符流,是因为Java中有大量对于字符的操作,所以专门有字符流。字节流和字符流的转换是以InputStreamReader和OutputStreamWriter为媒介的,InputStreamReader可以将一个字节流中的字节解码成字符,OutputStreamWriter可以将写入的字符编码成自节后写入一个字节流。

InputStreamReader中的解码字节,是由StreamDecoder完成的,StreamDecoder是Reader的实现类,定义在InputStreamReader的开头:

public class InputStreamReader extends Reader {

    private final StreamDecoder sd;

同样,OutputStreadWriter中的编码字节,是由StreamEncoder完成的,StreamEncoder是Writer的实现类,定义在OutputStreamWriter的开头:

public class OutputStreamWriter extends Writer {

    private final StreamEncoder se;

假如不对StreamDecoder和StreamEncoder指定Charset编码格式,将使用本地环境中的默认字符集,例如中文环境中将使用GBK编码。

InputStreamReader有两个主要的构造函数:

1、InputStreamReader(InputStream in)

2、InputStreamReader(InputStream in, String charsetName)

OutputStreamWriter也有两个主要的构造函数:

1、OutputStreamWriter(OutputStream out)

2、OutputStreamWriter(OutputStream out, String charsetName)

从构造函数就可以看出,字符流是利用字节流实现的。InputStreamReader和OutputStreamWriter的两个构造函数的区别在于,一个是使用的默认字符集,一个可以指定字符集名称。其实FileReader和FileWriter可以看一下源码,很简单,只有构造函数,里面都是分别根据传入的文件绝对路径或者传入的File实例,new出FileInputStream和FileOutputStream,在调用InputStreamReader和OutputStreamWriter的构造方法。这么做,帮助开发者省去了实例化FileInputStream和FileOutputStream的过程,让开发者可以直接以fileName或file作为构造函数的参数

三、BufferedWriter、BufferedReader

为了达到最高的效率,避免频繁地进行字符与字节之间的相互转换,最好不要直接使用FileReader和FileWriter这两个类进行读写,而使用BufferedWriter包装OutputStreamWriter,使用BufferedReader包装InputStreamReader。同样,在D盘Files文件夹下没有"buffered"这个文件,代码示例为:

package com.demo.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer; public class BufferedWriterReaderTest { public static void main(String[] args) throws Exception{
File file = new File("D:/Files/buffered.txt");
Writer writer = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(writer);
bw.write("1234\n");
bw.write("2345\n");
bw.write("3456\n");
bw.write("\n");
bw.write("4567\n");
bw.close();
writer.close(); if (file.exists() && file.getName().endsWith(".txt")){
Reader reader = new FileReader(file);
BufferedReader br = new BufferedReader(reader);
String str = null;
while ((str = br.readLine())!= null){
System.out.println(str);
}
reader.close();
br.close();
}
}
}

运行一下,首先D盘Files文件夹下多出了"buffered.txt"这个文件,文件中的内容为:

然后看一下控制台的输出结果:

1234
2345
3456 4567

没什么问题,输出了文件中的内容。注意两点:

1、利用BufferedWriter进行写操作,写入的内容会放在缓冲区内,直到遇到close()、flush()的时候才会将内容一次性写入文件。另外注意close()的顺序,一定要先关闭BufferedWriter,再关闭Writer,不可以倒过来,因为BufferedWriter的写操作是通过Writer的write方法写的,如果先关闭Writer的话,就无法将缓冲区内的数据写入文件了,会抛出异常。

2、利用BufferedReader进行读操作,不可以用父类Reader指向它,因为readLine()这个方法是BufferedReader独有的,readLine()的作用是逐行读取文件中的内容。

Java IO(五)——字符流进阶及BufferedWriter、BufferedReader的更多相关文章

  1. Java IO6:字符流进阶及BufferedWriter、BufferedReader

    字符流和字节流的区别 拿一下上一篇文章的例子: public static void main(String[] args) throws Exception { File file = new Fi ...

  2. Java IO4:字符流进阶及BufferedWriter、BufferedReader

    字符流和字节流的区别 拿一下上一篇文章的例子: 1 public static void main(String[] args) throws Exception 2 { 3 File file = ...

  3. Java IO: 其他字符流(下)

    作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) 本小节会简要概括Java IO中的PushbackReader,LineNumberReader,St ...

  4. Java IO之字符流和文件

    前面的博文介绍了字节流,那字符流又是什么流?从字面意思上看,字节流是面向字节的流,字符流是针对unicode编码的字符流,字符的单位一般比字节大,字节可以处理任何数据类型,通常在处理文本文件内容时,字 ...

  5. [Java IO]03_字符流

    Java程序中,一个字符等于两个字节. Reader 和 Writer 两个就是专门用于操作字符流的类. Writer Writer是一个字符流的抽象类.  它的定义如下: public abstra ...

  6. java IO之 字符流 (字符流 = 字节流 + 编码表) 装饰器模式

    字符流 计算机并不区分二进制文件与文本文件.所有的文件都是以二进制形式来存储的,因此, 从本质上说,所有的文件都是二进制文件.所以字符流是建立在字节流之上的,它能够提供字符 层次的编码和解码.列如,在 ...

  7. Java IO编程——字符流与字节流

    在java.io包里面File类是唯一 一个与文件本身有关的程序处理类,但是File只能够操作文件本身而不能够操作文件的内容,或者说在实际的开发之中IO操作的核心意义在于:输入与输出操作.而对于程序而 ...

  8. Java IO系统--字符流

    字符流:尽管字节流提供了处理任何类型输入/输出操作的足够功能,它们补鞥呢直接操作Unicode字符.字符流层次结构的顶层是Reader和Writer抽象类.类似于InputStream和OutputS ...

  9. Java——IO类 字符流概述

    body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...

随机推荐

  1. iframe 标签属性解读

    iframe 元素会创建包含另外一个文档的内联框架(即行内框架)

  2. Html5新增标签的学习。

    随笔,记录的比较随便. 今天新学习了9个标签. <audio> 简单的说就是一个音频标签,他的主要常用属性有src=""音频的路径 controls="con ...

  3. android笔试题二

    1.android系统架构: Linux内核——标准库——Framework层——应用层 Linux层包括:Android系统的核心服务,硬件驱动,进程管理,系统安全等等 (现在又加了一层变成了:Li ...

  4. 网络基础 记一次HTTPS证书验证测试过程

    记一次HTTPS证书验证测试过程 by:授客 QQ:1033553122 实践 1) 安装证书 选择主机A(假设10.202.95.88)上安装https证书 说明:采用https的服务器,必须安装数 ...

  5. loadrunner 脚本优化-参数化方法

    脚本优化-参数化方法 by:授客 QQ:1033553122 方法一 1.确定需要参数化的内容 2.选中需要参数化的内容 3.右键选中的内容->Replace with a Parameter- ...

  6. <自动化测试方案_10>第十章、自动化测试部署策略

    第十章.自动化测试部署策略 按照以下顺序部署自动化框架 1,部署API自动化    时间:三周2,部署PC端UI自动化 时间:1个月 3,部署Sonar代码质量管理 时间:1个月 4,集成到Jenki ...

  7. git 入门教程之实战 git

    实战 git git 是一款分布式版本控制系统,可以简单概括: 不要把鸡蛋放在一个篮子里,你的一举一动都在监视中. 实战场景 你作为某项目的其中一员或者负责人,和小伙伴们一起开发,大家既有着各自分工互 ...

  8. pjsip 播放音视频

    http://blog.csdn.net/leixiaohua1020/article/details/40246783 onCallMediaState回调里,解码方向,获取ci.media[i]. ...

  9. [20181116]18c DML 日志优化.txt

    [20181116]18c DML 日志优化.txt 1.环境:xxxxxxxx> select banner_full from v$version;BANNER_FULL---------- ...

  10. vs添加到附加进程调试(IIS页面调试)

    有时候单元测试不是很方便,通过页面调试接口会更直观,也跟容易发现问题(尤其是在页面传参的时候),这时vs添加到附加进程的调试方式就显得尤为重要了! 步骤如下: 1.首先是通过IIS建立网站,(前提是要 ...