Java 流

2023-10-31

Java 流

什么是流

流是一个相对抽象的概念,所谓流就是一个传输数据的通道,这个通道可以传输相应类型的数据。进而完成数据的传输。这个通道被实现为一个具体的对象。

字符流和字节流

抽象类

  • 处理字节:InputStream OutputStream

  • 处理字符:Reader Writer

Java中字符是以Unicode形式存储的,一个字符占用两个字节,然而InputStream和OutputStream都是以字节形式读取或写出数据的,会将一个字符拆分成两个字节来读写这样会造成乱码

基础用法

在InputStream 和 Reader抽象类中都有一个抽象方法 abstract int read(),这个方法将会读入一个字节或字符,当到达输入数据块的末尾的时候返回-1,所有的输入流只要覆盖这个方法,完成具体的功能。

在OutputStream 和 Writer抽象类中都有一个抽象方法 abstract void write(int b),这个方法将会象某一个输出位置写一个字节或者字符。所有的输出流只覆盖这个方法,完成具体的输出功能。

read()和write()方法都是阻塞方法,当一个流不能被立即访问或者字节不能被成功的读出或写入的时候,当前线程将进入阻塞态直到字节确实被读入或者被写出。这样的设置保证了数据的安全性。

流的结构

输入流与输出流层次结构

输入流与输出流层次结构

Reader和Writer的层次结构

Reader和Writer的层次结构

字符集与编码

ASCII

对于西方来说,用不到字符,字节就够了。26个字母外加几个常用的符号。256个码位就够了。这就是我们常见的ASCII码表

ASCII码表

ISO/IEC 8859-1

西方世界不光英语,还有小语种。每个国家都可以定义属于自己语言的特殊编码标准,而且大小一样不超过256。因为ASCII码本身还有空位。所以就衍生出了ISO/IEC 8859-n国际标准化组织定义的一系列8位字符集。比如ISO/IEC 8859-1就是法语,芬兰语所用的西欧字符集。如下图。

ISO/IEC 8859-1

Unicode

在出现Unicode之前,几乎每一种文字都有一套自己的编码方式。同一段“字节流”,在美帝可能是"hello world",到我们天朝就变成“锟斤拷” ,“烫烫烫”了。所以“Unicode”可谓大势所趋。它的理念非常简单:全世界每个不同语言的不同字符都统一编码,全球通行。

最初,每个字符占用2个字节,总共65536(2的16次方,即一个字符)个字符空间。后来又了附加字符集。目前Unicode收录的字符规模大概在12万左右。

UTF-16

编码里最容易搞混的一件事就是:Unicode只是一套符号的编码。但计算机具体怎么读取这套编码,又是另外一件事。

比如既然Unicode常规字符集占用2个字节,系统可以每次老老实实读取两个字节。然后用一个特殊符号告诉系统某个字符属于附加字符集,需要再往后读2个字节。比如说Java系统默认的UTF-16就是就是这样编码解码的。

UTF-16

UTF-8

但上面UTF-16的缺点也很明显:就是所有英语字符“I am”也被迫用2个字节来编码。

考虑到英语是使用最广泛的语言,用2个字节为1字节信息编码,浪费了内存空间。最好是让英语保持ASCII的编码,用1个字节。汉字等其他字符才用2个或更长的字节表示。

这里就涉及到一个技术问题:怎么让系统知道一个字符是用1个还是2个还是3个字节编码的呢?这就是UTF-8做的事。

如下图所示,这里UTF-8可变长编码用到了一个小技巧:用几位冗余信息告诉系统,当前字符有没有结束,是不是还需要继续往下读下一个字节。

UTF-8冗余位

可以看到如果一个字节是以“0”开头的,说明是一个ASCII字符,只占一个字节。如果是“11”开头的,说明这个字符占用多个字节。后续每个“10”打头的字节都是这个字符的一部分。

总结

