目录

问题缘由

背后原理

C#代码示例

总结


问题缘由

由于公司需求,需要读取游戏Redis数据做内外网数据迁移,没有与游戏组过多的沟通。  使用的数据类型是Hash, key是string,value是byte[]。以前对于编码的理解是:计算机底层存储的永远是01的二进制数据,编码是一种对于计算机二进制数据的字符映射,也就是约定好哪个值对应哪个字符。是为了便于在显示器上展示。

那么基于这个理解,我就以为 不需要关心存储的数据类型,因为我不需要用到数据,我只是负责做数据的搬运。于是我用的是HGetAsync方法去读的字符串。然后HSetAsync把数据存到另一个Redis。结果发现数据发生了编码。基于我上边对于编码的理解,也就是按照不同的编码读取字符串,只是显示器上会乱码,但是底层的01二进制没有发生变化,这次问题打破了我的认知。

背后原理

当一个byte[]在计算机中存储时,它就是以二进制形式保存的。如果这个byte[]中的每一个字节代表的是ASCII码(一个字节表示一个字符),那么它在不同的编码下读取应该没有问题。但是,如果它代表的是Unicode字符集(UTF-8和UTF-16等),那么在不同的编码下读取就会发生问题。因为不同的编码方式对存储方式和字节长度都有不同的要求。

以UTF-8为例,它对不同字符分配的位数不同。对于ASCII字符,UTF-8使用一个字节表示,而对于其他字符,它需要两个字节、三个字节或四个字节来表示。因此,在按照UTF-8格式读取一个byte[]时,如果它的编码确实是UTF-8,那么就可以读取正确的字符。但是,如果重新以UTF-8的格式存储它时,就会按照UTF-8的编码方式重新把这个字符转换成二进制。如果这个字符之前的编码不是UTF-8,那么它在转换为UTF-8的二进制时,就会变成不同的值,因此数据也就变了。

C#代码示例

var data = Encoding.UTF32.GetBytes("爱");
var word = Encoding.UTF8.GetString(data);
var word1 = Encoding.UTF32.GetString(data); File.WriteAllText($@"{AppDomain.CurrentDomain.BaseDirectory}/code.txt", word);
File.WriteAllText($@"{AppDomain.CurrentDomain.BaseDirectory}/code1.txt", word1); foreach (var d in File.ReadAllBytes($@"{AppDomain.CurrentDomain.BaseDirectory}/code.txt"))
{
Console.WriteLine(d);
}
Console.WriteLine("------------"); foreach (var d in File.ReadAllBytes($@"{AppDomain.CurrentDomain.BaseDirectory}/code1.txt"))
{
Console.WriteLine(d);
}
 

例如,我们有一个Unicode字符“爱”,其二进制表示为:0000 0100 1110 0111。按照UTF-8编码的规则,在存储这个字符时,我们需要使用3个字节的二进制数据:1110XXXX 10XXXXXX 10XXXXXX(X表示对应字符的二进制数据的高位)

我们将其存储到一个byte[]中,再将其存储到文件中。然后按照UTF-8的格式读取,解析出Unicode字符“爱”,再将其按照UTF-8的格式存储回文件。这时,由于使用了UTF-8编码,我们需要将Unicode字符“爱”转换为UTF-8编码的二进制数据,即,使用3个字节的二进制数据:11100100 10101110 10011111。

通过运行代码,可以看到,由于存储使用了UTF-8编码,而读取和重新存储又使用了UTF-8编码,因此二进制数据发生了变化。

总结

当一个byte[]在计算机中存储时,它就是以二进制形式保存的。如果这个byte[]中的每一个字节代表的是ASCII码(一个字节表示一个字符),那么它在不同的编码下读取应该没有问题。但是,如果它代表的是Unicode字符集(UTF-8和UTF-16等),那么在不同的编码下读取就会发生问题。

