none
UTF8 簡中txt文件轉 ANSI 簡中txt文件 亂碼問題 RRS feed

  • 問題

  • 有一個txt文件,其編碼為UTF8,內容是英文和中文的混合字符以及簡體中文字符串,我想將編碼轉換為ANSI格式,以供其他程序使用。 但是我使用StreamReader和StreamWriter進行編碼轉換新txt文件的簡體中文部分原來是亂碼

    奇怪的是,當我使用Windows的內置記事本保存新文件並將UTF8編碼更改為ANSI編碼時,文件內容顯示為簡體中文和英文的混合物。

    我該如何修改程式?
    或是有人知道windows 的記事本另存的編碼轉換是如何運作的嗎?

    先在這邊謝謝大家了

    我使用的代碼如下:

    try
    {
    
        System.IO.StreamReader streamReader = new StreamReader(tPath, Encoding.GetEncoding("utf-8"));
    
        string str = "";
        str = streamReader.ReadToEnd();
        FileStream fs = new FileStream(tPath2, FileMode.Create);
        using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
        {
            sw.Write(str);
            sw.Flush();
            sw.Close();
            sw.Dispose();
        }
    }
    catch (IOException ex)
    {
        string msg = ex.Message.ToString();
        MessageBox.Show(msg);
    }

    2019年12月17日 上午 03:40

解答

  • 前面說過:

    我個人偏好轉任何編碼輸出,都用 Encoding.GetBytes 轉換為 byte()

    這樣寫入之前就可以用中斷點檢查,而且寫入直接用位元組寫入也比較快。

    我個人不愛用 StreamReader ,因為我沒辦法檢核確認轉碼過程。

    .Net 字串跟傳統 VB/VC 字串不同。

    .Net 字串僅允許 Unicode 字串,不允許任何編碼字串,任何編碼字串只允許在 byte() 下存在。

    而傳統 VB/VC 字串是允許字串存入編碼字串,最多不能正常顯示。

    這表示只要不是 Unicode 字串,在 .Net 字串下無法被正確暫存,只要在 .Net 字串下存在任何非 Unicode 內容,都會被自動轉碼,轉碼失敗就是 ? 。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 J.Fengyi 2019年12月26日 上午 06:31
    2019年12月24日 下午 03:23

