Java-IO流之字节输入流详解
Java-IO流之字节输入流详解
- 一、Java IO体系与字节输入流概述
- 1.1 Java IO体系结构
- 1.2 字节输入流的核心类层次
- 1.3 字节输入流的基本工作模式
- 二、InputStream类的核心方法
- 2.1 `int read()`
- 2.2 `int read(byte[] b)`
- 2.3 `int read(byte[] b, int off, int len)`
- 2.4 `long skip(long n)`
- 2.5 `int available()`
- 2.6 `void close()`
- 三、常用字节输入流实现类
- 3.1 FileInputStream
- 3.2 ByteArrayInputStream
- 3.3 BufferedInputStream
- 3.4 DataInputStream
- 四、字节输入流的高级应用
- 4.1 实现文件复制功能
- 4.2 实现图片加密/解密功能
- 4.3 使用CheckedInputStream验证数据完整性
- 五、字节输入流的最佳实践
- 5.1 使用try-with-resources自动关闭流
- 5.2 选择合适的缓冲区大小
- 5.3 处理大文件时的性能优化
- 六、常见问题与解决方案
- 6.1 中文乱码问题
- 6.2 流关闭失败问题
- 6.3 性能瓶颈问题
Java编码中处理二进制数据是一项常见的任务,而字节输入流(Byte Input Stream)则是Java IO体系中用于读取二进制数据的核心组件。本文我将深入探讨Java中字节输入流的相关知识,从基础概念到高级应用,并结合实例代码,带你全面掌握这一重要技术。
一、Java IO体系与字节输入流概述
1.1 Java IO体系结构
Java IO(Input/Output)体系基于数据流的概念,提供了一套丰富的类和接口,用于处理各种输入输出操作。根据数据处理方式的不同,Java IO可分为:
- 字节流(Byte Stream):以字节为单位处理数据,适用于二进制文件、网络数据流等。
- 字符流(Character Stream):以字符为单位处理数据,适用于文本文件等。
1.2 字节输入流的核心类层次
字节输入流的顶层接口是java.io.InputStream
,所有字节输入流类都继承自该接口。主要的实现类包括:
FileInputStream
:用于从文件读取数据ByteArrayInputStream
:用于从内存中的字节数组读取数据PipedInputStream
:用于线程间通信的管道输入流FilterInputStream
:装饰器基类,用于增强其他输入流的功能BufferedInputStream
:提供缓冲功能,提高读取效率DataInputStream
:提供读取基本数据类型的功能CheckedInputStream
:提供校验功能,用于验证数据完整性
1.3 字节输入流的基本工作模式
字节输入流的基本工作模式是:
- 创建输入流对象,连接数据源(文件、网络等)
- 调用读取方法从流中读取数据
- 处理读取到的数据
- 关闭流,释放系统资源
二、InputStream类的核心方法
2.1 int read()
- 功能:从输入流读取一个字节的数据,返回值为0-255的整数。如果到达流的末尾,返回-1。
- 示例:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class ReadExample {public static void main(String[] args) {try (InputStream inputStream = new FileInputStream("test.txt")) {int data;while ((data = inputStream.read()) != -1) {System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();}}
}
2.2 int read(byte[] b)
- 功能:从输入流读取最多
b.length
个字节的数据到字节数组中,返回实际读取的字节数。如果到达流的末尾,返回-1。 - 示例:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class ReadByteArrayExample {public static void main(String[] args) {try (InputStream inputStream = new FileInputStream("test.txt")) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {System.out.write(buffer, 0, bytesRead);}} catch (IOException e) {e.printStackTrace();}}
}
2.3 int read(byte[] b, int off, int len)
- 功能:从输入流读取最多
len
个字节的数据到字节数组b
中,从索引off
开始存储,返回实际读取的字节数。如果到达流的末尾,返回-1。 - 示例:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class ReadByteArrayOffsetExample {public static void main(String[] args) {try (InputStream inputStream = new FileInputStream("test.txt")) {byte[] buffer = new byte[1024];int offset = 0;int bytesRead;while ((bytesRead = inputStream.read(buffer, offset, buffer.length - offset)) != -1) {offset += bytesRead;// 处理读取的数据}} catch (IOException e) {e.printStackTrace();}}
}
2.4 long skip(long n)
- 功能:跳过并丢弃输入流中的
n
个字节数据,返回实际跳过的字节数。
2.5 int available()
- 功能:返回可以从输入流中读取而不会被阻塞的估计字节数。
2.6 void close()
- 功能:关闭输入流并释放相关的系统资源。
三、常用字节输入流实现类
3.1 FileInputStream
FileInputStream
用于从文件系统中的文件读取数据,是最常用的字节输入流之一。
示例:读取文件内容
import java.io.FileInputStream;
import java.io.IOException;public class FileInputStreamExample {public static void main(String[] args) {try (FileInputStream fis = new FileInputStream("test.txt")) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = fis.read(buffer)) != -1) {String content = new String(buffer, 0, bytesRead);System.out.print(content);}} catch (IOException e) {e.printStackTrace();}}
}
3.2 ByteArrayInputStream
ByteArrayInputStream
用于从内存中的字节数组读取数据,适合处理临时数据。
示例:从字节数组读取数据
import java.io.ByteArrayInputStream;
import java.io.IOException;public class ByteArrayInputStreamExample {public static void main(String[] args) {byte[] data = {65, 66, 67, 68, 69}; // ASCII码对应A,B,C,D,Etry (ByteArrayInputStream bais = new ByteArrayInputStream(data)) {int byteValue;while ((byteValue = bais.read()) != -1) {System.out.print((char) byteValue + " ");}} catch (IOException e) {e.printStackTrace();}}
}
3.3 BufferedInputStream
BufferedInputStream
为输入流提供缓冲功能,通过减少直接与数据源的交互次数,提高读取效率。
示例:使用BufferedInputStream读取文件
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;public class BufferedInputStreamExample {public static void main(String[] args) {try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.txt"))) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = bis.read(buffer)) != -1) {System.out.write(buffer, 0, bytesRead);}} catch (IOException e) {e.printStackTrace();}}
}
3.4 DataInputStream
DataInputStream
允许应用程序以与机器无关的方式从底层输入流读取基本Java数据类型。
示例:读取二进制数据
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;public class DataInputStreamExample {public static void main(String[] args) {try (DataInputStream dis = new DataInputStream(new FileInputStream("data.bin"))) {int intValue = dis.readInt();double doubleValue = dis.readDouble();boolean booleanValue = dis.readBoolean();System.out.println("整数: " + intValue);System.out.println("双精度数: " + doubleValue);System.out.println("布尔值: " + booleanValue);} catch (IOException e) {e.printStackTrace();}}
}
四、字节输入流的高级应用
4.1 实现文件复制功能
import java.io.*;public class FileCopyExample {public static void main(String[] args) {try (InputStream in = new FileInputStream("source.txt");OutputStream out = new FileOutputStream("target.txt")) {byte[] buffer = new byte[4096];int bytesRead;while ((bytesRead = in.read(buffer)) != -1) {out.write(buffer, 0, bytesRead);}System.out.println("文件复制成功");} catch (IOException e) {e.printStackTrace();}}
}
4.2 实现图片加密/解密功能
import java.io.*;public class ImageEncryptDecrypt {private static final byte KEY = 0x55; // 加密密钥public static void main(String[] args) {try {// 加密图片encryptImage("input.jpg", "encrypted.jpg");System.out.println("图片加密完成");// 解密图片decryptImage("encrypted.jpg", "decrypted.jpg");System.out.println("图片解密完成");} catch (IOException e) {e.printStackTrace();}}public static void encryptImage(String inputFile, String outputFile) throws IOException {try (InputStream in = new FileInputStream(inputFile);OutputStream out = new FileOutputStream(outputFile)) {int byteValue;while ((byteValue = in.read()) != -1) {out.write(byteValue ^ KEY); // 异或加密}}}public static void decryptImage(String inputFile, String outputFile) throws IOException {// 解密与加密使用相同的算法encryptImage(inputFile, outputFile);}
}
4.3 使用CheckedInputStream验证数据完整性
import java.io.*;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;public class CheckedInputStreamExample {public static void main(String[] args) {try (CheckedInputStream cis = new CheckedInputStream(new FileInputStream("data.txt"), new Adler32())) {byte[] buffer = new byte[1024];while (cis.read(buffer) != -1) {// 读取数据但不处理,只是为了计算校验和}long checksum = cis.getChecksum().getValue();System.out.println("数据校验和: " + checksum);} catch (IOException e) {e.printStackTrace();}}
}
五、字节输入流的最佳实践
5.1 使用try-with-resources自动关闭流
Java 7引入的try-with-resources语句可以自动关闭实现了AutoCloseable
接口的资源,避免资源泄漏。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class TryWithResourcesExample {public static void main(String[] args) {// try-with-resources语句会自动关闭流try (InputStream inputStream = new FileInputStream("test.txt")) {int data;while ((data = inputStream.read()) != -1) {System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();}}
}
5.2 选择合适的缓冲区大小
使用缓冲区可以显著提高IO性能,但缓冲区大小需要根据具体情况选择。一般来说,4KB-8KB的缓冲区大小比较合适。
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class BufferSizeExample {public static void main(String[] args) {try (InputStream inputStream = new BufferedInputStream(new FileInputStream("large_file.txt"), 8192)) {// 使用8KB的缓冲区byte[] buffer = new byte[8192];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {// 处理数据}} catch (IOException e) {e.printStackTrace();}}
}
5.3 处理大文件时的性能优化
对于非常大的文件,应避免一次性读取整个文件到内存中,而是采用分块读取的方式。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class LargeFileProcessing {public static void main(String[] args) {try (InputStream inputStream = new FileInputStream("large_file.txt")) {byte[] buffer = new byte[1024 * 1024]; // 1MB缓冲区int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {// 处理每一块数据processChunk(buffer, bytesRead);}} catch (IOException e) {e.printStackTrace();}}private static void processChunk(byte[] buffer, int length) {// 处理数据块的逻辑}
}
六、常见问题与解决方案
6.1 中文乱码问题
字节输入流按字节读取数据,如果直接将字节转换为字符串而不指定字符编码,可能会导致中文乱码。
错误示例:
import java.io.FileInputStream;
import java.io.IOException;public class CharsetIssueExample {public static void main(String[] args) {try (FileInputStream fis = new FileInputStream("chinese.txt")) {byte[] buffer = new byte[1024];int bytesRead = fis.read(buffer);String content = new String(buffer, 0, bytesRead); // 未指定字符编码System.out.println(content); // 可能显示乱码} catch (IOException e) {e.printStackTrace();}}
}
正确示例:
import java.io.*;public class CharsetCorrectExample {public static void main(String[] args) {try (InputStreamReader isr = new InputStreamReader(new FileInputStream("chinese.txt"), "UTF-8")) {BufferedReader reader = new BufferedReader(isr);String line;while ((line = reader.readLine()) != -1) {System.out.println(line); // 正确显示中文}} catch (IOException e) {e.printStackTrace();}}
}
6.2 流关闭失败问题
如果流没有正确关闭,可能会导致资源泄漏。使用try-with-resources可以有效解决这个问题。
6.3 性能瓶颈问题
- 避免频繁调用
read()
方法,尽量使用带缓冲区的read(byte[] b)
方法。 - 对于大文件读取,使用
BufferedInputStream
提高性能。
若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ
相关文章:
Java-IO流之字节输入流详解
Java-IO流之字节输入流详解 一、Java IO体系与字节输入流概述1.1 Java IO体系结构1.2 字节输入流的核心类层次1.3 字节输入流的基本工作模式 二、InputStream类的核心方法2.1 int read()2.2 int read(byte[] b)2.3 int read(byte[] b, int off, int len)2.4 long skip(long n)2…...

从OCR到Document Parsing,AI时代的非结构化数据处理发生了什么改变?
智能文档处理:非结构化数据提出的挑战 在这个时代的每一天,无论是个人处理账单,还是企业处理合同、保险单、发票、报告或成堆的简历,我们都深陷在海量的非结构化数据之中。这类数据不像整齐排列的数据库表格那样规整,…...
【C/C++】入门grpc的idl
文章目录 grpc idl 简单介绍1. 文件结构组织规范文件命名包结构:推荐:一个文件只定义一个 service,如果 service 很复杂,可拆分多个 proto 文件。 2. 消息定义规范命名风格字段编号:示例: 3. 服务与 RPC 设…...
【Java实用工具类】手撸SqlBuilder工具类,优雅拼接动态SQL,MyBatisPlus同款风格!
📌 正文: 有时候我们项目底层是 JdbcTemplate 查询,没法像 MyBatisPlus 一样用 Wrapper 拼接条件,但我们又不想手撸字符串。那怎么办?我今天就给你整了个 SqlBuilder 工具类,支持 eq、ne、like、in、gt、l…...
宇树科技更名“股份有限公司”深度解析:机器人企业IPO前奏与资本化路径
从技术落地到资本跃迁,拆解股改背后的上市逻辑与行业启示 核心事件:股改释放的上市信号 2025年5月28日,杭州宇树科技有限公司正式更名“杭州宇树科技股份有限公司”,市场主体类型变更为“股份有限公司”。尽管官方称为常规运营调…...

Inno Setup 安装向导各个页面详解
概览 表中描述了使用Inno Setup生成的安装包在安装过程中各个页面的字段和对应的说明信息。后文会对各个页面的参数做进一步解释说明。 字段说明wpWelcome欢迎页wpLicense许可协议wpPassword密码wpInfoBefore信息wpUserInfo用户信息wpSelectDir选择目标位置wpSelectComponent…...
转战web3远程工作的英语学习的路线规划
目录 一、明确学习目标与定位 二、基础阶段(0 - 6个月) (一)词汇积累 (二)语法学习 (三)听力与口语 三、进阶阶段(6 - 18个月) (一…...

OPENCV重点结构体Mat的讲解
一、Opencv的作用 OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C 类构成,同时提供了Pytho…...
Java 创建线程池的几种方式
在 Java 中创建线程池主要通过 java.util.concurrent 包下的 ExecutorService 接口及其实现类。以下是创建线程池的几种常见方式: ✅ 1. 使用 Executors 工具类(最简单) ExecutorService executor Executors.newFixedThreadPool(10);常用方…...

【趣味Html】第11课:动态闪烁发光粒子五角星
打造炫酷的动态闪烁发光粒子五角星效果 前言 在现代Web开发中,视觉效果的重要性不言而喻。今天我们将深入探讨如何使用HTML5 Canvas和JavaScript创建一个令人惊艳的动态闪烁发光粒子五角星效果。这个项目不仅展示了Canvas的强大功能,还涉及了粒子系统、…...
AnyIO Event:异步编程中的同步利器
在异步编程的世界里,任务之间的通信和协调是一个常见的需求。AnyIO 提供的 Event 类,为这一需求提供了一个强大而简洁的解决方案。本文将深入探讨 anyio.Event 的使用方法、特点以及在实际应用中的最佳实践。 一、AnyIO Event 概述 anyio.Event 是 Any…...

CFTel:一种基于云雾自动化的鲁棒且可扩展的远程机器人架构
中文标题: CFTel:一种基于云雾自动化的鲁棒且可扩展的远程机器人架构 英文标题: CFTel: A Practical Architecture for Robust and Scalable Telerobotics with Cloud-Fog Automation 作者信息 Thien Tran, Jonathan Kua, Minh Tran, Hongh…...

Educational Codeforces Round 179 (Rated for Div. 2)
CF2111,简单手速场 A. Energy Crystals 贪心,每次最小值会乘2,直接模拟即可,复杂度 O ( log n ) O(\log n) O(logn) void solve(){int x;cin>>x;multiset<int> s{0,0,0};int res0;while(*s.begin()<x){int x*s.begin();s…...

完成一个可交互的k8s管理平台的页面开发
使用deepseek完成设计一个k8s管理平台,关键词如下: 完成一个可交互的k8s管理平台的页面开发Kubernetes 管理平台页面设计 下面是一个基于现代Web技术的可交互Kubernetes管理平台的页面设计方案,使用React作为前端框架,配合Ant De…...
多线程编程技术解析及示例:pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock
多线程编程技术解析及示例:pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock 摘要 本文深入解析了多线程编程中 pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock 三个函数的功能、使用场景及注意事项,并通…...
vue实现点击单选或者多选模式
toggleSelect(item) { if (!this.single) { // 多选模式 const itemIndex this.selectedItems.findIndex( (selectedItem) > selectedItem.userId item.userId ); // 假设每个对象都有一个唯一的id属性 if (itemIndex ! -1) { this.selectedItems.splice(itemIndex, 1); }…...

Windows系统工具:WinToolsPlus 之 SQL Server 日志清理
使用软件时提示数据库事务日志已满, 使用WinToolsPlus 数据库页签 先设置 数据源 , 选择 需要清理日志的数据库, 点击 数据库日志清理 即可。 下载地址: http://v.s3.sh.cn/archives/2279.html...

在Windows11上安装 Ubuntu WSL
不想安装虚拟机,想在Windows11上运行Linux。网上虽有教程,但是图片明显都是老图,与Windows11还是有些差异。网上缺乏一个齐全的真正的Windows11运行Linux的教程。 一、在Windows上的设置 1. 在window11的搜索框内(所有你找不到的应用都可以用这个搜索功能),搜索&q…...

嵌入式Linux之RK3568
系统烧写镜像。 1、直接使用正点原子官方的updata.img(MIDP) 进入瑞芯微发开工具RKDevTool,选择升级固件,上传到固件,记住这里要进入maskrom模式或者是loader模式,进入该模式之后点击升级即可。 2、烧入自己制作的镜像(单独、一…...
Elasticsearch的插件(Plugin)系统介绍
Elasticsearch的插件(Plugin)系统是一种扩展机制,允许用户通过添加自定义功能来增强默认功能,而无需修改核心代码。插件可以提供从分析器、存储后端到安全认证、机器学习等各种功能,使Elasticsearch能够灵活适应不同的应用场景和业务需求。 一、插件的核心特点 模块化扩展…...
提取 PDF 文件中的文字以及图片中的文字
Adobe 提供了多种方案可以快速提取 PDF 文件中的文字以及图片中的文字,主要依赖其 Acrobat 系列产品和 OCR(光学字符识别)技术。以下是具体解决方案的概述,涵盖了文字和图片文字的提取方法: 1. 提取 PDF 中的文字 如果…...

JavaScript性能优化实战技术
目录 性能优化核心原则 代码层面优化 加载优化策略 内存管理实践 及时解除事件监听 避免内存泄漏模式 渲染性能调优 使用requestAnimationFrame优化动画 批量DOM操作减少回流 性能监控工具 现代API应用 缓存策略实施 性能优化核心原则 减少资源加载时间 避免阻塞主…...
LeetCode 热题 100 739. 每日温度
LeetCode 热题 100 | 739. 每日温度 大家好,今天我们来解决一道经典的算法题——每日温度。这道题在 LeetCode 上被标记为中等难度,要求我们找到一个数组,其中每个元素表示从当前天开始,下一个更高温度出现的天数。如果之后没有更…...

网页前端开发(基础进阶3--Vue)
Vue3 Vue是一款用于构建用户界面的渐进式的JavaScript框架。 Vue由2部分组成:Vue核心包,Vue插件包 Vue核心包包含:声明式渲染,组件系统。 Vue插件包:VueRouter(客户端路由),Vuex…...

tryhackme——Abusing Windows Internals(进程注入)
文章目录 一、Abusing Processes二、进程镂空三、线程劫持四、DLL注入五、Memory Execution Alternatives 一、Abusing Processes 操作系统上运行的应用程序可以包含一个或多个进程,进程表示正在执行的程序。进程包含许多其他子组件,并且直接与内存或虚…...
【游戏科学】游戏开发中数学算法的核心与应用
一、游戏科学(Game Science) 涉及大量数学算法和模型,用于实现物理模拟、图形渲染、人工智能、路径规划、碰撞检测等核心功能。 1.1、图形渲染与几何计算 1. 三维变换(3D Transformations) 矩阵变换: 模…...
【Day44】
DAY 44 预训练模型 知识点回顾: 预训练的概念常见的分类预训练模型图像预训练模型的发展史预训练的策略预训练代码实战:resnet18 作业: 尝试在cifar10对比如下其他的预训练模型,观察差异,尽可能和他人选择的不同尝试通…...

基于 Alpine 定制单功能用途(kiosk)电脑
前言 故事回到 7 年前, 在网上冲浪的时候发现了一篇介绍使用 Ubuntu 打造 kiosk 单功能用途电脑的文章, 挺好玩的, 就翻译了一下并比葫芦画瓢先后用了 CentOS 7, ArchLinux 进行了实现. 历史文章: 翻译 - 使用Ubutnu14.04和Chrome打造单功能用途电脑(大屏展示电脑) 使用CentOS…...

知识图谱系统功能实现,技术解决方案,附源码
基于Java、Neo4j和ElasticSearch构建的医疗知识图谱知识库,是一个融合图数据库技术与搜索引擎的智能化医疗知识管理系统。该系统以Neo4j图数据库为核心,利用其高效的图结构存储能力,将疾病、症状、药品、检查项目、科室等医疗实体抽象为节点&…...
第12节 Node.js 函数
在JavaScript中,一个函数可以作为另一个函数接收一个参数。我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数。 Node.js中函数的使用与Javascript类似,举例来说,你可以这样做: funct…...