浅析 Io 处理

news2025/1/10 5:45:00

文件流: 在Java 中,文件流负责操作文件,包括读取和写入;

FileInputStream // 文件的字节输入流;

FileOutputStream // 文件的字节输出流;

FileReader // 文件的字符输入流;

FileWriter // 文件的字符输出流;

FileInputStream 和 FileOutputStream的父类分别是InputStream和OutputStream,都是字节流,以面向字节的形式提供IO操作。

FileReader 和 FileWriter的父类则是Reader和Writer,都是字符流,字符流以面向字符提供IO操作,同时,字符流兼容Unicode,能够提供更好的国际化支持。

在读取数据时,字节流的数据存储单位是字节,在接收字节流数据时,会新建一个字节类型的数组(byte[])来接收读取的数据;字符流的数据存储单位是字符,在接收字符流数据时,会新建一个字符类组(char[])的数据来接收读取的数据。

InputStream 和 OutputStream

InputStream:

InputStream及其子类的作用是用来表示不同数据源输入数据的类,其中封装了用于从数据源中读取数据的操作。这些数据源包括:

字节数组:byte[];String对象;资源文件:File;资源管道;其他流组成的流序列;其他数据源,如网络资源;InputStream子类:

ByteArrayInputStream:将内存的缓冲区当作数据源输入;StringBufferInputStream:将String转换成InputStream;FileInputStream:从本地文件中读取数据;PipedInputStream:资源管道的输入端,也是PipedOutputStream的输入源;SequenceInputStream:能够将2个或者以上的InputStream合并成一个单一的InputStream;FileterInputStream:为文件资源读取提供筛选功能;

OutputStream:

OutputStream及其子类的作用是用来表示数据输出将要去向的目标,比如:文件、资源管道、字节数组等。OutputStream也是因不同的目标有不同的子类:

ByteArrayOutputStream:在内存中创建缓冲区,所有输出的数据都会暂存在缓冲区中;FileOutputStream:将数据写出到文件中;PipedOutputStream:作为PipedInputStream的输出端,与PipedInputStream一起实现资源的“管道化”;FileterOutputStream:为文件资源写出提供筛选功能;

Reader 和 Writer

字符流有着和字节流近乎一样的功能,每个字节流api都能在字符流中找到与之相对应的,而且,字符流比字节流有着更好的性能;尽管如此,字符流的设计并不是为了取代字节流,相反,二者同时存在,相辅相成。

Reader 和 Writer及其子类都提供了对Unicode的支持,这是他们和InputStream与OutputStream系拓展最大的不同,详细如下图所示:

字节流和字符流的api对应

文件过滤器

Java IO中提供了过滤器:FilterInputStream和FilterOutputstream,用于筛选特定的输入流和输出流。因为FilterInputStream和FilterOutputstream也是自InputStream与OutputStream继承而来,所以他们都可以读写来自InputStream与OutputStream的数据。

FilterInputStream子类:

DataInputStream:用于从流中读取基本类型的数据,比如:char、int、long等,往往与DataOutputStream配合使用;BufferedInputStream:代表“缓冲区”,可以将数据暂存在缓冲区,使用它可以防止每次读取都进行实际的写操作;LineNumberInputStream:追踪输入流中的行号,可做调试用;PushbackInputStream:能弹出一个字节的缓冲区,能够将文件的最后一个字符返回(操作系统使用-1表示磁盘文件的结尾标记),通常作为编译器的扫描器,往往被编译器调用;FilterOutputStream子类:

DataOutputStream:用于从流中写出基本类型的数据,比如:char、int、long等,往往与DataInputStream配合使用;PrintStream:用于格式化输出,比如:java 的运行控制台打印;能够与DataOutputStream相互配合使用:DataOutputStream负责数据的存储,PrintStream负责数据的显示;BufferedOutputStream:代表“缓冲区”,可以将数据暂存在缓冲区,使用它可以防止每次都进行实际的写操作;可以使用flush()方法将缓冲区数据一次性写出;同样,在Reader 和 Writer中也提供了与之对应的类,详细如下:

 文件过滤器 子类

01字节流

字节流又分字节输入流(InputStream)和字节输出流(OutputStream),分别对应读和写;

字节输入流:FileInputStream,字节输入流的使用案例代码如下:

 字节输入流的使用案例代码

字节输入流在读取数据时使用的是read()方法,该方法还有另外的重载方法:

 字节输入流在读取数据时使用的是read()

字节输出流:FileOutputStream,字节输出流的使用案例代码如下:

 字节输出流的使用案例代码

与字节输入流在读取数据时使用的read()方法相对应的,字节输出流也提供了对应的写出数据的方法:write(),该方法也有一些重载方法:

 字节输出流也提供了对应的写出数据的