【踩坑记录】字节流数据按照string的方式读取然后按照string的方案存储,编码导致二进制数据发生变化,原理记录的更多相关文章

  1. [19/05/07-星期二] JDBC(Java DataBase Connectivity)_CLOB(存储大量的文本数据)与BLOB(存储大量的二进制数据)

    一. CLOB(Character Large Object ) – 用于存储大量的文本数据 – 大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式来处理的.而非一般的字段,一次 ...

  2. BLOB存储图片文件二进制数据是非对错

    子在一天一天虚度,生活也在一天一天中茫然 做人做事哪能尽如人意,付出多少收获多少虽然存在偏颇,但是不劳而获的心态是万万不对的,更不能去怨天尤人,低调为人.做好自己就可以了 改进你的系统的最好的方法是先 ...

  3. vue+ vue-router + webpack 踩坑之旅

    说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案   老司机可以忽略下面的内容了 1)起因  考虑到数据分离的问题  因为server是express搭的   自然少 ...

  4. 背水一战 Windows 10 (89) - 文件系统: 读写文本数据, 读写二进制数据, 读写流数据

    [源码下载] 背水一战 Windows 10 (89) - 文件系统: 读写文本数据, 读写二进制数据, 读写流数据 作者:webabcd 介绍背水一战 Windows 10 之 文件系统 读写文本数 ...

  5. XML中二进制数据的处理方法

    原文链接:http://www.west263.com/www/info/22308-1.htm 在xml中,所有的数据都是以文本的形式来显示,但是二进制数据不能直接以文本格式来表示,那xml又是怎么 ...

  6. Android学习笔记(十二)——使用意图传递数据的几种方式

    使用意图传递数据的几种方式 点此获取完整代码 我们除了要从活动返回数据,也经常要传递数据给活动.对此我们能够使用Intent对象将这些数据传递给目标活动. 1.创建一个名为PassingData的项目 ...

  7. Erlang 位串和二进制数据

    http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=25876834&id=3300393 因为在本人工作中,服务端Erla ...

  8. 讨论贴:Sqlserver varbinary 是二进制数据,却是十六进制的表现形式

    首先创建一个数据表 CREATE TABLE [dbo].[log_info]( [id] [,) NOT NULL, [info] [varchar]() NULL, [info1] [varbin ...

  9. 认识Js中的二进制数据

    Blob 在项目中涉及到要对html原生的audio组件进行样式复写,因此需要重新实现audio的一些功能,比如下载.实现一个下载大致的思路是服务端返回一段音频的二进制数据,客户端将其存放在Blob中 ...

  10. 转载:【原译】Erlang构建和匹配二进制数据(Efficiency Guide)

    转自:http://www.cnblogs.com/futuredo/archive/2012/10/19/2727204.html Constructing and matching binarie ...

随机推荐

  1. ZIP64压缩扩展的兼容性问题

    一.ZIP压缩的两种规范 zip64 格式是标准 zip 格式的扩展,实际上消除了 zip 存档中文件大小和数量的限制. 每种格式允许的最大值总结如下: Standard Format Zip64 F ...

  2. Java面试——Nginx

    一. 二.Nginx 的优点 [1]速度更快:这表现在两个方面:一方面,在正常情况下,单次请求会得到更快的响应:另一方面,在高峰期(如有数以万计的并发请求),Nginx 可以比其他 Web服务器更快地 ...

  3. JetBrains 2022全家桶-激活

    ## JetBrains 全家桶 激活教程 https://tech.souyunku.com/?page_id=50199

  4. PyQt5学习 (2)--QWidget(上)

    描述:   1.所有可视控件的基类   2.是一个最简单的空白控件   3.控件时用户界面的最小元素:接收各种事件.绘制在桌面上,展示给用户看   4.每个控件都是矩形的,它们按Z轴顺序排序   5. ...

  5. 搭建私有YUM仓库_及_内网镜像站

    搭建私有YUM仓库_及_内网镜像站 搭建私有YUM仓库(自己定制的rpm包)私有yum仓库环境系统版本:centos7.4 IP:192.168.1.47 #最好能上公网 私有yum仓库服务端配置 第 ...

  6. 快速部署Ceph分布式高可用集群

    快速部署Ceph分布式高可用集群 Ceph简介 Ceph是一个PB,EB级别的分布式存储系统,可以提供文件存储,对象存储.和块存储,它可靠性高,易扩展,管理简便,其中对象存储和块存储可以和其他云平台集 ...

  7. pandas之sql操作

    我们知道,使用 SQL 语句能够完成对 table 的增删改查操作,Pandas 同样也可以实现 SQL 语句的基本功能.本节主要讲解 Pandas 如何执行 SQL 操作.首先加载一个某连锁咖啡厅地 ...

  8. [云计算]杂谈:SaaS与PaaS的产品经理,做产品设计时有什么区别?[摘]

    本文摘自: 郝雨彤@碧岸久 于 2022-09-20在社交平台中所表达的观点. 产品性质/类型 服务领域 服务对象(受众) 核心能力 SaaS 面向具体业务 (所属行业的)业务用户 很看重对业务的理解 ...

  9. 【LeetCode动态规划#06】分割等和子集(01背包问题一维写法实战)

    分割等和子集 分割等和子集 给你一个 只包含正整数 的 非空 数组 nums .请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 示例 1: 输入:nums = [1,5,11,5 ...

  10. Mybatis 框架下 SQL 注入攻击的方式

    前言 SQL注入漏洞作为WEB安全的最常见的漏洞之一,在java中随着预编译与各种ORM框架的使用,注入问题也越来越少. 新手代码审计者往往对Java Web应用的多个框架组合而心生畏惧,不知如何下手 ...