【流 Stream】数据传输:字节流与字符流详解 文件读写必备基础知识!!!

news2024/11/16 11:50:19

目录

  • 0 引言
  • 1 流 Stream
    • 1.1 定义与作用
    • 1.2 流的分类
    • 1.3 字节流与字符流
      • 扩展知识
  • 2 IO编程实践
    • 2.1 字节流的使用
      • 小结
    • 2.2 字符流的使用
    • 2.3 总结

请添加图片描述

  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:C++专栏
  • 📜 相关文章:字符编码
  • 💥 标题:【流 Stream】数据传输:字节流与字符流详解 文件读写必备基础知识!!!
  • ❣️ 寄语:书到用时方恨少,事非经过不知难。
  • 🎈 最后:文章作者技术和水平有限,如果文中出现错误,希望大家能指正

0 引言

本文介绍一下字节流与字符流的概念以及区别,需要一些预备知识,可以更好的阅读本文。相关前置知识文章链接:预备知识文章链接

1 流 Stream

1.1 定义与作用

在计算机编程中,流(stream) 是一种抽象概念,用于表示数据在程序中的传输和处理方式。流可以看作是数据的通道,通过这个通道,数据可以按照特定的顺序从源头流向目的地。

主要用于解决数据传输和处理中的一些基本问题,例如:

  • 输入和输出:流提供了一种统一的方式来处理输入和输出。程序可以从输入流中读取数据,或将数据写入到输出流中。这使得程序可以与不同的数据源(如文件、网络、设备等)进行交互,而无需关心底层的细节。
  • 数据传输:流可以将数据分割成小的数据块(如字节或字符),并按照顺序逐个传输。这种分块传输的方式可以提高效率,特别是当处理大量数据时。
  • 缓冲机制:流还可以提供缓冲机制,将数据暂时存储在内存中,以提高读写的效率。通过缓冲,程序可以一次读取或写入多个数据块,减少了与底层数据源的频繁交互,从而提高了性能。

1.2 流的分类

根据流的不同分类标准,可以将流分为以下几类:

  • 按照流向分类
    • 输入流(Input Stream):从数据源(如文件、键盘、网络等)读取数据的流,程序可以通过输入流来接收外部数据
    • 输出流(Output Stream):向目标位置(如文件、屏幕、网络等)写入数据的流,程序可以通过输出流将数据发送到外部
  • 按照传输单位分类
    • 字节流(Byte Stream):以字节为单位进行数据传输的流。字节流主要用于处理二进制数据,如图像、音频等。在字节流中,数据被看作是一系列的字节流,可以按照字节的方式进行读取和写入。
    • 字符流(Character Stream):以字符为单位进行数据传输的流。字符流主要用于处理文本数据,如读写文本文件。在字符流中,数据被视为字符的序列,并根据字符编码将字符转换为字节进行传输。

1.3 字节流与字符流

字节流(Byte Stream)和字符流(Character Stream)是输入流(Input Stream)和输出流(Output Stream)在不同层次上的抽象。它们主要处理不同类型的数据。

  1. 字节流
    字节流以字节为单位进行数据传输和处理,适合处理二进制数据,如图像、音频、视频等。字节流将数据视为字节序列,在读取和写入时按照字节的方式进行操作,不对数据进行任何解析或处理。常见的字节流类包括InputStream和OutputStream。

  2. 字符流
    字符流以字符为单位进行数据传输和处理,适合处理文本数据,如读写文本文件。字符流将数据视为字符的序列,并根据指定的字符编码将字符转换为字节进行传输。字符流在读取和写入时会自动进行字符编码和解码。常见的字符流类包括Reader和Writer。

总结一下两者的区别

  • 数据类型:字节流处理原始字节数据,而字符流处理字符数据
  • 处理内容:字节流适合处理任意类型的二进制数据,如图像、音频等。字符流适合处理文本数据,如读写文本文件。
  • 编码和解码:字节流原封不动地传输数据,不进行编码和解码操作。字符流在传输数据之前会进行字符编码(将字符转换为字节)和解码(将字节转换为字符)
  • 接口方法:字节流提供了一些读取和写入原始字节的方法。字符流提供了一些读取和写入字符的方法,以及一些处理字符数据的辅助方法(如换行符转换)。

总体而言,字节流适用于处理底层的原始数据,而字符流适用于处理更高层次的文本数据。选择使用哪种类型的流取决于所处理数据的类型和需求。

扩展知识

