IO模型与NIO基础二
抽象基类之二
FilterInputStream
FilterInputStream 的作用是用来“封装其它的输入流,并为它们提供额外的功能”。
它的常用的子类有BufferedInputStream和DataInputStream。
(1) BufferedInputStream的作用就是为“输入流提供缓冲功能,以及mark()和reset()功能”。
- InputStream和Reader提供的一些移动指针的方法:
- void mark(int readlimit ); 在记录指针当前位置记录一个标记(mark)。
- boolean markSupported(); 判断此输入流是否支持mark()操作,即是否支持记录标记。
- void reset(); 将此流的记录指针重新定位到上一次记录标记(mark)的位置。
- long skip(long n); 记录指针向前移动n个字节/字符。
readlimit 参数给出当前输入流在标记位置变为非法前允许读取的字节数。
这句话的意思是说:mark就像书签一样,用于标记,以后再调用reset时就可以再回到这个mark过的地方。mark方法有个参数,通过这个整型参数,告诉系统,希望在读出多少个字符之前,这个mark保持有效。
比如说mark(10),那么在read()10个以内的字符时,reset()操作指针可以回到标记的地方,然后重新读取已经读过的数据,如果已经读取的数据超过10个,那reset()操作后,就不能正确读取以前的数据了,mark()打标记已经失效,reset()会报错。
但实际的运行情况却和JAVA文档中的描述并不完全相符。 有时候在BufferedInputStream类中调用mark(int readlimit)方法后,即使读取超过readlimit字节的数据,mark标记仍可能有效,仍然能正确调用reset方法重置。
事实上,mark在JAVA中的实现是和缓冲区相关的。只要缓冲区够大,mark后读取的数据没有超出缓冲区的大小,mark标记就不会失效。如果不够大,mark后又读取了大量的数据,导致缓冲区更新,原来标记的位置自然找不到了。
因此,mark后读取多少字节才失效,并不完全由readlimit参数确定,也和BufferedInputStream类的缓冲区大小有关。 如果BufferedInputStream类的缓冲区大小大于readlimit,在mark以后只有读取超过缓冲区大小的数据,mark标记才会失效。
public class test1 {public static void main(String[] args) throws IOException {byte[] b=new byte[] {1,2,3,4,5};//把数组转为数组输入流ByteArrayInputStream bais = new ByteArrayInputStream(b);//进行一次封装,封装时指定缓冲区大小,先指定2个字节大小BufferedInputStream bis = new BufferedInputStream(bais,2);//先读出第一个字节数据出来,指针会指向第二个字节即2上面System.out.println(bis.read()); // 1//现在指针在2上,打一个标记bis.mark(1); //按官方文档来说,读第一个数据出来后,标记会失效,reset()方法会报错,事实上不会报错,经过测试,是缓冲区bis读三个数据时,//大小缓冲区大小,缓冲区装不下了,标记才有用。System.out.println(bis.read()); //2System.out.println(bis.read()); //3bis.reset();System.out.println(bis.read()); //2}}
----------------------------------------------------------------------------
1
2
3
2
当连续读三个数据时,缓冲区(2个字节大小)装不下,标记才会失效
public class test1 {public static void main(String[] args) throws IOException {byte[] b=new byte[] {1,2,3,4,5};//把数组转为数组输入流ByteArrayInputStream bais = new ByteArrayInputStream(b);//进行一次封装,封装时指定缓冲区大小,先指定2个字节大小BufferedInputStream bis = new BufferedInputStream(bais,2);//先读出第一个字节数据出来,指针会指向第二个字节即2上面System.out.println(bis.read()); // 1//现在指针在2上,打一个标记bis.mark(1); //按官方文档来说,读第一个数据出来后,标记会失效,reset()方法会报错,事实上不会报错,经过测试,是缓冲区bis读三个数据时,//大小缓冲区大小,缓冲区装不下了,标记才有用。System.out.println(bis.read()); //2System.out.println(bis.read()); //3System.out.println(bis.read()); //4bis.reset();System.out.println(bis.read()); 没有数据打印,并报错了}}
----------------------------------------------------------------------------
1
2
3
4
Exception in thread "main" java.io.IOException: Resetting to invalid markat java.io.BufferedInputStream.reset(Unknown Source)at cn.ybzy.io.filter.test1.main(test1.java:33)
不设标记,不重设定位正常读没问题
public class test1 {public static void main(String[] args) throws IOException {byte[] b=new byte[] {1,2,3,4,5};//把数组转为数组输入流ByteArrayInputStream bais = new ByteArrayInputStream(b);//进行一次封装,封装时指定缓冲区大小,先指定2个字节大小BufferedInputStream bis = new BufferedInputStream(bais,2);System.out.println(bis.read()); // 1System.out.println(bis.read()); //2System.out.println(bis.read()); //3System.out.println(bis.read()); //4System.out.println(bis.read()); //5}}
(2) DataInputStream 是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”。
应用程序可以使用DataOutputStream(数据输出流)写入由DataInputStream(数据输入流)读取的数据。
FilterOutputStream
FilterOutputStream 的作用是用来“封装其它的输出流,并为它们提供额外的功能”。
它主要包括BufferedOutputStream, DataOutputStream和PrintStream。
(1) BufferedOutputStream的作用就是为“输出流提供缓冲功能”。
(2) DataOutputStream 是用来装饰其它输出流,将DataOutputStream和DataInputStream输入流配合使用,
“允许应用程序以与机器无关方式从底层输入流中读写基本 Java 数据类型”。
打印流PrintStream
PrintStream是用来装饰其它输出流。它能为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
打印流提供了非常方便的打印功能,可以打印任何类型的数据信息,例如:小数,整数,字符串。
之前打印信息需要使用OutputStream但是这样,所有数据输出会非常麻烦,PrintStream可以把OutputStream类重新包装了一下,使之输出更方便。
public class PrintStreamTest {public static void main(String[] args) throws FileNotFoundException {FileOutputStream fos =new FileOutputStream("c:\\c.txt");PrintStream print=new PrintStream(fos);print.print("xiongshaowen");print.print(123);print.print(12.3);print.print(new Object());print.close();}}

格式化输出:
JAVA对PrintStream功能进行了扩充,增加了格式化输出功能。直接使用Print即可。但是输出的时候需要指定输出的数据类型。

public class PrintStreamTest {public static void main(String[] args) throws FileNotFoundException {FileOutputStream fos =new FileOutputStream("c:\\c.txt");PrintStream ps=new PrintStream(fos);/*print.print("xiongshaowen");print.print(123);print.print(12.3);print.println(new Object());print.close();*///格式打印int i = 10;String s="打印流";float f = 15.5f;ps.printf("整数 %d,字符串 %s,浮点数 %f",i,s,f);ps.println();ps.printf("整数 [%d],字符串 %s,浮点数 '%f'",i,s,f);ps.close();}}

推回输入流的使用
通常我们使用输入流的时候,我们读取输入流是顺序读取,当读取的不是我们想要的怎么办,又不能放回去,虽然我们可以使用程序做其他的处理来解决,但是Java提供了推回输入流来解决这个问题,
推回输入流可以做这样子的事情:将已经读取出来的字节或字符数组内容推回到推回缓冲区里面,
从而允许重复读取刚刚读取的我们不想要的东西之前内容
注意:当程序创建一个推回输入流时需要指定推回缓冲区的大小,默认的推回缓冲区长度为一,
如果程序推回到推回缓冲区的内容超出了推回缓冲区的大小,将会引发Pushback buffer overflow 异常。
程序举例:
假如C盘下有一个aa.txt文件,内容如下:我现在只想读取aaa前面的内容,后面的我不想要。

public class TuiHuistream {public static void main(String[] args) throws IOException {//1文件流,2字符流 3输入流Reader reader = new FileReader("C:\\aa.txt");PushbackReader pr = new PushbackReader(reader,1024);//从输入流中读取数据char[] cs = new char[5];int hasReadCount = 0;String sumString="";int count=0; //计数器,看看下面读了多少次数据while((hasReadCount=pr.read(cs))!=-1) {String curString = new String(cs,0,hasReadCount);sumString =sumString+curString;count++;int aaaIndex = sumString.indexOf("aaa"); //这里我们以'aaa’为标记,推回aaa之前的内容到缓冲区中if(aaaIndex>-1) {pr.unread(sumString.toCharArray()); //把所有内容推到缓冲区中(cs)//重新把我想要的内容(即aaa之前的内容)读出来if(aaaIndex >5) {cs = new char[aaaIndex];//扩容缓冲区}pr.read(cs,0,cs.length);System.out.println("我想要的内容为:"+new String(cs));break;}else {System.out.println(new String(cs));}}System.out.println("一共读了多少次:"+count+"次");pr.close();}}
------------------------------------------------------------------------------------------------------------------------------
ccccc
ccccc
ccccc
cc
c
cccca
我想要的内容为:ccccccccccccccccc
ccccc
一共读了多少次:6次相关文章:
IO模型与NIO基础二
抽象基类之二 FilterInputStream FilterInputStream 的作用是用来“封装其它的输入流,并为它们提供额外的功能”。 它的常用的子类有BufferedInputStream和DataInputStream。 (1) BufferedInputStream的作用就是为“输入流提供缓冲功能,以及mark()和res…...
【设计模式】 单例模式(单例模式哪几种实现,如何保证线程安全,反射破坏单例模式)
单例模式 作用:单例模式的核心是保证一个类只有一个实例,并且提供一个访问实例的全局访问点。 实现方式优缺点饿汉式线程安全,调用效率高 ,但是不能延迟加载懒汉式线程安全,调用效率不高,能延迟加载双重检…...
T-SQL语言的数据库交互
T-SQL语言的数据库交互 引言 随着信息技术的不断发展,数据库在各个行业中扮演着越来越重要的角色。数据库的有效管理和优化对于企业的数据安全、效率提升和决策支持至关重要。T-SQL(Transact-SQL)作为微软SQL Server的重要扩展语言…...
【Linux系统】Ext系列磁盘文件系统二:引入文件系统(续篇)
inode 和 block 的映射 该博文中有详细解释:【Linux系统】inode 和 block 的映射原理 目录与文件名 这里有几个问题: 问题一: 我们访问文件,都是用的文件名,没用过 inode 号啊? 之前总是说可以通过一个…...
慧集通(DataLinkX)iPaaS集成平台-业务建模之域
通过左侧导航菜单〖业务建模〗→〖域〗,进入该界面;在该界面可以查看到系统中已存在的域列表。 新建域 在慧集通平台中进入【业务建模】的【域】页面,点击【新建】按钮进入新建页面;输入编码,名称、模块以及对应数据类…...
【机器学习实战】kaggle 欺诈检测---使用生成对抗网络(GAN)解决欺诈数据中正负样本极度不平衡问题
【机器学习实战】kaggle 欺诈检测---如何解决欺诈数据中正负样本极度不平衡问题https://blog.csdn.net/2302_79308082/article/details/145177242 本篇文章是基于上次文章中提到的对抗生成网络,通过对抗生成网络生成少数类样本,平衡欺诈数据中正类样本极…...
android wifi framework与wpa_supplicant的交互
android frmework直接与wpa_supplicant进行交互,使用aidl或者hidl 二、事件 framework注册事件的地方: packages/modules/Wifi/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java class SupplicantStaIfaceCallbackImpl exte…...
初学stm32 --- flash模仿eeprom
目录 STM32内部FLASH简介 内部FLASH构成(F1) FLASH读写过程(F1) 闪存的读取 闪存的写入 内部FLASH构成(F4 / F7 / H7) FLASH读写过程(F4 / F7 / H7) 闪存的读取 闪存的写入 …...
使用C语言实现栈的插入、删除和排序操作
栈是一种后进先出(LIFO, Last In First Out)的数据结构,这意味着最后插入的元素最先被删除。在C语言中,我们可以通过数组或链表来实现栈。本文将使用数组来实现一个简单的栈,并提供插入(push)、删除(pop)以及排序(这里采用一种简单的排序方法,例如冒泡排序)的操作示…...
C语言程序环境和预处理详解
本章重点: 程序的翻译环境 程序的执行环境 详解:C语言程序的编译链接 预定义符号介绍 预处理指令 #define 宏和函数的对比 预处理操作符#和##的介绍 命令定义 预处理指令 #include 预处理指令 #undef 条件编译 程序的翻译环境和执行环…...
基于机器学习随机森林算法的个人职业预测研究
1.背景调研 随着信息技术的飞速发展,特别是大数据和云计算技术的广泛应用,各行各业都积累了大量的数据。这些数据中蕴含着丰富的信息和模式,为利用机器学习进行职业预测提供了可能。机器学习算法的不断进步,如深度学习、强化学习等…...
三种文本相似计算方法:规则、向量与大模型裁判
文本相似计算 项目背景 目前有众多工作需要评估字符串之间的相似(相关)程度: 比如,RAG 智能问答系统文本召回阶段需要计算用户文本与文本库内文本的相似分数,返回前TopK个候选文本。 在评估大模型生成的文本阶段,也需要评估…...
Python语言的计算机基础
Python语言的计算机基础 绪论 在当今信息技术飞速发展的时代,编程已经成为了一种必备技能。Python凭借其简洁、易读和强大的功能,逐渐成为初学者学习编程的首选语言。本文将以Python语言为基础,探讨计算机科学的基本概念,并帮助…...
Dify应用-工作流
目录 DIFY 工作流参考 DIFY 工作流 2025-1-15 老规矩感谢参考文章的作者,避免走弯路。 2025-1-15 方便容易上手 在dify的一个桌面上,添加多个节点来完成一个任务。 每个工作流必须有一个开始和结束节点。 节点之间用线连接即可。 每个节点可以有输入和输出 输出类型有,字符串,…...
02.02、返回倒数第 k 个节点
02.02、[简单] 返回倒数第 k 个节点 1、题目描述 实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。 2、题解思路 本题的关键在于使用双指针法,通过两个指针(fast 和 slow),让 fast 指针比 slow 指针…...
Linux手写FrameBuffer任意引脚驱动spi屏幕
一、硬件设备 开发板:香橙派 5Plus,cpu:RK3588,带有 40pin 外接引脚。 屏幕:SPI 协议 0.96 寸 OLED。 二、需求 主要是想给板子增加一个可视化的监视器,并且主页面可调。 平时跑个模型或者服务,…...
怎么修复损坏的U盘?而且不用格式化的方式!
当你插入U盘时,若电脑弹出“需要格式化才能使用”提示,且无法打开或读取其中的数据,说明U盘极有可能已经损坏。除此之外,若电脑在连接U盘后显示以下信息,也可能意味着U盘出现问题,需要修复损坏的U盘&#x…...
语音技术在播客领域的应用(2)
播客是以语音为主,各种基于AI 的语音技术在播客领域十分重要。 语音转文本 Whisper Whisper 是OpenAI 推出的开源语音辨识工具,可以把音档转成文字,支援超过50 种语言。这款工具是基于68 万小时的训练资料,其中包含11.7 万小时的…...
【Linux】应用层自定义协议与序列化
🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 一:🔥 应用层 🦋 再谈 "协议"🦋 网络版计算器🦋 序列化 和 反序列化 二:🔥 重新理解 read、…...
深度学习中的张量 - 使用PyTorch进行广播和元素级操作
深度学习中的张量 - 使用PyTorch进行广播和元素级操作 元素级是什么意思? 元素级操作在神经网络编程中与张量的使用非常常见。让我们从一个元素级操作的定义开始这次讨论。 一个_元素级_操作是在两个张量之间进行的操作,它作用于各自张量中的相应元素…...
Harmonyos应用实例215: 条件概率模拟器
7. 条件概率模拟器 功能简介:通过模拟抽卡片、掷骰子等实验,展示条件概率的计算方法,验证贝叶斯定理。支持调整实验参数,实时显示概率结果和理论值对比,帮助学生理解条件概率的概念。 ArkTS代码: @Entry @Component struct ConditionalProbability {@State private...
OWL ADVENTURE Java面试题实战:手写一个简单的图像加载器
OWL ADVENTURE Java面试题实战:手写一个简单的图像加载器 最近在准备Java面试的朋友,是不是经常被问到IO、多线程这些基础?光背八股文总觉得心里没底。今天咱们换个玩法,不搞虚的,直接动手写一个能用在真实项目里的东…...
避坑指南:解决Livox Mid-360双雷达点云融合时坐标系错乱与IMU数据混杂问题
Livox Mid-360双雷达点云融合实战:坐标系校准与IMU数据分离全解析 当你在RViz中看到两个Livox Mid-360雷达的点云像醉酒的水母一样随机飘动,而IMU数据又像被搅拌机混合过的果汁——恭喜你,遇到了多传感器融合的经典难题。这不是简单的参数调整…...
避坑指南:Synopsys VCS工具安装中的5个常见错误及解决方案
Synopsys VCS工具安装避坑实战:从报错排查到环境调优 在芯片设计领域,Synopsys VCS作为业界标准的仿真工具,其安装过程却常常成为工程师们的"第一道门槛"。不同于简单的解压即用软件,VCS的安装涉及复杂的依赖关系、权限…...
为什么你的Pyd文件在Windows上总报“DLL加载失败”?系统级依赖扫描、Manifest嵌入与UCRT版本对齐终极方案
第一章:Pyd文件在Windows上的本质与加载机制Pyd 文件是 Windows 平台上 Python 的 C 扩展模块的二进制格式,其本质是遵循特定 ABI 约束的动态链接库(DLL),但被 Python 解释器以特殊方式识别和加载。它并非普通 DLL&…...
从“三次握手”到文件落地:用Wireshark抓包带你彻底搞懂C++ Socket文件传输全过程
从“三次握手”到文件落地:用Wireshark抓包带你彻底搞懂C Socket文件传输全过程 当你在浏览器下载文件时,是否好奇过数据是如何跨越网络准确无误地到达你的电脑?本文将带你用C实现一个完整的TCP文件传输程序,并通过Wireshark抓包工…...
OpenClaw成本优化方案:自建Qwen3-VL:30B替代高价多模态API
OpenClaw成本优化方案:自建Qwen3-VL:30B替代高价多模态API 1. 为什么需要关注OpenClaw的成本问题 第一次用OpenClaw完成多模态任务时,我被账单吓了一跳。当时需要处理200张产品图片的分类和描述生成,调用某商业多模态API后,费用…...
在Windows和RV1126上部署ONNX肺部分割模型:一份OpenCV DNN与RKNN的完整对比实践
跨平台肺部分割模型部署实战:OpenCV DNN与RKNN技术选型指南 当医疗影像分析遇上边缘计算,开发者们常常面临一个关键抉择:如何在保证精度的前提下,将训练好的深度学习模型高效部署到不同计算平台?本文将以肺部分割模型为…...
OpenClaw浏览器自动化:nanobot镜像实现定时抢购与价格监控
OpenClaw浏览器自动化:nanobot镜像实现定时抢购与价格监控 1. 为什么选择OpenClaw实现浏览器自动化 去年双十一期间,我为了抢购某款显卡,连续三天凌晨守着电脑刷新页面,结果还是错过了补货。这种经历让我开始寻找自动化解决方案…...
用51单片机+无源蜂鸣器播放《两只老虎》完整教程(附代码与乐理速成)
用51单片机驱动无源蜂鸣器演奏《两只老虎》全流程解析 第一次听到单片机播放音乐时,那种"机器唱歌"的奇妙感至今难忘。作为电子爱好者入门必备的趣味项目,用蜂鸣器演奏音乐不仅能巩固定时器、中断等核心知识,更能将枯燥的理论转化为…...
