禅与计算机 禅与计算机
首页
  • Java基础

    • 聊一聊java一些核心知识点
    • 聊聊java面向对象核心知识点
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 写作

    • 写好技术博客的5大核心原则:从认知科学到AI工具的全流程指南
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • 从Lucene到Elasticsearch:进化之路
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

sharkchili

计算机禅修者
首页
  • Java基础

    • 聊一聊java一些核心知识点
    • 聊聊java面向对象核心知识点
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 写作

    • 写好技术博客的5大核心原则:从认知科学到AI工具的全流程指南
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • 从Lucene到Elasticsearch:进化之路
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java基础

    • 聊一聊java一些核心知识点
    • 聊聊java面向对象核心知识点
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析 Java 泛型的魅力与机制
    • 来聊聊Java为什么只有值传递
    • 来聊聊大厂常问的SPI工作原理
    • 来聊聊session与token的区别
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • 一文带你速通HashMap底层核心数据结构红黑树
    • 深入HashMap底层理解阿里手册的遍历守则
    • LinkedHashMap源码到面试题的全解析
    • 空间预分配思想提升HashMap插入效率
    • 解析Java集合工具类:功能与实践
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
      • 输入和输出的基本概念
      • IO流常用类有那些?
      • 字节输入输出流
      • 数据流
      • 对象流
      • 字符流
        • 简介
        • 字符输入流Reader
        • 字符输出流Writer
        • 字符流异常处理的标准方式
        • FileWriter 实现数据追加
      • 字节缓冲流(文件读写增强器)
        • BufferedInputStream
        • BufferedOutputStream
      • 字符流缓冲区
        • 手写一个bufferReader实现readLine
      • 如何确定使用那种流对象
        • 明确是否有源和目的
        • 确定是读取文本还是媒体文件等
        • 是否需要提高性能
        • 案例1
        • 案例2
      • 补充:随机访问流
      • 场景设计——大文件上传
      • 参考文献
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • 聊聊Java关于IO流中的设计模式
    • 为什么流不关闭会导致内存泄漏
    • 聊聊java零拷贝的几种实现
    • Java8流式编程入门
    • Java8流式编程详解
    • 来聊聊java8的数值流
    • 聊聊Java8中的函数式编程
    • 一文速通lambda与函数式编程
    • 基于lambda简化设计模式
    • Java8函数式方法引用最佳实践
    • 使用Java8并行流的注意事项
    • 详解java数值类型核心知识点
    • 将一维数组按指定长度转为二维数组
    • 33个非常实用的JavaScript一行代码
    • 多种数组去重性能对比
    • 防抖与节流函数
    • 比typeof运算符更准确的类型判断
    • new命令原理
    • ES6面向对象
    • ES5面向对象
    • 判断是否为移动端浏览器
    • JS随机打乱数组
    • JS获取和修改url参数
    • 三级目录

  • 并发编程

  • JVM相关

  • 深入理解Spring框架

  • Java核心技术
  • Java基础
sharkchili
2022-12-17
目录

Java基础IO总结

# 输入和输出的基本概念

将数据输入到计算机内存的过程叫数据输入。

在这里插入图片描述

将数据输出到外部存储的过程叫数据输出。

在这里插入图片描述

# IO流常用类有那些?

IO流常用类大概有40个,按照数据输入输出的单位可分为字节流和字符流两个大类

  1. 字节流 InputStream、OutputStream
  2. 字符流 Reader、Writer

# 字节输入输出流

输入流常用方法

  1. read() :返回输入流中下一个字节的数据。返回的值介于 0 到 255 之间。如果未读取任何字节,则代码返回 -1 ,表示文件结束。
  2. read(byte b[ ]) : 从输入流中读取数据到数组b中,读取b数组的长度,这一点我们可以通过源码印证
public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }
1
2
3
  1. read(byte b[], int off, int len) :读取数据到b数组中,从off开始,读取len个。
  2. skip(long n) :忽略输入流中的 n 个字节 ,返回实际忽略的字节数。
  3. available() :返回输入流中可以读取的字节数。
  4. close() :关闭输入流释放相关的系统资源。