所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,虽然我们看到的是字符文字(这是使用字符编码将二进制数转换成了字符),也是一个字节一个字节地读取以形成字节序列。只不过字符流会会先进行编码和解码操作。

  • 如何区分使用字节流还是字符流
  • 最简单的方法,就是使用记事本打开文件。在计算机中所有的都是一个文件,假如使用记事本打开,是看的懂的字符,那么就使用字符流传输。如果乱码的话就使用字节流传输。(前提是,使用了正确的字符编码,不然有些事文本文件的,但是没使用对应的字符编码打开也会乱码)

例如:我打开了CompileVer.pri 和 shellbrd.dll 两个文件,不需要关心文件后缀是什么。只要关心打开之后乱不乱码就行。.dll文件就乱码了。(Tips:使用记事本打开任何文件时,右下角会显示当前使用的编码方式)
在这里插入图片描述

在这里插入图片描述

2 IO编程实践

接下来使用的是QT库实现对数据的IO操作。

预备知识

  • 在Qt中,Unicode编码是默认的字符编码方式,QString类和QChar类都使用Unicode编码来表示字符。
  • 可以使用QString的toUtf8()和fromUtf8()方法将文本数据转换为UTF-8编码的字节流进行存储和读取。
  • QByteArray类是用于处理原始字节数据的类,它并不对字节数据应用任何特定的编码方式。QByteArray只是简单地存储字节序列,不涉及解码或编码操作。

2.1 字节流的使用

首先添加 QFile 和 QDebug 头文件。

#include <QFile>
#include <QDebug>
  1. 新建函数 ReadFileByByteStream 实现通过字节流的方式读取文件
void ReadWriteFile::ReadFileByByteStream()
{
    // 打开文件进行读取
    QFile inputFile("output.bin");
    if (!inputFile.open(QIODevice::ReadOnly)) {
        qDebug() << "无法打开输入文件";
        return;
    }

    // 读取字节流数据
    QByteArray  readData          = inputFile.readAll();
    QString     readData_UTF8     = QString::fromUtf8(readData);    // 将读取的字节流数据以UTF-8编码规则解码为Unicode字符

    qDebug() << "readData = "           << readData;
    qDebug() << "readData_UTF8 = "      << readData_UTF8;

    // 关闭输入文件
    inputFile.close();
}
  1. 新建函数 WriteFileByByteStream 实现通过字节流的方式写入文件
void ReadWriteFile::WriteFileByByteStream()
{
    // 打开文件进行写入
    QFile outputFile("output.bin");
    if (!outputFile.open(QIODevice::WriteOnly)) {
        qDebug() << "无法打开输出文件";
        return;
    }

    // 写入字节流数据
    QByteArray data;
    data.append("hello你好");                     // Unicode字符,UTF-8编码
    outputFile.write(data);

    // 关闭输出文件
    outputFile.close();
}
  1. 测试功能,先写入数据,再读取数据
ReadWriteFile myIOFile;
myIOFile.WriteFileByByteStream();
myIOFile.ReadFileByByteStream();
  1. 输出结果如下:
readData =  "hello\xE4\xBD\xA0\xE5\xA5\xBD"
readData_UTF8 =  "hello你好"

结果分析

  • 结果一:readData = “hello\xE4\xBD\xA0\xE5\xA5\xBD”
    • 可以看到hello是正确显示了,但是 “你好” 字符串(以UTF-8编码)缺没有正常显示,是因为 QByteArray 是没有编码解码这种操作的。所以,存储了什么数据就直接输出了什么数据。但是你可以会疑惑,明明我写入的时候是 "hello你好"字符串,为什么变成这种形式。
    • 要弄清楚,现在我们测试的是字节流输入输出,是不涉及字符编码解码操作的。所以在将 “hello你好” 数据添加给 QByteArray 时,就已经是存储的字节数据。QByteArray 中存储的就是 “hello\xE4\xBD\xA0\xE5\xA5\xBD” 数据。这一步其实是QT底层帮我们进行的编码操作,将字符串解析成二进制数。“\xE4\xBD\xA0\xE5\xA5\xBD” 字符其实就是 “你好” 以UTF-8编码下的表示。
      在这里插入图片描述
  • 结果二:readData_UTF8 = “hello你好”
    • 为什么结果二正确显示了,因为我们使用了QString::fromUtf8()函数将 QByteArray 存储的原始数据进行UTF-8规则的解码。所以就可以正常显示中文了。(注意假如解码的规则和编码规则不同,也是会乱码的)
      在这里插入图片描述

小结

Tips:编码是将字符转换为二进制形式的过程,而解码则是将二进制形式的字符转换为可读的字符。

使用字节流输入输出操作,不会对数据进行解码与编码。上面的测试程序,之所以能够正常显示出来,是因为我们对数据进行了解码,才正确显示输出。假如不进行解码直接输出的就是原始数据。

2.2 字符流的使用

