当前位置: 首页 > news >正文

Java强化:IO流

一、IO流基础:

  • IO流的作用:用于读写文件、网络等数据,程序运行在内存中,输入流(I)将数据读入内存,输出流(O)将内存数据写出到磁盘或网络。
  • IO流的应用场景:包括读写文件(如记事本保存和打开文件)、游戏分数存储、文件拷贝、网络通信(消息发送和接收)等,是数据通信的基础技术。
  • IO流的分类:按方向分为输入流和输出流,按内容分为字节流和字符流。字节流以字节为单位,适合操作所有类型文件(如图片、文本复制);字符流以字符为单位,仅适合操作纯文本文件(如TXT、Java文件)。
  • IO流的四大流:包括字节输入流(从磁盘或网络以字节形式读数据到内存)、字节输出流(将程序数据以字节形式输出到磁盘或网络)、字符输入流(以字符形式读数据到内存)、字符输出流(将字符数据输出到外部),分别由Java的InputStream、OutputStream、Reader、Writer类代表。

二、文件字节输入流:

  • IO流体系分类及抽象类特点:IO流分为字节输入流、字节输出流、字符输入流和字符输出流四大体系,对应的代表类均为抽象类,不能直接使用,需使用其实现类,如FileInputStream(文件字节输入流)、FileOutputStream(文件字节输出流)等。
  • 文件字节输入流的作用:用于将磁盘文件中的数据以字节形式读入内存,不能读取网络数据。
  • 文件字节输入流的构造器:可通过文件对象或文件路径创建流管道,与目标文件接通,其中直接使用文件路径的方式更常用,因为无需构建文件对象,较为方便。
  • 文件字节输入流的read方法:有两种读取方式,一种是每次读一个字节并返回,无字节可读时返回-1;另一种是使用字节数组读取,相当于用桶来装字节,这种方式读取速度更快。
  • 每次读一个字节的代码实现及问题:通过循环读取,每次将读取的字节存入变量,若不等于-1则输出。该方式存在性能较差的问题,且读取汉字时会因截断字节导致乱码,不过作为入门代码,有助于理解IO流的基本思想。
  • 每次读多个字节的代码实现及问题:定义字节数组用于装字节,定义变量记录每次读取的字节数,通过循环读取。此方式能提升性能,减少硬盘与内存的交互次数,但读取中文时若字节数组大小设置不当,仍可能截断汉字字节导致乱码。
  • 一次性读取全部字节的方法及适用场景:使用readAllBytes方法可一次性读完文件的全部字节,能避免读取汉字时乱码,但用合读取小文,若文件过大*会,字节部组占用载内存过多而导致内存溢出。
  • 字节流与字符流的适用场景:读文本内容适合用字符流,因其按字符读取,不会出现乱码;字节流适合用于数据转移,如文件复制,将字节数据读出来转移到其他地方。

三、文件字节输出流:

  • FileOutputStream的作用:以内存为基准,将内存中的字节数据写入磁盘文件。
  • 构造器及数据写入特点:可通过文件对象或路径构建管道,默认会清空并覆盖原文件数据,若在构造器中添加参数true则可实现数据追加。
  • 写数据的方法:有三种,分别是写一个字节、写一个字节数组、写字节数组的一部分。写单个字节时,若写入像汉字这样的多字节数据会因只写第一个字节而导致乱码;写字节数组时,可先将字符串通过getBytes()编码成字节数组再写入;写字节数组部分时,需指定起始位置和写入长度。
  • 实现换行的方式:通过写入"\r\n"的字节数组来实现换行,因为"\r\n"兼容性好,能在Windows等多个平台使用,且写入时要先将其转成字节数组。
  • 使用流的注意事项:流使用完后要调用close()方法关闭,以释放内存与磁盘之间总线等底层硬件资源,提升整体性能。
  • 总结与后续:创建字节输出流管道需new FileOutputStream对象,追加数据要在构造器中声明参数true;写数据方法有写单个字节、字节数组及部分字节数组;换行需将"\r\n"转成字节数组写入;下节课将利用文件字节输入流和输出流实现文件复制。