使用示例

 /**
     * 注意中文有可能出现乱码问题
     */
    @Test
    public void readTest() {
        //input.txt内容:JAVAIO_STUDY
        try (InputStream fis = new FileInputStream("input.txt")) {
            int available = fis.available();
            System.out.println("skip前输入流中可以读取的字节数" + available);//skip前输入流中可以读取的字节数12


            long skip = fis.skip(2);
            System.out.println("跳过的字节数 " + skip);//跳过的字节数 2


            available = fis.available();
            System.out.println("skip后输入流中可以读取的字节数" + available);//skip后输入流中可以读取的字节数10

            int content;
            System.out.println("读取input.txt");
            while ((content = fis.read()) != -1) {
                System.out.print((char) content);//VAIO_STUDY
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

输出流常用方法

  1. write(int b) :将特定字节写入输出流。
  2. write(byte b[ ]) : 将b数组的内容写到输出流中。
  3. write(byte[] b, int off, int len) : 将b数组中从off到off+len的内容写到输出流中。
  4. flush() :刷新此输出流并强制写出所有缓冲的输出字节。
  5. close() :关闭输出流释放相关的系统资源。

输出流使用示例

将FileOutputStream写到out.txt中

 /**
     * 输出流
     *
     * @throws Exception
     */
    @Test
    public void outputStreamTest() throws Exception {
        try (FileOutputStream fis = new FileOutputStream("out.txt")) {
            fis.write("FileOutputStream".getBytes());
        }
    }
1
2
3
4
5
6
7
8
9
10
11

# 数据流

DataInputStream 常用于文本文件有特定格式的场景读取使用,例如我们有一个文本文件内容格式依次是布尔、整形、短整型、浮点型。我们就可以使用DataInputStream,注意格式必须严格遵守,就像下面这样

/**
     * 注意读写顺序必须保持一致
     *
     * @throws Exception
     */
    @Test
    public void dataInputStreamTest() throws Exception {
        FileOutputStream fileOutputStream = new FileOutputStream("abc.txt");
        DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);

        dataOutputStream.writeBoolean(true);
        dataOutputStream.writeInt(55);
        dataOutputStream.writeShort(111);
        dataOutputStream.writeDouble(3.14);

        FileInputStream fileInputStream = new FileInputStream("abc.txt");
        DataInputStream dataInputStream = new DataInputStream(fileInputStream);
        System.out.println(dataInputStream.readBoolean());
        System.out.println(dataInputStream.readInt());
        System.out.println(dataInputStream.readShort());
        System.out.println(dataInputStream.readDouble());

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 对象流

ObjectInputStream 常用于将文件内容反序列化

/**
     * 对象流
     *
     * @throws Exception
     */
    @Test
    public void objTest() throws Exception {
        Student student = new Student();
        student.setId(1);
        student.setName("小往");
        System.out.println(student);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.data"));
        oos.writeObject(student);

        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.data"))) {
            Student student1 = (Student) ois.readObject();
            System.out.println(student1);
        }

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 字符流

# 简介

以字符的形式读取或者写入数据,从而避免一些编码问题。我们常见的编码有:

  1. utf8:英文一个字节,一个中文占3个字节。
  2. unicode:无论中文英文都占2个字节。
  3. gbk:一个英文1个字节,中文2个字节。

# 字符输入流Reader

常用方法

  1. read() : 从输入流读取一个字符。
  2. read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中,等价于 read(cbuf, 0, cbuf.length) 。
  3. read(char[] cbuf, int off, int len) :在read(char[] cbuf) 方法的基础上增加了 off 参数(偏移量)和 len 参数(要读取的最大字节数)。
  4. skip(long n) :忽略输入流中的 n 个字符 ,返回实际忽略的字符数。
  5. close() : 关闭输入流并释放相关的系统资源。

使用示例

@Test
    public void fileReaderTest() throws Exception {
        //input.txt内容JAVAIO_STUDY
        try (FileReader fis = new FileReader("input.txt")) {
            int content;
            fis.skip(2);
            while ((content = fis.read()) != -1) {
                System.out.print((char) content);

            }
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12

# 字符输出流Writer

  1. write(int c) : 写入单个字符。
  2. write(char[] cbuf) :将cbuf内容全部写到输出流。
  3. write(char[] cbuf, int off, int len) :将cbuf的内容从off到off+len写到cbuf中。
  4. write(String str) :写入字符串,等价于 write(str, 0, str.length()) 。
  5. write(String str, int off, int len) :在write(String str) 方法的基础上增加了 off 参数(偏移量)和 len 参数(要读取的最大字节数)。
  6. append(CharSequence csq) :将指定的字符序列附加到指定的 Writer 对象并返回该 Writer 对象。
  7. append(char c) :将指定的字符附加到指定的 Writer 对象并返回该 Writer 对象。
  8. flush() :刷新此输出流并强制写出所有缓冲的输出字符。
  9. close():关闭输出流释放相关的系统资源。

使用示例

 @Test
    public void writerTest() {
        try (FileWriter writer = new FileWriter("writer.txt")) {
            writer.write("LLJAVA", 2, "LLJAVA".length()-2);//将JAVA写到writer.txt
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
1
2
3
4
5
6
7
8

# 字符流异常处理的标准方式

  1. 操作代码放置到try块中。
  2. finally中关闭流,注意判空。

当然java8的之后我们完全可以使用try-with-resource

@Test
    public void writerTest() {
        FileWriter fw = null;
        try {
            fw = new FileWriter("demo.txt");
            fw.write("abcdefg");

        } catch (IOException e) {
            System.out.println("catch:" + e.toString());
        } finally {
            try {
                if (fw != null)
                    fw.close();
            } catch (IOException e) {
                System.out.println(e.toString());
            }

        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# FileWriter 实现数据追加

//传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。
		FileWriter fw = new FileWriter("demo.txt",true);

1
2
3

# 字节缓冲流(文件读写增强器)

# BufferedInputStream

BufferedInputStream会将读取到的字节流存到缓冲区中,只有当缓冲区满了,再将数据刷到内存中,注意缓冲区默认大小为8192字节,如有需要我们可以手动调整一下。如下源码所示

public class BufferedInputStream extends FilterInputStream {
    // 内部缓冲区数组
    protected volatile byte buf[];
    // 缓冲区的默认大小
    private static int DEFAULT_BUFFER_SIZE = 8192;
    // 使用默认的缓冲区大小
    public BufferedInputStream(InputStream in) {
        this(in, DEFAULT_BUFFER_SIZE);
    }
    // 自定义缓冲区大小
    public BufferedInputStream(InputStream in, int size) {
        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

public synchronized int read() throws IOException {
        if (pos >= count) {
        //缓冲空间不足情况下,该函数会通过CAS对缓冲区进行扩容,将count重新计算一下实际大小
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }
}




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# BufferedOutputStream

同样的BufferedOutputStream会将写入的数据优先存放到缓冲区,当前缓冲区空间不足时,才将缓冲区数据写到输出流中,如下源码所示

public synchronized void write(int b) throws IOException {
      if (count >= buf.length) {
            flushBuffer();
                   }
         buf[count++] = (byte)b;
      }

1
2
3
4
5
6
7

缓冲流与常规性能测试代码

可以看到走了缓冲之后,避免了没必要的IO,程序性能一下子提高不少。

 @Test
    public void readTimeTest() throws Exception {
        long start = System.currentTimeMillis();
        int content;
        try (FileInputStream fis = new FileInputStream("斗破苍穹.txt");
             FileOutputStream fos = new FileOutputStream("fos斗破苍穹.txt")) {
            /**
             * public int read() throws IOException {
             *         return read0();
             *     }
             */
            while ((content = fis.read()) != -1) {
                fos.write(content);
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("FileOutputStream:" + (end - start));


        start = System.currentTimeMillis();
        try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream("斗破苍穹.txt"));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("fos斗破苍穹.txt"))) {
            /**
             * public synchronized int read() throws IOException {
             *         if (pos >= count) {
             *             fill();
             *             if (pos >= count)
             *                 return -1;
             *         }
             *         return getBufIfOpen()[pos++] & 0xff;
             *     }
             */
            while ((content = fis.read()) != -1) {
                /**
                 * 可以看到超过了buf才执行写入
                 * public synchronized void write(int b) throws IOException {
                 *         if (count >= buf.length) {
                 *             flushBuffer();
                 *         }
                 *         buf[count++] = (byte)b;
                 *     }
                 */
                bos.write(content);
            }
        }
        end = System.currentTimeMillis();
        System.out.println("BufferedOutputStream:" + (end - start));

     
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

输出结果

   /**
         * 输出结果
         * FileOutputStream:26886
         * BufferedOutputStream:156
         */
1
2
3
4
5

# 字符流缓冲区

和字节缓冲流差不多,这里就不多介绍了。通过源码我们就知道,字符流是以字符为单位将数据存到数组中,如下源码所示:

public int read() throws IOException {
        synchronized (lock) {
            ensureOpen();
            for (;;) {
                if (nextChar >= nChars) {
                    fill();
                    if (nextChar >= nChars)
                        return -1;
                }
                if (skipLF) {
                    skipLF = false;
                    if (cb[nextChar] == '\n') {
                        nextChar++;
                        continue;
                    }
                }
                //读入缓冲区数组中
                return cb[nextChar++];
            }
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 手写一个bufferReader实现readLine

手动实现一个bufferReader,实际上readLine底层就是调用单字符读取的read方法,一旦遇到\n停止指针偏移,输出读取到的字符串,如下图:

在这里插入图片描述

代码示例

public class MyBufferReader implements Closeable {

    private Reader reader;

    public MyBufferReader(Reader reader) {
        this.reader = reader;
    }

    public MyBufferReader() {
    }


    public String readLine() throws IOException {
        StringBuilder stringBuilder = new StringBuilder();
        int readCode;
        while ((readCode = reader.read()) != -1) {
            char c = (char) readCode;
            if (c == '\n') {
                break;
            }
            if (c == '\r') {
                continue;
            }

            stringBuilder.append(c);
        }
        return stringBuilder.toString();
    }




    @Override
    public void close() throws IOException {
        reader.close();
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

测试代码

@Test
    public void myReaderTest(){
        /**
         * 文本内容
         * JAVAIO_STUDY
         * 123
         */
        try (MyBufferReader reader = new MyBufferReader(new FileReader("input.txt"))) {
            System.out.println(reader.readLine());
            System.out.println(reader.readLine());
            /**
             * 输出结果
             * JAVAIO_STUDY
             * 123
             */
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 如何确定使用那种流对象

# 明确是否有源和目的

如果有输入则要用到InputStream 或者Reader 如果有输出则要用到OutputStream 或Writer

# 确定是读取文本还是媒体文件等

如果是文本文件则是字符流,反之其他媒体文件或者对格式没有要求的文件都用字节流

# 是否需要提高性能

如果需要考虑性能就使用缓冲流包装一下

# 案例1

  1. 将一个文本文件中数据存储到另一个文件中,复制文件,请确定要使用的流。

按照题目所说因为有源,所以要使用InputStream Reader 读取的是字符所以用Reader 原设备是硬盘的文本文件,所以用FileReader 我们需要提高效率所以要用BufferedReader 所以代码为 FileReader fr = new FileReader("a.txt"); BufferedReader bufr = new BufferedReader(fr); 输出流同理得出 FileWriter fw = new FileWriter("b.txt"); BufferedWriter bufw = new BufferedWriter(fw);

# 案例2

将键盘录入的数据保存到一个文件中。

源是键盘,但是要转成文本所以用System.in转换成Reader 不需要提高效率所以InputStreamReader足矣 输出到文本且要效率所以的BufferedWriter套FileWriter

# 补充:随机访问流

随机访问流支持操作偏移量灵活改动或者读取数据如下所示

 @Test
    public void randomAccessFile() throws Exception {
        RandomAccessFile randomAccessFile = new RandomAccessFile("input.txt", "rw");

        System.out.println("读取前的偏移量:" + randomAccessFile.getFilePointer() + " 读取到的字符: " + (char) randomAccessFile.read() + " 读取后的偏移量: " + randomAccessFile.getFilePointer());
        System.out.println("读取前的偏移量:" + randomAccessFile.getFilePointer() + " 读取到的字符: " + (char) randomAccessFile.read() + " 读取后的偏移量: " + randomAccessFile.getFilePointer());
        System.out.println("读取前的偏移量:" + randomAccessFile.getFilePointer() + " 读取到的字符: " + (char) randomAccessFile.read() + " 读取后的偏移量: " + randomAccessFile.getFilePointer());

        randomAccessFile.seek(1);
        System.out.println("读取前的偏移量:" + randomAccessFile.getFilePointer() + " 读取到的字符: " + (char) randomAccessFile.read() + " 读取后的偏移量: " + randomAccessFile.getFilePointer());
        randomAccessFile.seek(0);
//        覆盖已有字符串
        randomAccessFile.write(new byte[]{'J', 'A', 'V', 'A'});
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 场景设计——大文件上传

Java实现文件分片上传 (opens new window)

# 参考文献

Java IO基础知识总结 (opens new window)

编辑 (opens new window)
上次更新: 2026/03/26, 01:05:31
深入解析CopyOnWriteArrayList的工作机制
Java三大IO模型小结

← 深入解析CopyOnWriteArrayList的工作机制 Java三大IO模型小结→

最近更新
01
基于EasyExcel实现高效导出
03-25
02
从开源框架中学习那些实用的位运算技巧
03-25
03
浅谈分布式架构设计思想和常见优化手段
03-25
更多文章>
Theme by Vdoing | Copyright © 2025-2026 Evan Xu | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×
×