总而言之,一切都是字节流,其实没有字符流这个东西。字符只是根据编码集对字节流翻译之后的产物。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 流 的相关文章

  • Android 中的 java.util.Observable 是线程安全的吗?

    Android 中的 java util Observable 是线程安全的吗 这文档 http developer android com reference java util Observable html说只有deleteObser
  • 如何忽略 LeakCanary 中的某些类?

    有人能给我一个如何忽略 LeakCanary 中的某些类的有效示例吗 我正在查看这个示例 以忽略 LeakCanary 中第三方库中的某些类 但我不知道将其放在应用程序中的何处 我把它放在我的应用程序类中 但这些变量和方法有错误 isInA
  • FLAG_ACTIVITY_REORDER_TO_FRONT 被忽略

    我有一个包含项目列表的 FragmentActivity 当应用程序处于后台时 可以推送该项目列表 发生这种情况时 我想创建一个状态栏通知并提醒用户更新 当用户单击通知时 活动应重新排序到前面并显示在屏幕上 同时在列表底部显示新项目 所以我
  • Android 中有没有办法获取 SD 卡大小?

    欢迎大家 我已经在 Stackoverflow 和 google 上尝试过与此相关的每个问题 但没有一个有效 我已经尝试过类似下一个链接的操作 但它返回的内容与内部存储相同 如何获取外部存储 SD 卡的大小 带安装的 SD 卡 https
  • 我的 Android 设备需要安装哪个驱动程序才能运行我的应用程序?

    我购买了 intex mobile 来在真实设备中测试我的 Android 应用程序 然而 该设备不存在于 OEM USB 驱动程序列表中 android 提供的设备列表中 我检查了 intex 官方网站 但不确定到底需要安装哪个驱动程序
  • 无法在云控制台中启用 Maps SDK for Android

    我在云控制台中启用适用于 Android 的 Maps SDK 时遇到此问题 https console cloud google com https console cloud google com 它会抛出以下错误 附截图 我收到错误消
  • 使用 RxJava 限制吞吐量

    我现在遇到的情况很难解释 所以我会写一个更简单的版本来解释这个问题 我有一个Observable from 它发出一系列由ArrayList文件数量 所有这些文件都应上传到服务器 为此 我有一个函数可以完成这项工作并返回一个Observab
  • 如何更改对话框片段内的片段

    我想做一个空的DialogFragment with a LinearLayout然后更改里面的片段LinearLayout 例如 第一个片段是 3 个按钮 facebook google 电子邮件登录 的登录 当有人按下电子邮件时 第 2
  • 如何在android中画一条曲线?

    我是 Android 新手 正在开发一个关于绘制线条的示例项目 我想画一条连接两点的曲线或高架线 x1 y1 and x2 y2 我试过canvas drawArc 方法 但是RectF内的值drawArc方法只是圆的 x y 中心点 它在
  • Android - 多次实例化一个片段?

    我正在创建一个在 ListView 中显示数据的应用程序 数据分为两种类型 热门 收藏夹 我有一个活动和两个片段 片段根据类别显示项目列表 我为此使用了 ListView 然后我有两个fragment layouts 它们在设计上完全相同
  • Android Drawable 绘图性能?

    在我看来 我有一个简单的 ARGB 可绘制对象 大约需要 2 毫秒才能绘制 但我可以在 0 5 毫秒内绘制与位图相同的文件 只是一些快速代码 我真的不能认为它是一个选项 优化可绘制对象的绘制速度的最佳方法是什么 这取决于可绘制的数量以及每个
  • 如何更改 Android 12 启动屏幕中的图标形状?

    我想要矩形形状的启动屏幕图标 而不是 android 12 中的圆形形状 我不相信你可以 如果你看这里的第 3 点 https developer android com about versions 12 features splash
  • 使用 Riverpod 处理身份验证

    我正在尝试获取 Riverpod 但遇到了一些问题 我创建了一个用于登录用户的表单 并且尝试在用户登录时更改主视图 我的问题是 当我设置更改状态并导航回应用程序根目录时 新状态似乎不可用 但是 如果我保存文件或热重新加载应用程序 则新状态可
  • 如何通过 AppCompatActivity 使用 YouTube Android 播放器 API

    为了在我的应用程序中播放视频 我决定扩展 YouTube Android Player API 但问题是我的菜单消失了 因为我没有从 AppCompatActivity 扩展 问题是 如何使用 YouTube Android Player
  • 从 sqlite 和 mysql 加载数据微调器

    我试试这个tutorial http nielpoenya blogspot com 2012 08 tutorial android spinner dari database html加载Spinner from sqlite and
  • 使用 RecyclerView.Adapter 在 onBindViewHolder() 内设置 onItemClickListener

    我有一个自定义对象 学生班 public class Student private String name private String age public String getName return name public void
  • 如何从灰度字节缓冲区图像创建位图?

    我正在尝试使用新的 Android 人脸检测移动视觉 API 来处理帧图像 所以我创建了自定义检测器来获取帧并尝试调用 getBitmap 方法 但它为空 所以我访问了帧的灰度数据 有没有办法从它或类似的图像持有者类创建位图 public
  • 在android中使用BaseActivity的不同活动中的通用标头

    我想编写一次代码并在不同的活动中使用 我创建了一个Base Activity class为了那个原因 此外 不同活动中所有布局的标题都是相同的 我在以下人员的帮助下做到了这一点
  • Android Jasper 报告

    Jasper Reporting 可以集成到 Android 应用程序中吗 我正在尝试从 jrxml 文件生成 PDF CSV 文本和 XLS 报告 但是 我没有看到 Android SDK 支持 net sf jasperreports
  • 查询联系人 - 有时返回空游标

    我正在尝试查询联系人的显示名称 Override public void onActivityResult int requestCode int resultCode Intent data switch requestCode case

