Java Stream 流对象(实用技巧)
目录
一、InputStream & OutputStream
1.1、InputStream 和 OutputStream 一般使用
1.2、特殊使用
1.2.1、如何表示文件读取完毕?(DataInputStream)
1.2.2、字符读取/文本数据读取(Scanner)
1.2.3、文件的随机读写(RandomAccessFile)
一、InputStream & OutputStream
1.1、InputStream 和 OutputStream 一般使用
InputStream 有以下几个方法:
- int read():读取一个字节的数据,返回 -1 代表已经完全读完了.
- int read(byte[] b):最多读取 b.length 字节的数据到 b 中,返回实际读到的数 量;-1 代表以及读完了(这就像是你去端了个盆,去食堂让阿姨给打饭,那么阿姨肯定是按照她这饭的多少,能给你打满,就尽量给你打满),这也是实际比较常用的方法.
- int read(byte[] b, int off, int len):最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返回实际读到的数量;-1 代表以及读完了.
- void close():关闭字节流(一般会把 InputStream 写在 try() 中,就不用手动释放了~).
inputStream 只是一个抽象类,要使用还是需要具体的实现类,比如 当客户端和服务器 accept 后,获取流对象具体实现类...... 但是我们最常用的还是文件的读取,也就是 FileInputStream.
OutputStream 有以下几个方法:
- void write(int b):将指定的字节写入此输出流.
- void write(byte[] b):将 b 这个字符数组中的数据全部写入 os 中.
- int write(byte[] b, int off, int len):将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个
- void close():关闭字节流
- void flush():我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置, 调用 flush(刷新)操作,将数据刷到设备中。
OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。我们现在还是只关心写入文件中, 所以使用 FileOutputStream
Ps:FileOutputStream 有一个构造器是 new FileOutputStream(String path, boolean append),第一个参数是文件路径,第二个参数是是否以追加到末尾的形式写入,这里如果要在文件末尾追加数据,就需要填写 true 即可~
1.2、特殊使用
1.2.1、如何表示文件读取完毕?(DataInputStream)
使用 read() 方法,返回一个 int 值,这个值如果是 -1,表示文件已经全部读取完毕~
但是实际的项目中,还常常使用一种顺水推舟方式表示文件读取完毕~ 如果我们约定数据的格式,是一个 int (表示 payload 的长度 )+ payload,后面也是一样格式的数据,那么这个时候,我们就需要通过 DataInputStream (这个流对象专门用来读取数字和字节流,必须搭配 DataOutputStream 使用)中的 readInt 方法来读取 这个 int,这个方法特殊就在于读取到文件末尾以后,继续读取就会抛出 EOFException 这个异常(以往我们读取到文件末尾都是返回 -1,或者是 null。),因此这里我们就可以 通过 catch 来捕获这个异常,表示读取完成~
Ps:值得注意的是,DataInputStream / DataOutputStream 可以方便进行数字的读写(readInt、writeInt),原生的 InputStream / OutputStream 没有提供数字读写方法,需要我们自己转化.
public LinkedList<Message> loadAllMessageFromQueue(MSGQueue queue) throws IOException {//1.检查文件是否存在if(!checkQueueFileExists(queue.getName())) {throw new IOException("[MessageFileManager] 获取文件中所有有效消息时,发现队列文件不存在!queueName=" + queue.getName());}//2.获取队列中所有有效的消息synchronized (queue) {LinkedList<Message> messages = new LinkedList<>();try (InputStream inputStream = new FileInputStream(getQueueDataFilePath(queue.getName()))) {try (DataInputStream dataInputStream = new DataInputStream(inputStream)) {int index = 0;while(true) {int messageSize = dataInputStream.readInt();byte[] payload = new byte[messageSize];int n = dataInputStream.read(payload);if(n != messageSize) {throw new IOException("[MessageFileManager] 读取消息格式出错!expectedSize=" + messageSize +", actualSize=" + n);}//记录 offsetMessage message = (Message) BinaryTool.fromBytes(payload);if(message.getIsValid() == 0x0) {index += (4 + messageSize);continue;}message.setOffsetBeg(index + 4);message.setOffsetEnd(index + 4 + messageSize);messages.add(message);index += (4 + messageSize);}}} catch (EOFException e) {System.out.println("[MessageFileManager] 队列文件中有消息获取完成!queueName=" + queue.getName());}return messages;}}
1.2.2、字符读取/文本数据读取(Scanner)
对字符类型直接使用 InputStream 进行读取是非常麻烦且困难的,所以,我们使用一种我们之前比较熟悉的类来完成该工作,就是 Scanner 类。
Scanner 一般搭配 PrintWrite ,进行文本格式数据的读写,大大省去了 InputStream/OutputStream 还需要将 字节数据 和 文本数据 之间使用 UTF-8 解码转换的操作.
例如一:
// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "你好中国" 的内容public class Main {public static void main(String[] args) throws IOException {try (InputStream is = new FileInputStream("hello.txt")) {try (Scanner scanner = new Scanner(is, "UTF-8")) {while (scanner.hasNext()) {String s = scanner.next();System.out.print(s);}}}}
}
例如二:
public void writeStat(String queueName, Stat stat) {try (OutputStream outputStream = new FileOutputStream(getQueueStatFilePath(queueName))) {PrintWriter printWriter = new PrintWriter(outputStream);printWriter.write(stat.totalCount + "\t" + stat.validCount);printWriter.flush();} catch (IOException e) {throw new RuntimeException(e);}}public Stat readStat(String queueName) {Stat stat = new Stat();try (InputStream inputStream = new FileInputStream(getQueueStatFilePath(queueName))) {Scanner scanner = new Scanner(inputStream);stat.totalCount = scanner.nextInt();stat.validCount = scanner.nextInt();return stat;} catch (IOException e) {throw new RuntimeException(e);}}
1.2.3、文件的随机读写(RandomAccessFile)
之前使用 DataInputStream / DataOutputStream 都是接收 FileInputStream/FileOutputStream 进行文件的顺序读写(要么是从头读到尾,要么是在尾部追加写入......),RandomAccessFile 类就特别在可以任意指定位置进行 读/写 操作!
这里涉及到光标的概念,实际上就是你写文件的时候,你写到哪个位置,哪个位置就会有一个光标一闪一闪~
在 RandomAccessFile 中,可以使用 seek() 方法指定光标的位置(单位是字节),例如你要对一个文件中的某一段内存进行逻辑删除(没有实际删除,只是先读出来标记为无效,然后在写回文件,回收站就差不多是这个逻辑).
public void deleteMessage(MSGQueue queue, Message message) throws IOException {//1.检查队列相关文件是否存在if(!checkQueueFileExists(queue.getName())) {throw new IOException("[FileDataCenter] 删除消息时,发现队列相关文件不存在!queueName=" + queue.getName());}synchronized (message) {//2.将要删除的消息文件读出来try (RandomAccessFile randomAccessFile = new RandomAccessFile(getQueueDataFilePath(queue.getName()), "rw")) {randomAccessFile.seek(message.getOffsetBeg() - 4);int payloadSize = randomAccessFile.readInt();byte[] payload = new byte[payloadSize];int n = randomAccessFile.read(payload);if(n != payloadSize) {throw new IOException("[FileDataCenter] 读取文件格式出错!path=" + getQueueDataFilePath(queue.getName()));}//3.将待删除的消息标记为无效(isValid = 0x0)Message toDeleteMessage = (Message) BinaryTool.fromBytes(payload);toDeleteMessage.setIsValid((byte) 0x0);//4.将消息写入文件randomAccessFile.seek(message.getOffsetBeg());randomAccessFile.write(BinaryTool.toBytes(toDeleteMessage));}//5.更新统计文件Stat stat = readStat(queue.getName());stat.validCount -= 1;writeStat(queue.getName(), stat);}}
Ps:
RandomAccessFile 的有两种构造器(实际上是一种),RandomAccessFile(String name, String mode)等价于RandomAccessFile(new File(name), String mode)
mode 这个参数表示 访问模式~
➢ "r":以只读方式打开指定文件。如果试图对该RandomAccessFile执行写入方法,都将抛出IOException异常。
➢ "rw":以读、写方式打开指定文件。如果该文件尚不存在,则尝试创建该文件。
➢ "rws":以读、写方式打开指定文件。相对于"rw"模式,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
➢ "rwd":以读、写方式打开指定文件。相对于"rw"模式,还要求对文件内容的每个更新都同步写入到底层存储设备。

相关文章:
Java Stream 流对象(实用技巧)
目录 一、InputStream & OutputStream 1.1、InputStream 和 OutputStream 一般使用 1.2、特殊使用 1.2.1、如何表示文件读取完毕?(DataInputStream) 1.2.2、字符读取/文本数据读取(Scanner) 1.2.3、文件的随机…...
【用unity实现100个游戏之8】用Unity制作一个炸弹人游戏
文章目录 前言素材开始一、绘制地图二、玩家设置三、玩家移动四、玩家四方向动画运动切换 五、放置炸弹六、生成爆炸效果七、墙壁和可破坏障碍物的判断八、道具生成和效果九、玩家死亡十、简单的敌人AI十一、简单敌人AI十二、随机绘制地图十三、虚拟摇杆 最终效果待续源码完结 …...
简易版人脸识别qt opencv
1、配置文件.pro #------------------------------------------------- # # Project created by QtCreator 2023-09-05T19:00:36 # #-------------------------------------------------QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsTARGET 01_face TEMP…...
如何系统地学习 JavaScript?
前言 在学习JavaScript前需要先将Html和Css的相关知识点弄清楚,Js的很多操作是要结合Html和Css,下面我总结了Html、Css和Js的相关学习知识点供参考,希望对你有所帮助喔~ Html 文档学习 【HTML 】w3school教程 :https://www.w3school.com.…...
对称二叉树(Leetcode 101)
题目 101. 对称二叉树 思路 使用层序遍历,遍历当前层的节点时,如该节点的左(右)孩子为空,在list中添加null,否则加入左(右)孩子的值。每遍历完一层则对当前list进行判断,…...
动手学深度学习(2)-3.5 图像分类数据集
文章目录 引言正文图像分类数据集主要包介绍主要流程具体代码练习 总结 引言 这里主要是看一下如何加载数据集,并且生成批次训练的数据。最大的收获是,知道了如何在训练阶段提高模型训练的性能 增加batch_size增加num_worker数据预加载 正文 图像分类…...
C标准输入与标准输出——stdin,stdout
🔗 《C语言趣味教程》👈 猛戳订阅!!! —— 热门专栏《维生素C语言》的重制版 —— 💭 写在前面:这是一套 C 语言趣味教学专栏,目前正在火热连载中,欢迎猛戳订阅&#…...
如何将home目录空间扩充到根目录下
目录 1、查看查看磁盘使用情况2、扩容思路3、卸载并删除/home4、扩大/root逻辑卷5、扩大/文件系统6、重建/home逻辑卷7、创建/home文件系统8、将新建的文件系统挂载到/home目录下9、恢复/home并删除备份10、再次查看看磁盘存储 系统:centos7.9 1、查看查看磁盘使用…...
Ceph PG Peering数据修复
ceph数据修复 当PG完成了Peering过程后,处于Active状态的PG就可以对外提供服务了。如果该PG的各个副本上有不一致的对象,就需要进行修复。 Ceph的修复过程有两种:Recovery和Backfill。 Recovery是仅依据PG日志中的缺失记录来修复不一致的对…...
服务器上使用screen和linux的基本操作
临时换源 pip install torch1.7.1 -i https://pypi.tuna.tsinghua.edu.cn/simple some-package pip install torch1.7.1 -i http://pypi.douban.com/simple some-package临时清华源和豆瓣源 配环境的一点小问题 我们尽量是去配置能满足代码的环境,而不要想着修改…...
Kafka3.0.0版本——文件存储机制
这里写木目录标题 一、Topic 数据的存储机制1.1、Topic 数据的存储机制的概述1.2、Topic 数据的存储机制的图解1.3、Topic 数据的存储机制的文件解释 二、Topic数据的存储位置示例 一、Topic 数据的存储机制 1.1、Topic 数据的存储机制的概述 Topic是逻辑上的概念,…...
Linux如何安装MySQL
Linux安装MySQL5.7 1、下载 官网下载地址:http://dev.mysql.com/downloads/mysql/ 2、复制下面几个文件 3、检查当前系统是否安装过mysql、检查当前mysql依赖环境、检查/tmp文件夹权限 1)检查当前系统是否安装过mysql,执行安装命令前&am…...
确保网络的安全技术介绍
防火墙技术 防火墙是隔离本地网络与外界网络的一道防御系统。通常用于内部局域网 与外部广域网之间,通过限制外部网络用户以非法手段来访问内部资源,来达到保 护内部网络的安全。根据安全规则,防火墙对任何外部网络访问内部网络的行为进 …...
机器学习练习
原文章添加链接描述...
算法通关村第十九关——最小路径和
LeetCode64. 给定一个包含非负整数的 m n 网格 grid,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 输入:grid[[1,3,1],[1,5,1],[4,2,1]] 输出:7 解释:因为路径1→3→1→1→1的总和最小。 public int minPath…...
Linux 访问进程地址空间函数 access_process_vm
文章目录 一、源码解析二、Linux内核 用途2.1 ptrace请求2.2 进程的命令行 参考资料 一、源码解析 /*** get_task_mm - acquire a reference to the tasks mm** Returns %NULL if the task has no mm. Checks PF_KTHREAD (meaning* this kernel workthread has transiently a…...
selenium 动态爬取页面使用教程以及使用案例
Selenium 介绍 概述 Selenium是一款功能强大的自动化Web浏览器交互工具。它可以模拟真实用户在网页上的操作,例如点击、滚动、输入等等。Selenium可以爬取其他库难以爬取的网站,特别是那些需要登录或使用JavaScript的网站。Selenium可以自动地从Web页面…...
小程序中如何查看会员的积分和变更记录
积分是会员卡的一个重要功能,可以用于激励会员消费和提升用户粘性。在小程序中,商家可以方便地查看会员卡的积分和变更记录,以便更好地了解会员的消费行为和积分变动情况。下面将介绍如何在小程序中查看会员卡的积分和变更记录。 1. 找到指…...
音视频 ffmpeg命令直播拉流推流
直播拉流 ffplay rtmp://server/live/streamName ffmpeg -i rtmp://server/live/streamName -c copy dump.flv对于不是rtmp的协议 -c copy要谨慎使用 直播推流 ffmpeg -re -i out.mp4 -c copy flvrtmp://server/live/streamName参数:-re,表示按时间戳读取文件 参…...
Python钢筋混凝土结构计算.pdf-T001-混凝土强度设计值
以下是使用Python求解上述问题的完整代码: # 输入参数 f_ck 35 # 混凝土的特征抗压强度(单位:MPa) f_cd 25 # 混凝土的强度设计值(单位:MPa) # 求解安全系数 gamma_c f_ck / f_cd # …...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