注意:字节流读写中的数据类型是字节数据类型(byte[])。

案例1,使用字节流完成文件拷贝任务。

 案例1,使用字节流完成文件拷贝任务

02字符流

字符流又分字符输入流(Reader)和字符输出流(Writer),分别对应文件读和写;需要注意的是:字符流读写中的数据类型是字符数据类型(char[]),区别于字节流中的字节类型(byte[])。

字符输入流,FileReader,字符输入流的使用案例代码如下:

 字符输入流的使用案例代码

字符输入流在读取数据时使用的是read()方法,该方法还有另外的重载方法:

 字符输入流在读取数据时使用的read()

字符输出流,FileWriter,字符输出流的使用案例代码如下:

 字符输出流的使用案例代码

字符输出流在读取数据时使用的是write()方法,该方法还有另外的重载方法:

 字符输出流在读取数据时使用的write()

案例2,使用字符流完成文件拷贝任务

 案例2,使用字符流完成文件拷贝任务

 文件拷贝

案例3,使用流完成Java 代码动态编译、运行

 案例3,使用流完成Java 代码动态运行

 buildJavaCode

 compileJavaCode

 runJavaCode

缓冲区

在上述的字符输出流的使用案例中,使用了flush()方法,该方法有何作用呢?

因为计算机访问外部设备(磁盘文件)时,要比直接访问内存慢很多,如果每次调用write()方法都要直接把数据写出到磁盘文件中,CPU会花更多的时间,计算机执行性能会大大降低。

因此,我们可以准备一个内存缓冲区,程序每次调用write()方法时,会将数据先写到内存缓冲区中,暂存于缓冲区中;当内存缓冲区满后,系统才把缓冲区中暂存的数据一次性写出到磁盘文件中。这样就能减少直接操作本地文件系统的频率,使得系统性能得以提升。

flush()方法

flush(),刷新操作,输出流中都有flush方法。该方法的作用正是把缓冲区中暂存的数据一次性写出到磁盘文件中。

使用缓冲区的好处:

提高CPU使用率,提高系统的执行性能;有机会回滚写入的数据,能避免一定的脏数据;缓冲区大小一般使用容量整数倍,可以提高IO性能;对于字节流,flush方法不是都有作用(部分字节流才有作用),对于字符流、缓冲流则都起作用。如果我们调用close方法关闭系统资源,那么,系统在关闭资源前,会先调用flush方法。

03资源关闭

资源关闭分为手动关闭和自动关闭两种:

手动关闭:手动调用流的close()方法;自动关闭:不需要手动调用close方法,不过,前提是资源对象实现了AutoClose接口;

 资源关闭案例

 资源手动关闭

 资源自动关闭

04包装类/缓冲流

字节缓冲输入流,BufferedInputStream,案例代码如下:

 字节缓冲输入流案例

字节缓冲输出流,BufferedOutputStream,案例代码如下:

 字节缓冲输出流 案例

字符缓冲输入流,BufferedReader,案例代码如下:

 字符缓冲输入流 案例

字符缓冲输出流,BufferedWriter,案例代码如下:

 字符缓冲输出流 案例

字节流、缓冲流性能测试比较:

 字节流、缓冲流性能测试比较

 testSingleByteStream

 testSingleBufferedStream

 testMultiByteStream

 testMultiBufferedStream

上述测试运行结果如下:

性能孰高孰低,测试结果已经很能说明问题了。

05转换流

由于字节流和字符流同时存在,有时候会把二者结合起来使用,甚至在二者之间实现转换;为了实现这样的功能,Java IO中提供了字节流和字符流的适配器:

InputStreamReader:可以把InputStream转换为Reader;OutputStreamWriter:可以把OutputStream转换为Writer;以下便是这个适配器—“转换流”的使用案例,案例通过文件的拷贝操作来体现,在读写的过程中,均使用了特定编码。案例代码实现如下:

 转换流 案例

为什么只有字节转字符流,却没有字符转字节流呢?原因也很简单:

字节流可以操作一切文件,包括纯文本文件、二进制文件;字符流是对字节流的增强,是用来操作纯文本使用的;字节流和字符流之间并不对等,无法实现转换,就比如C++程序可以运行C程序,但C程序却不能运行C++程序。

06数组流/内存流

面向字节的数组流/内存流:ByteArrayInputStream和ByteArrayOutputStream;该“流”会把数据暂存到内存中,以便实时读写,读写时使用的字节类型(byte[]);

ByteArrayInputStream:把数据从程序输出到内存中;ByteArrayOutputStream:把数据从内存读取到程序中;代码案例如下:

 面向字节的数组流/内存流 案例