四、字节流进行文件复制及关闭资源:

  • 字节流适合文件复制的原因:计算机中所有文件底层都是字节组成,字节流可一字不漏转移全部字节,只要复制前后文件格式一致就不会有问题,适合复制图片、视频、TXT等各种文件。
  • 字节流复制文件的步骤:先确定源文件和目标文件路径,创建文件字节输入流与源文件接通,创建文件字节输出流与目标文件接通,定义字节数组作为“桶”,从输入流读字节到数组,再从数组写入输出流,直到读完所有字节。
  • 传统关闭资源方式的问题:在复制代码中若中间出现异常,程序跳走会导致输入输出流未关闭,存在资源未释放的风险。
  • try catch finally关闭资源:将代码放try catch块,finally块无论try代码正常执行还是异常都会执行,可在finally中关闭资源;但变量在try块内是局部的,需在try外定义并初始化为null,关闭时要判断是否为null,且关闭操作可能抛异常,需再用try catch处理,代码较臃肿。
  • try with resource关闭资源:JDK7新增方式,将资源定义在try后的小括号中,用完会自动调用close方法关闭资源,简洁优雅;资源需实现Closeable或AutoCloseable接口,如FileInputStream、FileOutputStream等字节流类都实现了这些接口,可作为资源放入。

五、字符流FileReader和FileWrite:

  • 字符流介绍:字符流适合读取文本文件内容,每次读取字符,其核心实现类为文件字符输入流FileReader和文件字符输出流FileWriter,开发中常结合多态使用。
  • FileReader的作用与使用:以内存为基准,将磁盘文件中的字符读入内存,通过构造器与文件接通,提供read()方法读单个字符(返回字符编号,无字符返回-1)和read(char[])方法读多个字符(返回读取字符数,无字符返回-1),后者性能更高,且读中文不会乱码。
  • FileReader代码演示:在IDEA中创建类,使用try-with-resources创建FileReader对象并关联文件,通过字符数组读取文件内容,需注意文件编码与代码编码一致,避免乱码。
  • FileWriter的作用与使用:以内存为基准,将内存中的字符写入磁盘文件,构造器可通向文件对象或路径,提供write(int)、write(String)、write(String, int, int)、write(char[])、write(char[], int, int)等方法写字符,写换行可通过写入"\n"实现。
  • FileWriter追加与刷新:默认创建的管道是覆盖管道,追加数据需在构造器中传入true;字符输出流写出数据后需刷新或关闭流才能使数据生效,因为数据先写入内存缓冲区,刷新可将缓冲区数据写入文件,关闭流包含刷新操作且关闭后流不可用。
  • 字符流与字节流对比:文件复制用字节流,因其处理所有文件的字节数据;读文本内容用字符流,按字符读取,不会出现乱码。

六、缓冲流相关知识:

  • 缓冲流分类及作用:缓冲流分为缓冲字节流和缓冲字符流,其中缓冲字节流包括缓冲字节输入流和缓冲字节输出流,缓冲字符流包括缓冲字符输入流和缓冲字符输出流。它们的作用是提高对应低级流的性能,就像给车改装一样,改装后性能明显提高。
  • 缓冲字节流提高性能的原理:以16KB数据为例,用原始字节流读写需32次系统调用,而缓冲字节输入流和输出流自带8KB缓冲池,读时8KB8KB往内存读,写时倒满8KB同步到文件,各只需2次系统调用,总共4次,大幅减少系统调用次数,提高性能。
  • 缓冲字节流的使用:通过构造器包装低级字节流,如用BufferedInputStream包装FileInputStream得到缓冲字节输入流BIS,用BufferedOutputStream包装FileOutputStream得到缓冲字节输出流BOS,然后用BIS读、BOS写,功能不变但性能提升,且源码显示默认缓冲池大小为8192字节即8KB。
  • 缓冲字符输入流:继承Reader,为提高字符输入流性能,原理与缓冲字节流类似,读16K字符时,原始流用1K桶需16次系统调用,缓冲流自带8K桶只需2次。其用法是包装低级字符输入流,还新增按行读的功能readLine,这是读取文本优雅的方案,能避免字符数组读导致的截断问题,可用循环实现按行读取。
  • 缓冲字符输出流:提高字符输出流写数据性能,16K字符用1K桶需16次系统调用,包装成缓冲流后用8K池只需2次。用法是包装原始字符输出流,新增换行功能newLine,比写“\r\n”更优雅,且低级流的特性如追加由高级流决定。

七、性能分析、几种特殊流以及IO框架:

  • 缓冲流与低级流性能对比
    • 对比方式:分别使用低级字节流按单个字节、字节数组形式,高级缓冲字节流按单个字节、字节数组形式复制大视频,统计每种方式的耗时。
    • 性能结论:低级字节流单个字节复制最慢,几乎无法忍受;低级字节流按字节数组形式复制较慢但可接受;高级缓冲字节流单个字节复制也慢,应淘汰;高级缓冲字节流按字节数组形式复制最快。
    • 桶大小影响:将桶加大,低级管道性能可提升,不一定比缓冲管道差;桶并非越大越好,过大占用内存会影响计算机整体性能和其他程序运行。
  • 字符输入转换流
    • 作用:解决不同编码读取乱码问题,先提取文件原始字节流,再按真实字符集编码将其转换成字符输入流。
    • 构造器:第二个构造器可指定编码,将原始字节流转换为字符输入流,避免乱码。
  • 打印流
    • 种类:包括PrintStream(继承字节输出流)和PrintWriter(继承字符输出流)。
    • 功能优势:可更方便、高效地打印数据,写啥就是啥,支持换行,性能较好,API丰富,可通向文件或低级管道。
    • 追加数据:不能在PrintStream或PrintWriter构造器中加参数追加,需包装低级管道并在低级管道后配追加参数。
  • 特殊数据流
    • 作用:允许将数据和类型一并写出去,满足通信时对数据类型的需求。
    • 用法:将特殊数据输出流包装低级字节输出流,可使用writeByte、writeInt、writeDouble、writeUTF等功能;读取时对应使用readByte、readInt、readDouble等,收发要对应,不能跳读。
  • IO框架
    • 框架定义:预先写好的代码库或工具,以jar包形式体现,简化和加速开发过程。
    • 导入步骤:从官网下载框架,解压后将jar包复制到项目新建的lib文件夹,右键找到Add library将其添加到项目。
    • 功能演示:可完成文件复制、文件夹拷贝、文件删除、指定编码读取文件内容、写入数据等操作,一行代码即可实现,部分功能借鉴JDK 1.7的NIO新IO技术。

八、华容道中添加步数记录和展示:

  • 案例背景与需求:学完file和IO流后,通过综合案例巩固知识,需在基础班开发的石头迷阵游戏中,增加游戏胜利后最少步数的记录和展示功能,且该数据需长久保存。
  • 开发思路分析:第一步在游戏界面展示历史最少步数信息;第二步创建文件记录历史最少步数;第三步在玩家胜利后,比较当前步数与历史最少步数,若当前步数更少则更新文件;第四步每次启动游戏时显示历史最少步数。
  • 界面展示实现:在界面初始化时,复制当前移动步数组件并修改,用于展示历史最少步数,将历史最少步数定义为全局变量,从文件读取后展示,同时调整展示位置、字体颜色等样式。
  • 文件操作实现:在项目的SRC下创建score.txt文件,初始写入0。编写方法读取文件中的最少步数,使用缓冲字符输入流,读取后转为整数返回;编写方法将步数写入文件,需转为字符串。
  • 胜利后步数处理:玩家胜利后,读取文件中的最少步数,若为0(首次玩),则将当前胜利步数写入文件;若不为0,当前步数小于历史最少步数时也更新文件。
  • 启动时展示处理:启动游戏时,从文件读取最少步数并赋值给全局变量,用于界面展示。同时处理首次玩时的展示问题,可判断若为0则显示“没有历史部署”。
  • 功能测试与问题解决:启动游戏测试功能,若出现展示问题,通过打日志等方式排查,如确保在展示界面前读取最少步数,最终实现功能。
http://www.dtcms.com/a/279907.html

相关文章:

  • 正则表达式替换中使用 g<0> 引用整个匹配的内容
  • vim扩展与 neovim
  • IOS开发者账号如何添加 uuid 原创
  • Doris
  • 20250714--长连接应用中ORA-04061: existing state of has been invalidated
  • 迪拜金融市场交易量激增,中阿资本合作深化——阿联酋交易所系统解决方案全景解析
  • Transformer江湖录 第七章:江湖新篇 - Transformer的现代演化
  • FilterRegistationBean报错does not have type parameters。idea启动日志无明显报错提示冲突 kaki的博客
  • 力扣-25.K个一组翻转链表
  • 多线程进阶——线程安全的集合类
  • B站自动回复工具(破解)
  • Linux多进程
  • 国产IP摄像头存在隐蔽后门,攻击者可获取Root权限
  • 知识点2:MCP:python-sdk 核心概念
  • 丑团-h5-Mtgsig算法-分析
  • 技能升级--二分例题
  • 2025年大数据、建模与智能计算国际会议(ICBDMIC 2025)
  • 指针和数组(二)
  • AI 临床医学课题【总结】
  • Vue2 day08-10(智慧商城)
  • 应用系统报错:com.highgo.jdbc.util.PSQLException:bad value for long(APP)
  • DOM事件绑定时机:解决脚本提前加载导致的绑定失败
  • git modules
  • 8.6 Rag-基础工具介绍(开源工具)
  • 5、qt系统相关
  • 面试150 根节点到叶子节点数字之和
  • 机构参与度及其Python数据获取示例
  • SVD、DCT图像压缩实践
  • 020 实现一个简易 Shell
  • Java集合和字符串