同样添加 QFile 和 QDebug 头文件。

#include <QFile>
#include <QDebug>
  1. 新建函数 ReadFileByCharacterStream 实现通过字符流的方式读取文件
void ReadWriteFile::ReadFileByCharacterStream()
{
    // 打开文件进行读取
    QFile inputFile("output.txt");
    if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "无法打开输入文件";
        return;
    }

    // 创建QTextStream对象,并与输入文件关联
    QTextStream inputStream(&inputFile);

    // 读取字符流数据
    QString readData = inputStream.readAll();
    qDebug() << "readData = " << readData;

    // 关闭输入文件
    inputFile.close();
}
  1. 新建函数 WriteFileByCharacterStream 实现通过字符流的方式写入文件
void ReadWriteFile::WriteFileByCharacterStream()
{
    // 打开文件进行写入
    QFile outputFile("output.txt");
    if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "无法打开输出文件";
        return;
    }

    // 创建QTextStream对象,并与输出文件关联
    QTextStream outputStream(&outputFile);

    // 写入字符流数据
    outputStream << "Hello, World!";

    // 关闭输出文件
    outputFile.close();
}

2.3 总结

  • 所有文件的存储都是字节(byte)的存储,在磁盘上保留的是字节。
  • 所有文件都能使用字节流的方式读取,而字符流主要处理文本数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1152324.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第五章 I/O管理 六、I/O核心子系统

目录 一、核心子系统 1、I/O调度 2、设备保护 二、假脱机技术 1、脱机&#xff1a; 2、假脱机&#xff08;SPOOLing技术&#xff09;&#xff1a; 3、应用&#xff1a; 1.独占式设备&#xff1a; 2.共享设备&#xff1a; 4、共享打印机原理分析 三、总结 一、核心子系…

Android 驱动学习调试

1 Android 驱动代码编译 参考https://www.sharetechnote.com/html/Linux_DeviceDriver_Programing.html#Device_Driver_HelloWorld编译ko文件调试驱动代码&#xff0c;将ko文件push到手机上验证 相关C文件testdriver.c #include <linux/init.h> #include <linux/mod…

新恶意软件使用 MSIX 软件包来感染 Windows

人们发现&#xff0c;一种新的网络攻击活动正在使用 MSIX&#xff08;一种 Windows 应用程序打包格式&#xff09;来感染 Windows PC&#xff0c;并通过将隐秘的恶意软件加载程序放入受害者的 PC 中来逃避检测。 Elastic Security Labs 的研究人员发现&#xff0c;开发人员通常…

华为机试题:HJ8 合并表记录

目录 第一章、算法题1.1&#xff09;题目描述1.2&#xff09;解题思路与答案1.3&#xff09;牛客链接 友情提醒: 先看文章目录&#xff0c;大致了解文章知识点结构&#xff0c;点击文章目录可直接跳转到文章指定位置。 第一章、算法题 1.1&#xff09;题目描述 题目描述&…

谁知道腾讯云轻量服务器“月流量”是什么意思?

腾讯云轻量服务器月流量什么意思&#xff1f;月流量是指轻量服务器限制每月流量的意思&#xff0c;不能肆无忌惮地使用公网&#xff0c;流量超额需要另外支付流量费&#xff0c;上海/广州/北京等地域的轻量服务器月流量不够用超额部分按照0.8元/GB的价格支付流量费。阿腾云aten…

cocos tilemap的setTileGIDAt方法不实时更新

需要取消勾选 Enable Culling。同时代码添加&#xff1a;markForUpdateRenderData函数。 floor.setTileGIDAt(102427,newP.x,newP.y,0); //中心 floor.markForUpdateRenderData(); 具体问题参考官网说明&#xff1a; Cocos Creator 3.2 手册 - 项目设置

软考网工历年简答题汇总(2016下半年~2023年上半年)

目录 2016年下半年 2018年上半年 2018年下半年 2021年上半年 2022年上半年 2022年下半年 2023年上半年 2016年下半年 试题一&#xff1a; 【问题 3】若地址规划如图 1-1 所示&#xff0c;从IP 规划方案看该地址的配置可能有哪些方面的考虑&#xff1f; 答案&#xff…

博客系统的前后端实现

前面的学习中, 我们基于 HTML, CSS, JavaScript 实现了一个简单的博客系统的页面. 接下来我们基于博客系统页面来实现一个带服务器版本的博客程序. 1.准备工作 1.创建项目 2.引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns…

简单聊聊远程协同运维定义以及优势-行云管家

