C++ -讀取 txt 文字檔 區分 big5 和 utf8 檔案

環境
windows 11 64 bits
Visual Studio 2022

ansi 檔和 utf8 檔是完全分不出來的,因為它們沒有檔頭。嚴格來說,ansi 字串和 utf8 字串也是分不出來的。

用 ansi 編碼方式儲存的字串,英文使用 ascii code 編碼佔 1 個 byte,中文字使用 big5 編碼,佔 2 個 byte。

用 utf8 編碼方式儲存的字串,英文還是使用 ascii code 編碼,但是其他非英文字,包括中文、日文、韓文,則佔1~3 byte 不等。

參考 chatgpt 提供的方法,逐行讀取文件,將每一行轉換為 wchar_t,如果轉換過程中出現錯誤,比方說不是有效的 utf8 字符,則假設這是 big5 編碼的文件。

檢查是否是 utf8 文字檔的程式碼

#include <iostream>
#include <fstream>
#include <codecvt>
#include <string>

bool IsUtf8(const char *szFile) 
{
    std::ifstream file(szFile);
    std::string line;
    bool bIsUTF8 = true;

    while (std::getline(file, line)) 
    {
        try 
        {
            std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
            std::wstring wide_line = converter.from_bytes(line);
        }
        catch (const std::range_error&) 
        {
            bIsUTF8 = false;
            break;
        }
    }

    return bIsUTF8;
}

完整程式碼

#include <iostream>
#include <fstream>
#include <codecvt>
#include <string>

bool IsUtf8(const char* szFile);
void CheckFile(const char* szFile);

int main()
{
    CheckFile("ansi_test01.txt");
    CheckFile("ansi_test02.txt");
    CheckFile("ansi_test03.txt");
    CheckFile("ansi_test04.txt");
    CheckFile("ansi_test05.txt");
    CheckFile("ansi_test06.txt");

    CheckFile("utf8_test01.txt");
    CheckFile("utf8_test02.txt");
    CheckFile("utf8_test03.txt");
    CheckFile("utf8_test04.txt");
    CheckFile("utf8_test05.txt");
    CheckFile("utf8_test06.txt");

	system("pause");
	return 0;
}

bool IsUtf8(const char *szFile) 
{
    std::ifstream file(szFile);
    std::string line;
    bool bIsUTF8 = true;

    while (std::getline(file, line)) 
    {
        try 
        {
            std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
            std::wstring wide_line = converter.from_bytes(line);
        }
        catch (const std::range_error&) 
        {
            bIsUTF8 = false;
            break;
        }
    }

    return bIsUTF8;
}
void CheckFile(const char* szFile)
{
    std::cout << szFile;
    bool bIsUTF8 = IsUtf8(szFile);
    if (bIsUTF8)
        std::cout << " - utf8" << std::endl;
    else
        std::cout << " - big5" << std::endl;

    std::cout << std::endl;
}

執行結果

測試檔下載
https://www.dropbox.com/scl/fi/o3m5lzhu5prc3str7c9sl/testfile03.zip?rlkey=ru0w3iyn65ljelkai5kmo00qz&dl=0

參考資料
https://www.cns11643.gov.tw/pageView.jsp?ID=9
https://eric0806.blogspot.com/2014/07/detect-big5-or-utf8-encoding.html
https://blog.darkthread.net/blog/detect-big5-encoding
https://openhome.cc/Gossip/Encoding/TextFile.html

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *