【Java IO流】字符流详解

news2024/11/17 17:53:01

文章目录

  • 1. 前言
  • 2. 字符输入流
  • 3. 字符输出流
  • 4. 字符流底层原理解析
    • 4.1 字符输入流
    • 4.2 字符输出流

1. 前言

在上一篇字符集详解中我们说到了产生乱码的原因,要么是读取数据时未读完整个汉字,要么是因为编码和解码的方式不统一,对于后者我们只需要规定好编码和解码的方式,而要解决读取数据时未读完整个汉字的问题,我们必须要有一个在遇到汉字时一次读取多个字节的方法,字符流应运而生。

其实,字符流的底层依然是字节流的方式,在读取英文等字符时一次读取一个字节,不同的是,当遇到中文时,会一次读取多个字节。我们已经学习了字节流中的文件 FileOutputStream 类和 FileInputStream 类,现在我们可以按照前面的方法继续学习。

image-20230116215921721

首先,在字符流中有两个基本类,分别是字符输入流 Reader 类和字符输出流 Writer 类,这两个类都是抽象类,不能实例化对象,我们一般使用其子类创建对象完成数据的写出和读取。

2. 字符输入流

我们可以使用字符输入流 FileReader 把本地文件中的数据读取到程序中,该类在使用时分为以下三个步骤:

  1. 创建流对象
  2. 读取数据
  3. 释放资源/关流

示例:

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

public class Test {
    public static void main(String[] args) throws IOException {
        //创建流对象
        FileReader fileReader = new FileReader("test.txt");
        //读取数据
        int b;
        while((b=fileReader.read())!=-1){
            System.out.print((char)b);
        }
        //释放资源
        fileReader.close();

    }
}

在 read() 方法中,程序会把读取到的数据进行解码并转换成 字符集表中对应的十进制数,其底层还是字节流的方式,只是在遇到中文时一次读取多个字节并解码转为字符集表中对应的十进制数。程序中的异常直接抛出即可。

同样,我们也可以往 read() 方法中传入一个数组,表示一次读取多个字符并存入数组中,与空参的 read() 方法不同的是,带参数的方法返回每次读取的数据个数,这个数字由数组的大小决定。读取到文件末尾时返回 -1。

示例:

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

public class Test {
    public static void main(String[] args) throws IOException {
        //创建流对象
        FileReader fileReader = new FileReader("test.txt");
        //读取数据
        char[] chars = new char[2];
        int len;
        while((len=fileReader.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }
        //释放资源
        fileReader.close();
    }
}

读取数据是一个解码的过程。

3. 字符输出流

使用字符输出流 FileWriter 往本地文件中写出数据有两种方式:

  • 清空文件,把数据写入文件中
  • 把数据追加到文件末尾

在创建 FileWriter 类对象时,参数既可以是 String 类型也可以是 File 类对象,如果传入String 类型,其底层同样会创建 File 类对象。写入数据时,如果文件不存在,则会创建文件并写入数据,但是要保证父级路径正确,如果文件存在,默认会清空 文件并写入数据,如果想要追加写入,则传入参数 true 。

示例:

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

public class Test {
    public static void main(String[] args) throws IOException {
        //创建流对象
        FileWriter fileWriter = new FileWriter("test.txt",true);
        String s="Java你好";
        char[] chars=s.toCharArray();
        //写入数据
        fileWriter.write(97);//写出一个字符
        fileWriter.write(s);//写出一个字符串
        fileWriter.write(s,1,2);//写出一个字符串的一部分

        fileWriter.write(chars);//写出一个字符数组
        fileWriter.write(chars,2,3);//写出一个字符数组的一部分
        //释放资源
        fileWriter.close();
    }
}

写出一个字符时,write() 方法传入的参数是要写入文件的字符在字符集中对应的十进制数,写出数据其实是一个编码的过程。

4. 字符流底层原理解析

接下来我们一起探讨一下字符流的底层原理,

4.1 字符输入流

当我们创建一个文件字符输入流的对象时,其底层会在内存中创建一个缓冲区,该缓冲区是一个大小为 8192 的字节数组,在读取数据时,Java 首先会判断缓冲区中是否有数据,如果缓冲区中没有数据,则会从文件中读取数据,并且尽量充满缓冲区,如果缓冲区中有数据,则会从缓冲区中读取数据,直到读取完该区的数据,Java 会继续从文件中往缓冲区读取数据并且尽量充满缓冲区,直到读取到文件末尾,返回 -1。

使用Debug的方法查看缓冲区:

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

public class Test {
    public static void main(String[] args) throws IOException {
        //创建流对象
        FileReader fileReader = new FileReader("test.txt");
        //读取数据
        fileReader.read();
        //释放资源
        fileReader.close();
    }
}

image-20230116234500447

4.2 字符输出流

同样的,在我们创建文件字符输出流的同时,其底层会在内存中创建一个大小为 8192 的缓冲区,该缓冲区是一个字节数组。在写出数据时,首先会把数据按照UTF-8 的编码方式编码,然后写到这个缓冲区中,那么什么时候数据会被写到文件中呢?

image-20230116234043097

以下三种情况缓冲区数据会被写入文件:

  1. 缓冲区装满了
  2. 调用成员方法 flush() 刷新
  3. 关流

我们下期见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/173170.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PromQL之函数

Prometheus 版本 2.41.0 平台统一监控的介绍和调研直观感受PromQL及其数据类型PromQL之选择器和运算符PromQL之函数 PromQL 聚合函数 PromQL 的聚合函数只能用于瞬时向量,支持的聚合函数有: sum 求和min 最小值max 最大值avg 平均值group 分组&#xf…

Nginx与LUA(5)

您好,我是湘王,这是我的CSDN博客,欢迎您来,欢迎您再来~Nginx诞生以来就获赞无数,反向代理、负载均衡、流量限制与流量扩展都是它的拿手好戏。基本上是互联网应用的主流入口,和计算、即时通讯、存…

python批量下载modis数据(可筛选日期、范围、数据类型)

找了一圈下modis数据的,有的不能空间筛选有的不能下初级产品(也可能没找到),不甚满意,自己搞了个 0 前言 用到的主要依赖是selenium,下载网站是https://ladsweb.modaps.eosdis.nasa.gov,环境是…

ensp实现不同VLAN之间的通信

1.VLAN的基本配置 一个简单的VLAN实验&#xff0c;基本配置如图。 其中交换机为S5700。 在只对四台PC配置IP地址&#xff0c;交换机不用配置后&#xff0c;四台PC可以互相ping通。 下面是对交换机配置VLAN的方法 <Huawei>sys #进入系统视图 [Huawei…

钉钉搭和金蝶云星空接口打通对接实战

数据源系统:阿里宜搭宜搭是阿里巴巴自研的基于钉钉和阿里云的低代码平台&#xff0c;可让用户通过简单的拖拽、配置即可完成应用搭建&#xff0c;为每个组织提供低门槛、高效率的数字化业务应用生产新模式。有效缩减企业应用开发时间&#xff0c;助力企业数字化升级。对接目标系…

第四层:友元与函数成员别样定义

文章目录前情回顾友元友元的概念友元的目的友元的关键字友元的两种种用法全局函数做友元类做友元函数成员的别样定义有缘人学友元&#xff0c;急速突破第四层本章知识点&#xff08;图片形式&#xff09;&#x1f389;welcome&#x1f389; ✒️博主介绍&#xff1a;一名大一的…

Python怎么获取节假日信息?

“holidays” 是一个 Python 第三方库&#xff0c;它可以用来解析和处理节假日信息。 该库提供了一系列函数&#xff0c;可以用来检查某一天是否是节假日、获取某一年中所有节假日的列表等。它支持多种国家和地区的节假日&#xff0c;例如美国、加拿大、澳大利亚、英国等。 “…

【软件架构思想系列】分层架构

- 分层架构 -今天谈下架构设计中的分层思想和分层模型。架构思维概述对于架构思维本身仍然是类似系统思维&#xff0c;结构化思维&#xff0c;编程思维等诸多思维模式的一个合集。由于架构的核心作用是在业务现实世界和抽象的IT实现之间建立起一道桥梁&#xff0c;因此…

CUDA编程笔记(4)

文章目录前言1.CUDA的计时程序2.CUDA程序的计时影响GPU加速的关键总结前言 怎么才能看出使用cuda编程&#xff0c;提高了程序的性能&#xff0c;一般都是通过比较程序运行的时间来验证。所以熟悉程序的运行时间的计时&#xff0c;可以查看优化的性能效果。 1.CUDA的计时程序 …

每日亿题(面试题)

每日亿题(面试题) new Fn和new Fn()有什么区别&#xff1f; 1.首先如果是为传参数的情况下结果是相同的 2.如果是获取属性new Fn() 正常执行&#xff0c;而 new Fn 报错 3.不带括号不能给构造函数传参 分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用…

Spring看这一篇文章就够了

第一章 Spring简介 第1节 Spring的介绍 Spring官网地址 1https://spring.ioSpring的介绍 1Spring是一个开放源代码的设计层面框架&#xff0c;他解决的是业务逻辑层和其他各层的松耦合问题&#xff0c;因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003年兴起的一…

4.2w字,详细的带你认识基础I/O【Linux--基础IO】

前言 相信大家最开始都挺疑惑的&#xff0c;什么I/O。在计算机操作系统中&#xff0c;所谓的I/O实则就是输入&#xff08;Input&#xff09;和输出&#xff08;Output&#xff09;&#xff0c;也可以理解为读&#xff08;Read&#xff09;和写&#xff08;Write&#xff09;&…

Linux常用命令——tar命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) tar Linux下的归档使用工具&#xff0c;用来打包和备份。 补充说明 tar命令可以为linux的文件和目录创建档案。利用tar&#xff0c;可以为某一特定文件创建档案&#xff08;备份文件&#xff09;&#xff0c;也…