随机推荐

  • snipaste使用教程介绍

    snipaste是一个简单但强大的截图工具 但是很多用户下载之后都不知道怎么用 今天小编带来的内容就是snipaste使用方法教程 Win10纯净版 Win10 64位纯净版 Win10纯净精简版系统下载 系统部落 1 打开Snipaste
  • zynq开发,在SDK中自动生成的IP核驱动文件出现错误解决办法

    ZYNQ开发 在SDK中自动生成的IP核驱动文件出现错误解决办法 zynq开发 在SDK中出现IP驱动文件报错 寻找错误原因 对比 为什么出现这种情况 Block Design查看问题 最后 zynq开发 在SDK中出现IP驱动文件报错 报
  • STM32CUBEMX+FreeRTOS开发笔记3-----按键选择任务挂起

    按键初始化 和上次一样 复制上次的串口文件 改成keytask 打开cubemx工程 将PA3设置成中断线3模式 并将标签改为key1 使能中断线3 添加按键任务 生成代码即可 进入工程 查看中断线3函数 找到callback函数 因为中断
  • 《ESP32-Arduino》LVGL之输入设备详解及实例(触摸屏,实体按键,编码器,多功能按键)

    前言 好久没写博客了 一方面是平时着实没有时间 另一方面是知识还是欠缺 实在没啥技术拿得出手 其实更主要的还是懒 最近玩的比较多的就是LVGL了 自己也是做了几个小项目 后续考虑开源 考虑到网上LVGL入门教程还是比较少 特此出来写篇博客
  • Android移动开发-在Android项目里调用基于百度地图API实现定位

    基于地理位置服务的Android平台的开发对Android移动开发来说是非常重要的 基于地理位置服务的Android平台的开发是主要用于Android系统作为载体 我们可以利用定位出的位置进行许多丰富多彩的操作 比如说天气预报程序可以根据用
  • 【精华】AIGC专栏-Text/Img/Video/audio

    一 LLM专栏 大模型相关技术原理以及实战经验 liguodongiot llm action 1 ColossalAI 1 参考资料 700 亿参数 LLaMA2 训练加速 195 基础大模型最佳实践再升级 2 开源地址 https gi
  • 单片机晶振上两个电容的作用

    这两个电容叫晶振的负载电容 分别接在晶振的两个脚上和对地的电容 一般在几十皮发 它会影响到晶振的谐振频率和输出幅度 一般订购晶振时候供货方会问你负载电容是多少 晶振的负载电容 Cd Cg Cd Cg Cic C式中Cd Cg为分别接在晶振的
  • Qt无法解析的外部命令

    程序编译没有问题 上传svn后 下载整个项目后 编译错误 提示多个无法解析的外部的命令 检查的要点 程序的编译环境是否正确 程序需要的库的路径是否正确 查看库的路径是否正确时 需要查看 pro文件 但是上传svn时这些文件的内容肯定是一样的
  • 跑了这么久,汽车后市场电商终于快分出胜负了?

    图片来自网络 文 魏启扬 来源 智能相对论 ID aixdlun 汽车后市场电商是蓝海 也是火海 2015年前后 一大批创业者以互联网创新的方式闯入汽车后市场赛道 随便例举几个名字 博湃养车 E洗车 i保养 是不是都有些眼熟 其中有一些没啥
  • java动态代码方案

    方案一 https vimsky com examples detail java class javax script Invocable html import javax script Invocable 导入依赖的package包
  • PostMan的安装和使用教程

    postman的下载 官网 https www getpostman com downloads 创建账号或者用谷歌浏览器账号登录 一个demo了解一下 我做的是一个app 后台使用java做的 app通过ajax来请求后台 但是我不知道后
  • gcc编译步骤

    可以一步一步得到对应运行结果 o 其实跟重命名差不多
  • Java Collections.replaceAll()方法具有什么功能呢?

    转自 Java Collections replaceAll 方法具有什么功能呢 下文笔者讲述Collections replaceAll 方法的功能简介说明 如下所示 Collections replaceAll 方法的功能 用于替换集合
  • CPAN常见问题集

    CPAN常见问题集 想要更详细的关于perl的文档 你应该到这里来看看 www perl com 如果想看perl FAQ 可以到这里来 perlfaq cpan org 1998 2001 Elaine Ashton
  • Linux定时任务:ERROR (getpwnam() failed) 解决方法

    设置了个定时任务 但是发现没有执行 查看日志如下 root xw crm dep d tail f var log cron Aug 13 22 09 01 dep crond 1619 system RELOAD etc crontab
  • postgreSQL离线安装(rpm包方式)

    1 下载pg的rpm包 https yum postgresql org 根据选择适合的版本 这里以centos7和pg13 0为例 下载好这四个rpm包 postgresql13 server 13 0 1PGDG rhel7 x86 6
  • 开心档-软件开发入门之MongoDB 高级索引

    作者简介 每天分享MongoDB教程的学习经验 和学习笔记 座右铭 有自制力 做事有始有终 学习能力强 愿意不断地接触学习新知识 个人主页 iOS开发上架的主页 前言 本章将会讲解在数组中创建索引 需要对数组中的每个字段依次建立索引 所以在
  • 按键实现顺序一次亮2个led,顺序一次灭2个led

    c语言实现编程 keil51 点亮led灯 学习记录 在以前的基础上实现按一下 亮俩个 按一下 灭俩个 解决一直存在的问题 1 char代表的首位为符号位 1为负数 0为正数 所以有效位数为7位 uchar不区分 直接就是8位 2 关于右移
  • 100天精通Python(基础篇)——第4天:数据类型

    作者介绍 Python领域优质创作者 数据开发工程师 励志成为Python全栈工程师 关注我发现更多精彩 本文已收录于Python全栈系列专栏 100天精通Python从入门到就业 欢迎订阅 订阅后可私聊进Python全栈VIP交流群 手把
  • Java 流

    Java 流 什么是流 流是一个相对抽象的概念 所谓流就是一个传输数据的通道 这个通道可以传输相应类型的数据 进而完成数据的传输 这个通道被实现为一个具体的对象 字符流和字节流 抽象类 处理字节 InputStream OutputStre