很多新人小伙伴对于远程协同运维不是很了解&#xff0c;今天我们就来简单聊聊远程协同运维定义以及优势。 远程协同运维定义 远程协同运维其实非常容易理解&#xff0c;主要是指计算机系统技术服务工程相关的人员通过局域网或者是其他网络对于它来进行连接&#xff0c;共同远…

【PyQt学习篇 · ⑦】:QWidget - 父子关系扩充和层级控制

文章目录 父子关系扩充常用API案例 层级控制案例 父子关系扩充 常用API childAt(x, y) 函数可以根据传入的坐标参数获取该QWidget中位于该坐标位置的子QWidget&#xff0c;如果该位置没有子QWidget则返回None。 parentWidget() 函数可以获取当前QWidget的父QWidget&#xff0…

k8s之pod

目录 一、Pod基础概念 1.1 在Kubrenetes集群中Pod有如下两种使用方式 1.2 pod的种类 二、容器的分类 &#xff08;1&#xff09;基础容器&#xff08;pause&#xff09; &#xff08;2&#xff09;初始化容器&#xff08;initcontainers&#xff09; &#xff08;3&#…

数字经济之于城市碳排放:“加速器”抑或“减速带”?

数据简介&#xff1a;数字经济是我国经济高质量发展的核心驱动力&#xff0c;在提升碳福利绩效过程中发挥重要作用&#xff0c;其在许多方面都能提供减少碳排放的机会。通过数字化和物联网技术&#xff0c;能源系统、交通运输、城市规划等领域可以实现智能化管理和优化&#xf…

VPN与IP代理用哪个好?有何区别?

当谈到网络安全和IP变更时&#xff0c;人们会想到VPN和IP代理服务器。很多人很困惑&#xff0c;它们之间有什么区别&#xff0c;应该选择哪一个呢&#xff1f;这取决于您的需求来决定哪一个更好。 一、什么是VPN与IP代理&#xff1f; VPN 是虚拟专用网络 (Virtual Private Net…

软件测试进阶篇----接口测试

接口测试 一、接口的概述 接口是什么&#xff1f; 在系统与系统之间、子系统与子系统之间数据交互的功能就是接口。 接口就是一个特定功能的函数&#xff08;方法&#xff09;&#xff0c;有参数&#xff0c;有返回值&#xff0c;调用者需要通过某种方式&#xff08;网络协议&…

CVE-2021-21234 spring-boot-actuator-logview目录遍历漏洞

0x01 影响版本 Spring-Boot-Actuator-logview < 0.2.13 0x02 漏洞分析 源码中对filename进行了校验但并未对路径进行校验 校验函数如下&#xff1a; 0x03 漏洞复现 首先开vulhub的镜像 点击下载&#xff0c;原数据包如下 送入repeater打入payload&#xff0c;复现…

【机器学习】一、机器学习概述与模型的评估、选择

机器学习简介 由来 阿瑟.萨缪尔Arthur Samuel,1952年研制了一个具有自学习能力的西洋跳棋程序&#xff0c;1956年应约翰.麦卡锡John McCarthy&#xff08;人工智能之父&#xff09;之邀&#xff0c;在标志着人工智能学科诞生的达特茅斯会议上介绍这项工作。他发明了“机器学习…

视频增强修复软件Topaz Video AI mac中文版支持功能

Topaz Video AI mac是一款使用人工智能技术对视频进行增强和修复的软件。它可以自动降噪、去除锐化、减少压缩失真、提高清晰度等等。Topaz Video AI可以处理各种类型的视频&#xff0c;包括低分辨率视频、老旧影片、手机录制的视频等等。 使用Topaz Video AI非常简单&#xff…

一文搞懂隐私计算

隐私计算 1. 安全多方计算2. 联邦学习3. 可信执行环境4. 隐私计算三类技术比较 隐私计算&#xff08;Privacy computing&#xff09;是指在保证数据不对外泄露的前提下&#xff0c;由两个或多个参与方联合完成数据分析计算相关技术的统称。 隐私计算作为跨学科技术&#xff0c…

如何优雅地单元测试 Kotlin/Java 中的 private 方法?

翻译自 https://medium.com/mindorks/how-to-unit-test-private-methods-in-java-and-kotlin-d3cae49dccd ❓如何单元测试 Kotlin/Java 中的 private 方法❓ 首先&#xff0c;开发者应该测试代码里的 private 私有方法吗&#xff1f; 直接信任这些私有方法&#xff0c;测试到…

Leetcode—169.多数元素【简单】

2023每日刷题&#xff08;十四&#xff09; Leetcode—169.多数元素 算法思想 由于nums中一定存在多数元素&#xff0c;所以将nums数组元素递增排序&#xff0c;取出位置的元素即可 实现代码 class Solution { public:int majorityElement(vector<int>& nums) {s…