mysql 基本组成

1 mysql 基本组成 1.1、mysql连接器的工作流程: 1.2、查看连接状态: show processlist; Note:客户端太长时间没动静 就自动断开 这个时间是由wait_timeout参数控制的,默认8h 长连接短链接 长连接是链接成功后,如果客户端持续有请求,则使用同一个链接[尽量使用长连接,因为每次…

组件间通信

1、Vue组件的嵌套关系 1.1、认识组件的嵌套 前面我们是将所有的逻辑放到一个App.vue中&#xff1a; 在之前的案例中&#xff0c;我们只是创建了一个组件App&#xff1b;如果我们一个应用程序将所有的逻辑都放在一个组件中&#xff0c;那么这个组件就会变成非常的臃肿和难以维…

【网络通信】【电信运营商实战工程师】思科设备篇-思科设备园区网实战

电信运营商实战工程师系列文章. 思科设备篇-思科设备园区网实战. 文章目录1. 思科设备链路捆绑实战2. 思科设备VRRP、HSRP实战3. 思科设备ACL实战全集4. 思科设备RIP协议实战5. 思科设备OSPF协议全集-理论6. 思科设备OSPF协议全集-实战1. 思科设备链路捆绑实战 知识点&#xff…

【中科微北斗+GPS模块经纬度数据解析详细教程-附免费代码工程】

中科微北斗GPS模块经纬度数据解析详细教程-附免费代码工程简介准备工作PC端需要用到的工具代码下载地址GD32F103C8T6最小系统板代码实现GD32串口引脚定义如下&#xff1a;串口的初始化串口0初始化代码&#xff1a;串口1初始化代码串口的输入串口0的输入代码如下&#xff1a;串口…

嵌入式Linux-线程的开始

1. 线程的开始 1.1 线程的含义 学习了进程相关的知识内容&#xff0c;对进程有了一个比较全面的认识和理解&#xff0c;从今开始呢&#xff0c;我们要学习一个新的概念&#xff0c;叫做线程&#xff01; 那什么是线程呢? 与进程类似&#xff0c;线程是允许应用程序并发执行…

java中的方法2023016

定义方法&#xff08;VS函数&#xff09;&#xff1a; 方法是类或对象的行为特征的抽象&#xff0c;方法是类或对象最重要的组成部分。但从功能上来看&#xff0c;方法完全类似于传统结构化程序设计里的函数。区别是&#xff1a;Java里的方法不能独立存在&#xff0c;所有的方法…

《精力管理》阅读笔记

目录 什么是精力及如何管理精力 高效表现有节奏——劳逸结合的平衡 管理精力的三个步骤 明确目标——知道什么最重要才能全情投入 正视现实——你的精力管理做得如何 付诸行动——积极仪式习惯的力量 精力管理的四个基本原则 体能精力——为身体添柴加火 情感精力——把…