所有回覆

  • 中文編碼唯一推黑大的工具:https://blog.darkthread.net/blog/cea-release/

    裡面也有 Source Code 可以研究。


    理直氣和,切記。

    個人

    2019年12月17日 上午 06:20

  • .Net 的 Encoding 有做防呆,不在系統對照表上的,都不能轉換。

    請改用 API WideCharToMultiByte來轉換。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年12月17日 下午 02:45
  • 十分感謝~~
    我來研究看看
    2019年12月18日 上午 12:48
  • 好的瞭解了
    我來研究看看~~

    2019年12月18日 上午 12:49
  • 我個人偏好轉任何編碼輸出,都用 Encoding.GetBytes 轉換為 byte()

    這樣寫入之前就可以用中斷點檢查,而且寫入直接用位元組寫入也比較快。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年12月18日 下午 02:52
  • 據我所知
    文件開啟時還是會依照文件的編碼進行顯示
    那想請問
    心冷大大您說的用位元組寫入有沒有可能讓兩種編碼同時存在於一份文件中呢?
    例如說:
    簡體中文就使用GB2312的編碼
    繁體中文就使用big5的編碼
    然後文件的編碼為ANSI


    因為當我使用記事本進行轉存後,使用notepad++ 開啟 或是記事本開啟
    文件的編碼都僅顯示為ANSI...
    這就讓我疑惑了,windows 的記事本是如何讓兩種編碼的文字同時存在於一份文件檔案中的?@@

    2019年12月19日 上午 03:43
  • 首先检查一下Encoding.Default.EncodingName是什么,这个Default在不同机器上是不一样的,所以你先看看你到底是用什么编码来读取和写入的。另外你的操作系统是什么语言的?
    2019年12月19日 上午 07:54
  • 作業系統是繁體中文
    預設編碼是big5
    檔案的讀取因為原檔是utf-8的編碼
    因此用UTF8讀取

    2019年12月19日 上午 09:10
  • 你如果透過 byte() 來操作,在 byte() 下啥編碼都可以,你再多幾倍的編碼,加密、壓縮都能一起塞,但一般軟體不能獨。

    記事本並沒有一份文件多個編碼。

    記事本是透過 BOM 確認這個文件是 Unicode / UTF8 的哪種編碼,無 BOM 預設為系統編碼。

    當無 BOM 時,企圖轉換為系統編碼 (繁中為 Big5) ,再由 big5 轉換為 Unicode 顯示,在 WinNT 下,記事本為 Unicode Window ,所以當原始編碼未正確轉換為 big5 時,再轉換成 Unicode 就是一團亂,不是多個編碼存在於同一個檔案內。

    多個編碼存在於同一個檔案內,通常用於軟體介面的語言檔或是多語系的參數檔。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年12月19日 下午 02:47
  • 首先我把操作系统的区域设置设定为“台湾”,然后我用记事本保存一段混编文字,这时我得到以下提示。

    我选择确定后,记事本保存的文件内容如下。

    简体中文中的部分字符被替换成了?。

    接下来我创建一个c#(WPF)程序,使用如下代码。

    var path = @"d:\temp.txt";
    var coding = Encoding.Default;
    using (var sw = new StreamWriter(new FileStream(path, FileMode.OpenOrCreate), coding))
    {
        sw.Write(Txt.Text);
        sw.Flush();
        sw.Close();
        sw.Dispose();
    }
    Txt.Text = "Encoding.Default: " + coding.EncodingName + "\r\n";
    using (var sr = new StreamReader(new FileStream(path, FileMode.OpenOrCreate), coding))
    {
        Txt.Text += sr.ReadToEnd();
        sr.Close();
        sr.Dispose();
    }

    然后我得到的内容是这样的。

    这个和Windows10自带的记事本程序完全一致,没有任何不同之处,因此我不清楚你那里出了什么问题。如果方便的话,请提供示例文本,或者能呈现问题的截屏。

    另外这里还有一点需要说明一下。Win95之后的Windows中的gb2312并非真正的gb2312,实际上是gbk,尽管你看到的显示是gb2312或者指定为gb2312,但实际上都是gbk,gb2312和gbk的代码页都是CP936,因为尽管中国弄了这么一套简体中文字符,但传统的繁体中文仍然广泛使用,尤其是在古籍文献中,所以实际上在中国是简繁体同时使用,因此仅支持简体字的纯粹的gb2312没有任何使用价值。gbk本身就是微软搞出来的,被称为微软版的gb2312,从Win95开始的所有Windows中的gb2312全部都是gbk。换言之就是没有big5和gb2312混编这种东西,因为微软操作系统中的gb2312(即gbk)本身就包含了全部big5字符,是简体中文、big5和日韩汉字的总集。

    2019年12月19日 下午 04:40
  • 有點久了,不知道有沒有記錯,在 .Net 2.0 測過。

    big5e 受 API 支援,但不被 Encoding 類別支援。

    但在安裝過 Unicode 補完計畫的 WinXP/Vista/7 下,Encoding 就能支援 big5e 。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年12月19日 下午 05:14
  • 謝謝心冷大大跟[-]大大的解釋,昨天在試作的時候發現在提問時,忘記提一個重要的前提

    我所說的記事本轉存成ansi會正常顯示簡體中文的原因是

    我有安裝心冷大大所說的 Unicode 補完計畫

    因此在未安裝補完計畫前,只用記事本轉存會跳出跟 [-]大大 所截的那個訊息一樣,並且簡體中文會變成 ?

    那這個樣的話,我有另外一個問題想請教

    在安裝 Unicode 補完計畫時,他會產生一個 C_950.NLS 檔案

    然後將其覆蓋在System32 的目錄底下

    就能夠讓記事本另存的結果達到我想要的

    但為甚麼我直接用編碼寫入文件,他不會自動將 unicode 補完計畫中的參數帶入檔案

    以達到跟記事本一樣的效果?

    是需要做甚麼樣的設定或是程式得部分需要怎樣修改才能讓他去到unicode 補完計畫 安裝後的參數呢?


    • 已編輯 J.Fengyi 2019年12月20日 上午 01:27 論述缺少,將其補完整
    2019年12月20日 上午 01:26
  • 你的.net程序是用和操作系统一样的位元编译的吗?比如你操作系统是64位的,那你的.net程序也是64位的吗?system32是给64位程序用的,32位程序用的是syswow64,不知道是不是这个原因。我没有这个“补完计划”,所以无法测试,等其他朋友帮你解决吧。
    2019年12月20日 上午 04:22
  • UniCode 補完計畫是在 big5 對照表 (c_950.nls) 增加約八千餘字的對照,使其滿足日韓簡罕的基本對照,實際上仍遠低於目前 Unicode 的完整字集十萬餘字。

    Encoding 轉換要參照 big5 對照表,所以沒有 Unicode 補完計畫時,對照表上沒有的將轉換為 ? 。

    API 則沒有這問題,但是 API 能轉的也就那麼多,API 的範圍我沒特別測試過。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年12月20日 下午 03:22
  • 先回 [-]大大 您說的這個方法我有試過,但沒有用。還是十分感謝您的協助~

    心冷大大,那照您這樣說,在有安裝補完計畫的前提下,

    其實,我的程式在執行轉碼的時候

    他會自動抓對照表中的資料,然後去執行轉碼,而不需要特別透過呼叫的方式對嗎?

    那為甚麼會沒有用......ORZ(小崩潰..處理這個已經花了2個禮拜....

    API ? 請問是甚麼的API呢? Unicode 補完計畫的 API 嗎?還是有其他相似的東西?

    可以請您跟我說說嗎?感激不盡

    2019年12月23日 上午 12:51
  • c#的encoding内部是通过调用WideCharToMultiByte和MultiByteToWideChar来实现编解码的,按说和记事本是一样的。

    https://referencesource.microsoft.com/#mscorlib/system/text/encoding.cs,3b6090c501893c25

    补完计划的API我就不清楚了。除了记事本,其它程序行么?比如用vs,使用big5保存?

    2019年12月23日 上午 04:08
  • 再问一个问题,如果你用记事本保存一个txt文件,然后用“StreamReader(new FileStream(path, FileMode.OpenOrCreate), Encoding.Default)”读取是否正常呢(不要用自动判断,指定为Encoding.Default)?如果c#的写入有问题,那按说它读取出来的内容应该也不正确。
    2019年12月23日 上午 05:06

  • .Net 的 Encoding 有做防呆,不在系統對照表上的,都不能轉換。

    請改用 API WideCharToMultiByte來轉換。

    一開始我就有寫哪個 API 阿。

    我有一個介面語系編輯器輸出用加密的 txt 格式,就可以同時處理,是用 .Net framework 2.0 的 Encoding ,在 W7E 裝 Unicode 補完計畫。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年12月23日 下午 03:59
  • 回 [-] 大大 

    第一個問題:

    我有使用notepad++進行一樣的操作,但沒有效果orz

    第二個問題:

    若您是指用記事本的進行文件轉碼後,使用StreamReader讀取資料,

    在我前幾次的試驗中,讀進的資料在偵錯模式下的區域變數中是正常的,

    但有可能是我記錯了,我再來試試看,謝謝您的幫助~

    回 心冷大大
    我懂您的意思了,我再來試試看(回完才發現眼殘...)

    2019年12月23日 下午 04:05
  • 我有使用notepad++進行一樣的操作,但沒有效果orz

    你是说除了记事本以外其它程序全不行?用vs并指定代码页950也不行?但所有程序都能正常读取?
    2019年12月24日 上午 03:42
  • 前面說過:

    我個人偏好轉任何編碼輸出,都用 Encoding.GetBytes 轉換為 byte()

    這樣寫入之前就可以用中斷點檢查,而且寫入直接用位元組寫入也比較快。

    我個人不愛用 StreamReader ,因為我沒辦法檢核確認轉碼過程。

    .Net 字串跟傳統 VB/VC 字串不同。

    .Net 字串僅允許 Unicode 字串,不允許任何編碼字串,任何編碼字串只允許在 byte() 下存在。

    而傳統 VB/VC 字串是允許字串存入編碼字串,最多不能正常顯示。

    這表示只要不是 Unicode 字串,在 .Net 字串下無法被正確暫存,只要在 .Net 字串下存在任何非 Unicode 內容,都會被自動轉碼,轉碼失敗就是 ? 。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 J.Fengyi 2019年12月26日 上午 06:31
    2019年12月24日 下午 03:23