【Unity拓展工具】批量更改脚本文件的编码格式 (unity中脚本文件的编码格式从ANSI转换到UTF8出现乱码)
提示:記錄點(diǎn)學(xué)習(xí)過程中的簡(jiǎn)單成果,方便日后回顧也希望對(duì)讀者有點(diǎn)小幫助
文章目錄
- 前言
- 一、實(shí)現(xiàn)思路
- 二、基礎(chǔ)知識(shí)
- 1.編碼格式
- 2.Unity腳本轉(zhuǎn)碼注意事項(xiàng)
- 三、具體代碼實(shí)現(xiàn)
- 參考鏈接
- 總結(jié)
前言
在一些游戲項(xiàng)目中,有的項(xiàng)目或許屬于前期的某種設(shè)計(jì)缺陷導(dǎo)致沒有string表,需要在腳本文件中寫漢字。這樣操作一般是不允許的,是因?yàn)樵诖a中寫漢字容易因?yàn)槲募幋a的問題導(dǎo)致在真機(jī)包出現(xiàn)錯(cuò)誤。由于文件的累積最后需要更改腳本文件的數(shù)量甚是龐大,需要消耗大量時(shí)間,于是自己第一次學(xué)習(xí)寫了這個(gè)拓展工具。
一、實(shí)現(xiàn)思路
主要是需要先找到我們想要的更改編碼的文件,判斷編碼當(dāng)前的編碼格式是否是我們目標(biāo)編碼格式,不一致就需要進(jìn)行更改。
二、基礎(chǔ)知識(shí)
1.編碼格式
| ASCII | ASCII全名是American Standard Code for Information Interchange, 叫做“美國(guó)信息交換標(biāo)準(zhǔn)碼”。ASCII碼中,一個(gè)英文字母(不分大小寫)占一個(gè)字節(jié)的空間,一個(gè)中文漢字占兩個(gè)字節(jié)的空間。ASCII碼是目前最普及的一種字符編碼。 |
| ANSI | ANSI編碼是一種對(duì)ASCII碼的拓展:ANSI編碼用0x00~0x7f (即十進(jìn)制下的0到127)范圍的1 個(gè)字節(jié)來表示 1 個(gè)英文字符,超出一個(gè)字節(jié)的 0x80~0xFFFF 范圍來表示其他語(yǔ)言的其他字符。也就是說,ANSI碼僅在前128(0-127)個(gè)與ASCII碼相同,之后的字符全是某個(gè)國(guó)家語(yǔ)言的所有字符。 |
| Unicode | ASCII碼叫做“美國(guó)信息交換標(biāo)準(zhǔn)碼”,一個(gè)英文字母(不分大小寫)占一個(gè)字節(jié)的空間,一個(gè)中文漢字占兩個(gè)字節(jié)的空間。ASCII碼是目前最普及的一種字符編碼,只適用于美帝,要是用在美帝之外的國(guó)家,就不能滿足需求了。還有ANSI編碼其實(shí)包括很多編碼:中國(guó)制定了GB2312編碼,用來把中文編進(jìn)去另外,日本把日文編到Shift_JIS里,韓國(guó)把韓文編到Euc-kr里,各國(guó)有各國(guó)的標(biāo)準(zhǔn)。受制于當(dāng)時(shí)的條件,不同語(yǔ)言之間的ANSI碼之間不能互相轉(zhuǎn)換,這就會(huì)導(dǎo)致在多語(yǔ)言混合的文本中會(huì)有亂碼。 |
| UTF8 | 為了解決不同國(guó)家ANSI編碼的沖突問題,Unicode應(yīng)運(yùn)而生:如果全世界每一個(gè)符號(hào)都給予一個(gè)獨(dú)一無二的編碼,那么亂碼問題就會(huì)消失。這就是Unicode,就像它的名字都表示的,這是一種所有符號(hào)的編碼。Unicode標(biāo)準(zhǔn)也在不斷發(fā)展,但最常用的是用兩個(gè)字節(jié)表示一個(gè)字符(如果要用到非常偏僻的字符,就需要4個(gè)字節(jié))。現(xiàn)代操作系統(tǒng)和大多數(shù)編程語(yǔ)言都直接支持Unicode。但是問題在于,原本可以用一個(gè)字節(jié)存儲(chǔ)的英文字母在Unicode里面必須存兩個(gè)字節(jié)(規(guī)則就是在原來英文字母對(duì)應(yīng)ASCII碼前面補(bǔ)0),這就產(chǎn)生了浪費(fèi)。那么有沒有一種既能消除亂碼,又能避免浪費(fèi)的編碼方式呢?答案就是UTF-8! |
2.Unity腳本轉(zhuǎn)碼注意事項(xiàng)
Unity腳本文件在轉(zhuǎn)碼的時(shí)候我們需要先去讀取文件的文本內(nèi)容,然后再去將讀到的內(nèi)容使用UTF8的編碼格式寫入文件。值得注意的是這里面如果是因?yàn)橹形膩y碼的話就可以使用Encoding.GetEncoding(“Gb3212”)的編碼格式去讀,否則你讀到的本身就是亂碼,那么重新寫入也只會(huì)是亂碼。
三、具體代碼實(shí)現(xiàn)
using Sirenix.OdinInspector.Editor; using UnityEngine; using System.IO; using UnityEditor; using System.Text; using System;namespace Game.Editor {public class UTF_8 : OdinEditorWindow{private string Path = "Assets/Code/Game@hotfix/Window";private string Result;private string Finish;private int FileCount;private int ChangeCount;private Vector2 scrollPos;[MenuItem("Tools/UTF-8編碼", false)]public static void Open(){var window = (UTF_8)EditorWindow.GetWindow(typeof(UTF_8), false, "UTF-8編碼");window.maxSize = window.minSize = new Vector2(400, 400);window.Show();}private void OnGUI(){scrollPos = GUILayout.BeginScrollView(scrollPos);{GUILayout.BeginVertical();{GUILayout.Space(20);GUILayout.BeginHorizontal();{GUILayout.Label("File_Path");GUILayout.FlexibleSpace();Path = GUILayout.TextField(Path, GUILayout.Width(300));}GUILayout.EndHorizontal();GUILayout.Space(10);GUILayout.Space(30);if (GUILayout.Button("生成")){FileCount = 0;ChangeCount = 0;GetAllFile();}if (GUILayout.Button("清空log")){Clear();}GUILayout.Space(30);GUILayout.Label(Finish);GUILayout.Space(10);GUILayout.Label(Result);}GUILayout.EndVertical();}GUILayout.EndScrollView();}private void GetAllFile(){if (Path == null || Path == ""){Result = "路徑不可以為null";}//獲取指定路徑下面的所有資源文件 if (Directory.Exists(Path)){DirectoryInfo direction = new DirectoryInfo(Path);FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);for (int i = 0; i < files.Length; i++){if (files[i].Name.EndsWith(".meta")){continue;}Encoding _encoding = GetType(files[i].OpenRead());if (_encoding != Encoding.UTF8){var s = File.ReadAllText(files[i].FullName, Encoding.GetEncoding("GB2312"));File.WriteAllText(files[i].FullName, s, new UTF8Encoding(false));ChangeCount++;}FileCount++;}Result = $"總共找到{FileCount}個(gè)cs文件 {ChangeCount}個(gè)cs文件的編碼格式被修改成了UTF-8";Finish = "完成";}else{Result = "未找到此路徑";}}private static System.Text.Encoding GetType(FileStream fs){byte[] Unicode = new byte[] { 0xFF, 0xFE, 0x41 };byte[] UnicodeBIG = new byte[] { 0xFE, 0xFF, 0x00 };byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF }; //帶BOMEncoding reVal = Encoding.Default;BinaryReader r = new BinaryReader(fs, System.Text.Encoding.Default);int i;int.TryParse(fs.Length.ToString(), out i);byte[] ss = r.ReadBytes(i);if (IsUTF8Bytes(ss) || (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF)){reVal = Encoding.UTF8;}else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00){reVal = Encoding.BigEndianUnicode;}else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41){reVal = Encoding.Unicode;}r.Close();return reVal;}/// <summary>/// 判斷是否是不帶 BOM 的 UTF8 格式/// </summary>/// <param name="data"></param>/// <returns></returns>private static bool IsUTF8Bytes(byte[] data){int charByteCounter = 1;//計(jì)算當(dāng)前正分析的字符應(yīng)還有的字節(jié)數(shù)byte curByte; //當(dāng)前分析的字節(jié).for (int i = 0; i < data.Length; i++){curByte = data[i];if (charByteCounter == 1){if (curByte >= 0x80){//判斷當(dāng)前while (((curByte <<= 1) & 0x80) != 0){charByteCounter++;}//標(biāo)記位首位若為非0 則至少以2個(gè)1開始 如:110XXXXX...........1111110Xif (charByteCounter == 1 || charByteCounter > 6){return false;}}}else{//若是UTF-8 此時(shí)第一位必須為1if ((curByte & 0xC0) != 0x80){return false;}charByteCounter--;}}if (charByteCounter > 1){throw new Exception("非預(yù)期的byte格式");}return true;}private void Clear(){Result = null;Finish = null;}} }參考鏈接
鏈接: 字符編碼ANSI和ASCII區(qū)別、Unicode和UTF-8區(qū)別
總結(jié)
如果有大佬看到還望指點(diǎn)一二!!!
總結(jié)
以上是生活随笔為你收集整理的【Unity拓展工具】批量更改脚本文件的编码格式 (unity中脚本文件的编码格式从ANSI转换到UTF8出现乱码)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 64位进程和32位进程通信问题,接收端收
- 下一篇: 初入职场的工作感悟