热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

传入的时候是utf8的读出的时候报文中出现nul怎么解决_Unity中编码Encoding脱坑指南...

本文节选自洪流学堂公众号技术专栏《大话Unity2018》,未经允许不可转载。洪流学堂公众号回复专栏,查看更多专栏文章。《大话Unity2018》&#x

本文节选自洪流学堂公众号技术专栏《大话Unity2018》,未经允许不可转载。

洪流学堂公众号回复专栏,查看更多专栏文章。


《大话Unity2018》,大智带小新学Unity2018的有趣经历,让你学Unity更简单。所有订阅《大话Unity2018》的用户,可在《大话Unity2019》上线时获得1元换购资格。

0aca5acad2fa0b6b1d76e3cebf05f5bb.png

洪流学堂,让你快人几步。你好,我是郑洪智。

大智:“昨天我们了解了编码的基本知识,要佩服并感谢一下ISO和Unicode联盟,做了这么伟大的事情将全世界的语言文字统一收录和编码,而这当中包括了那么多我们根本没听说过的奇怪的语言文字。正是因为他们的努力奠定了互联网是一个无国界的世界,每天我们都能通过它获得来自任何地方任何语言的信息。”
小新:“不过这里面的编码的问题何解决呢?”
大智:“今天就给大家带来这个脱坑指南,说说编码方面常遇到的坑。”

乱码是如何出现的?

由于大多数(有些包含BOM)文本中并没有包含特定信息,指示文本使用了什么编码方式,当文本在文件或者网络中交换时,可能会导致保存文本的编码和打开文本的编码不一致。这时候文本解析出来的字符就可能不一致,甚至有些根本就没有对应的字符,就会显示为乱码。

BOM

前两天我们说到使用UTF8 without BOM的编码方式是最佳的选择。那这个BOM是个什么东西呢?

BOM(Byte-Order Mark,字节序标记)是Unicode码点U+FEFF。它被定义来放在一个UTF-16文件的开头,如果字节序列是FEFF那么这个文件就是大端序,如果字节序列是FFFE那么这个文件就是小端序。

UTF-8本身是没有字节序的问题的(因为它是以单个字节为最小单位),但是Windows里面很多编辑器(比如记事本)会多此一举的在UTF-8文件开头加入EF BB FF也就是U+FEFF的UTF-8编码。

如果你的文本文件里面有一个这东西你就倒了大霉了,可能会:

  • 文件用一些编辑器打开出现乱码。

  • 使用代码读取文件会出错。

建议在Windows上做开发的同学,如果遇到了编码问题,一定要选择“使用UTF-8无BOM格式”保存。

Unity中的代码目前使用的默认编码方式是UTF8。

C#中的编码处理

在开发中我们可以控制编码的格式,但是很多情况下我们还是要处理非UTF8编码的文本,这时候怎么做呢?下面我们学习一下在C#中如何和“编码”友好相处。

读文件

之前我们在读取文件时,都没有关注过编码这个问题,因为我们之前文件保存的编码方式是UTF8。

读文件的时候想把文件中的正确内容读取出来有两个关键的地方:

  • 文件的编码方式是什么

  • 读取的时候编码方式是什么

文件的编码方式

文件的编码方式是多种多样的,昨天我们提到的那些编码方式都可以作为文件的编码。文件的编码如何查看以及修改呢呢?

在这里推荐Visual Studio Code这个编辑器。在Visual Studio Code的右下角,可以看到当前文档打开时所用的编码方式。

1242c8e8b50f911cff37225109776aec.png
VS Code打开文档的界面

注意:这里显示的编码方式并不一定是文档真正的编码方式,因为文本文件的编码方式大部分情况是无法检测的。

你会看到上面的文本就出现了很多问号的乱码,这时候可以点击下面UTF-8的部分来用其他编码方式重新打开,如下图所示:

33b8176652fc652c5d1c8a8a21365dde.gif
用其他编码方式打开.gif

Visual Studio Code提供了内容猜测的方式来识别文本的编码方式,使用正确的编码方式打开后,你就会发现乱码变为正常的字符了。

那如何将文本转换成UTF8这个最佳的编码方式呢?

1、首先你要确定当前打开的文件中没有显示乱码,如果有乱码尝试用其他的编码方式重新打开
2、选择“通过编码保存”,选择UTF-8即可

8cb0ec54c5f5a8f6a645e075f7be3418.gif
用其他编码保存.gif

用代码读文件

之前我们使用了很多次File.ReadAllText,其实它还有第二个参数:

public static string ReadAllText(string path, Encoding encoding);

如果不传入这个参数,会使用默认的编码方式:

Debug.Log(System.Text.Encoding.Default); // 你会看到这个输出是UTF8

那如果我们的文本文件是GB2312的编码方式,读出来的文件会怎样呢?

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;

public class FileWithEncoding : MonoBehaviour
{
    void Start(){
        var path = Path.Combine(Application.streamingAssetsPath, "data.txt");
        Debug.Log(Encoding.Default);
        var text = File.ReadAllText(path, Encoding.Default);
        Debug.Log(text);
    }
}

通过上面的代码,你会看到输出是:

d99286883081cb1fb2f7a3683c1b0b09.png

改成下面这一行以后,你就能获取到正确的编码文本了!

var text = File.ReadAllText(path, Encoding.GetEncoding("GB2312"));

Unity发布后读取乱码

到这还没完,如果你将上面的简单的程序发布出来,你会发现又不行了!

这时候是咋回事呢?我将思路提供给你。

1、先想办法找到线索,那就是Log文件。发布出来的Exe的log文件的位置是:

macOS    ~/Library/Logs/Unity/Player.log
Windows    C:\Users\\AppData\LocalLow\CompanyName\ProductName\output_log.txt

对于我就是:

C:\Users\32954\AppData\LocalLow\DefaultCompany\198Encoding

2、找到log文件后打开,你会发现这么一句话

NotSupportedException: Encoding 936 data could not be found. Make sure you have correct international codeset assembly installed and enabled.

3、这时候你就可以拿这句话去google了,你肯定能找到答案

我也把答案附上吧:
原因是Unity在发布时并没有包含这些字符集,需要手动加进去,方法是:
1、找到Unity安装目录

2018.3.0f2\Editor\Data\Mono\lib\mono\2.0

将里面的I18N.dllI18N.CJK.dll复制到工程中

2、重新发布即可

BOM如何处理

其实使用C#的File类时,你不需要对BOM进行特殊处理,因为C#自动帮你处理了BOM,但是如果是通过网络传输或者其他情况,BOM可能会害的你很惨。这个我们后面学到使用WebRequest时再详说。

总结

大智:“说了这么多,相信你已经对编码有一定的了解了。那我们到底应该用什么编码呢?用UTF8 without BOM保准没错,下节课我们再来说说这是个什么东西。”

今日思考题

大智:“试着用C#读取不同编码的文本文件?”
小新:“好嘞!”
大智:“收获别忘了分享出来!也别忘了分享给你学Unity的朋友,也许能够帮到他。”


洪流学堂公众号回复专栏,查看更多专栏文章。

fd3eb7b487cb8fcbc793ed66d3bd569f.png



推荐阅读
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
author-avatar
手机用户2502905845
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有