面向字符的数组流/内存流,CharArrayReader和CharArrayWriter,该“流”会把数据暂存到内存中,以便实时读写,读写时使用的字符类型(char[]);

代码案例如下:

 面向字符的数组流/内存流 案例

面向字符串的内存流,StringReader/StringWriter,把数据临时存储到字符串中,也同样是在内存中,但数据的类型是字符串;

案例代码如下:

 面向字符串的内存流 案例

07合并流

合并流,SequenceInputStream:能够将2个或者以上的InputStream合并成一个单一的InputStream,进而进行合并操作;

 合并流 案例

08字符编码

字符编码的发展历程:

阶段1:计算机只认识数字0和1,计算机里的一切数据都是以数字来表示;因为英文符号有限,所以规定使用的字节的最高位是0,每一个字节都是以0~127之间的数字来表示,比如:A对应65,a对应97..这就是美国标准信息交换码-ASCII;

阶段2:随着计算机在全球的普及,很多国家和地区都把自己的字符引入了计算机中,比如汉字;但是ASCII中的一个字节能表示数字范围太小,不能包含所有的中文汉字,所以就规定使用两个字节来表示一个汉字;

所以决定,原有的ASCII字符的编码保持不变,仍然使用一个字节表示;为了区别一个中文字符与两个ASCII码字符:

中文字符的每个字节最高位规定为1(中文的二进制是负数),这个规范就是GB2312编码;后来在GB2312的基础上增加了更多的中文字符,比如简体中文,GBK应运而生;阶段3:新的问题产生了,在中国是认识汉字的,支持GBK编码,但是如果把GBK编码的汉字传递给其他国家,该国家的编码表中没有收录该汉字的字符,故不能正常显示,很容易就出现了乱码。

为了解决各个国家因为本地化字符编码带来的影响,把全世界所有的符号统一进行编码-Unicode编码;此时某一个字符在全世界任何地方都是固定的,比如字符:'哥',在任何地方都是以十六进制的54E5来表示。Unicode的每个编码字符都占有2个字节大小。

常见的字符集:

ASCII:每个字符占一个字节,只能包含128个符号,不能表示汉字;ISO-8859-1:每个字符占一个字节,收录西欧语言,不能表示汉字;ANSI:每个字符占两个字节,在简体中文的操作系统中,ANSI 就指的是 GB2312;GB2312/GBK/GB18030:每个字符占两个字节,中文专用编码;UTF-8:是一种针对Unicode的可变长度字符编码,又称万国码,是Unicode的实现方式之一,目前的应用率最高;UTF-8 BOM:是微软搞出来的编码,默认占3个字节,使用率并不高;编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。

互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。

存储字母,数字和汉字

存储字母和数字时无论是什么字符集都只占1个字节(因为和ASCII兼容),但是存储汉字:GBK家族占两个字节,UTF-8家族占3个字节。

存储中文时,GBK和UTF-8都是OK的。

 字符编码 案例

09

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

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

相关文章

Python基于百度智能云平台股票资讯情感分析

Python基于百度智能云平台股票资讯情感分析 全部代码和数据地址如下:Python基于百度智能云平台股票资讯情感分析 本文章详细内容如下: 文章目录 Python基于百度智能云平台股票资讯情感分析导入相应的包1.引入库2.设置账户秘钥3.导入数据4.数据合并5.百度…

10年测试老鸟总结,性能测试-性能内存瓶颈分析(超详细)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 性能测试-内存瓶颈…

【2023 年第三届长三角高校数学建模竞赛】B 题 长三角新能源汽车发展与双碳关系研究 18页论文、数据和代码

【2023 年第三届长三角高校数学建模竞赛】B 题 长三角新能源汽车发展与双碳关系研究 18页论文、数据和代码 1 题目 《节能与新能源汽车技术路线图 2.0》提出至 2035 年,新能源汽车市场占比超过 50%,燃料电池汽车保有量达到 100 万辆,节能汽车…

windows11 安装cuda和cudnn深度学习开发环境

首先先要确认自己的显卡最高能支持到cuda的版本,一般是不限制版本号的。 然后在官网地址下载: cuDNN的官网下载地址:cuDNN Archive | NVIDIA Developer CUDA 的下载地址:CUDA Toolkit Archive | NVIDIA Developer 有一点需要注…

Jetpack:DataBinding

目录 一、DataBinding简介 设置 Data Binding 数据绑定表达式 双向绑定 二、例子 MainActivity : Food: activity_main: build.gradle: 运行结果: 三、总结 一、DataBinding简介 DataBinding 是一种用于在安卓应用中实现简洁、高效的数据绑定的…

SpringMVC中的@RequestMapping注解的详细介绍过程~

RequestMapping注解的功能: 从注解名称上我们可以看出,RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系,SpringMVC接收到指定的请求,就会来找到在映射关系中对应的控制方法来处理这个…

备战秋招 | 笔试强训7

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、在()情况下适宜采用 inline 定义内联函数 A. 函数体含有循环语句 B. 函数体含有递归语句 C. 函数代码少、频繁调用 D. 函数代码多,不常调用 2、在 C 语言中&a…

数据结构(王道)——队列的应用

对树的层次遍历: 图的广度优先遍历 队列在操作系统的应用

composer的劈坑

现在是php8盛行的天下,安装php8我就不多说了,宝塔、小出面板一大堆,一键安装。真心说方便。(好吧,不打广告了),以下是针对 linux 系统 1、安装composer 安装composer之前,需要要先在…

基于SpringBoot+vue的在线BLOG网设计与实现

博主介绍: 大家好,我是一名在Java圈混迹十余年的程序员,精通Java编程语言,同时也熟练掌握微信小程序、Python和Android等技术,能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

CAN转ETHERCAT网关can协议和canfd协议

大家好,今天要跟大家分享一款自主研发的通讯网关,YC-ECT-CAN。这款产品能够将各种CAN总线和ETHERCAT网络连接起来,实现高效的数据传输和通信。那么,这款通讯网关具体有哪些功能和特点呢?接下来,我们就一起来…

【关于C++中----特殊类设计和单例模式】

文章目录 一、设计一个类,不能被拷贝1.1C98的实现方法及其弊端1.2 C11的实现方法 二、设计一个类,只能在堆上创建对象三、设计一个类,只能在栈上创建对象四、设计一个类,不能被继承五、设计一个类,只能创建一个对象(单…

【Java】理解java传参总是采用值传递/按值调用

参考《Java核心技术卷Ⅰ》 按值调用 Java所有的方法传参都是按值调用,方法得到的是所有参数值的一个拷贝。 方法参数的类型 方法参数共有两种类型 基本数据类型(数字、布尔值)对象引用 一个内部方法不可能基本数据类型,但能通…

Qt6 Qt Quick UI Prototype学习QML第一篇

Qt6 Qt Quick UI原型学习QML第一篇 开始创建项目Qt Quick UI原型简介.qmlproject文件举例Window平台小例子运行效果QML语法 了解语法 开始创建项目 创建一个具有QML入口点的Qt Quick 2 UI项目。要使用它,您需要设置一个QML运行时环境,例如gmlscene。 仅当…

学C的第二十六天【指针的进阶(二)】

相关代码gitee自取:C语言学习日记: 加油努力 (gitee.com) 接上期: 学C的第二十五天【指针的进阶(一)】_高高的胖子的博客-CSDN博客 6 . 函数指针数组 (1). 含义: 函数指针数组 是一个数组&a…

CSDN 周赛 63 期

CSDN 周赛 63 期 参赛体验63期周赛题目题目名称:小玉家的电费题目名称:收件邮箱题目名称:饿龙咆哮-逃离城堡题目名称:寻找宝藏山小结参赛体验 这次是最近难得的四个编程题的比赛了,可惜出了一个骗分题。 然后,今天早上进入考试,还好几次,连进都进不去 嗯,最后是开着…

开源代码分享(7)—考虑电动汽车可调度潜力的充电站两阶段市场投标策略(附matlab代码)

[1]詹祥澎,杨军,韩思宁等.考虑电动汽车可调度潜力的充电站两阶段市场投标策略[J].电力系统自动化,2021,45(10):86-96. 摘要:在电力市场环境下,充电站优化投标策略能降低电力成本,甚至通过售电获取收益。文中考 虑了电动汽车成为柔性储荷资源的潜力&#…

android 下载源码 一路踩坑

python 从 2.0 升级到3.0 从官网下载 pyhon3.0 安装器,然后更改配置 # Setting PATH for Python 3.8# The original version is saved in .bash_profile.pysaveexport PATH"/Library/Frameworks/Python.framework/Versions/3.11/bin:$PATH"alias python"/Libr…

h5真机调试之ios和Android和vconsole

目录 1:h5真机调试之Android01:安卓端 小米11开启开发者模式02:Android edge 2:h5真机调试之ios1:iOS Safari 3:真机链接本地项目 之 Android ( 重点 )3-1 vconsole的安装与使用 (…

计算机服务器中了360后缀勒索病毒怎么办,勒索病毒解密数据恢复

计算机服务器被360后缀勒索病毒攻击,会给企业的正常生产运转带来极大麻烦,最近,我们收到很多企业的求助,企业的服务器被360后缀勒索病毒攻击。360后缀勒索病毒是BeijingCrypt勒索家族的一种病毒,该病毒通过远程桌面攻击…