2009-09-03 66 views
18

我正在用C語言編寫一個小應用程序,它讀取一個簡單的文本文件,然後逐個輸出這些行。問題在於文本文件包含特殊字符,如Æ,Ø和Å等。當我在終端運行程序時,這些字符的輸出用「?」表示。處理C中的特殊字符(UTF-8編碼)

有沒有簡單的解決方法?

回答

28

首先:

  1. 讀入緩衝
  2. 使用libiconv的或類似於來自UTF-8獲得wchar_t的類型,並使用寬字符處理功能,諸如wprintf()
  3. 使用C中的寬字符函數!大多數文件/輸出處理函數具有寬字符變體

確保您的終端可以處理UTF-8輸出。通過正確的語言環境設置和操作語言環境數據,可以爲您自動完成文件打開和轉換......取決於您在做什麼。

還記得 UTF-8中的代碼點或字符的寬度是可變的。這意味着你不能只尋求一個字節,並像ASCII一樣開始閱讀......因爲你可能會落在代碼點的中間。好的庫可以在某些情況下做到這一點。

下面是一些代碼(未礦),演示的UTF-8文件讀出和寬字符一些使用中C.處理

#include <stdio.h> 
#include <wchar.h> 
int main() 
{ 
    FILE *f = fopen("data.txt", "r, ccs=UTF-8"); 
    if (!f) 
     return 1; 

    for (wint_t c; (c = fgetwc(f)) != WEOF;) 
     printf("%04X\n", c); 

    fclose(f); 
    return 0; 
} 

鏈接

  1. libiconv
  2. Locale data in C/GNU libc
  3. Some handy info
  4. Another good Unicode/UTF-8 in C resource
+0

謝謝兄弟!我會試試這個... – o01

+0

沒問題。堅持下去,C語言中的Unicode並不是世界上最簡單的東西......熟悉這些標準吧:) –

3

請確保您不會意外刪除任何字節;一些UTF-8字符的長度不止一個字節(這就是要點),你需要保留所有的字符。

它可以打印緩衝區爲十六進制的內容有用,這樣你就可以檢查哪些字節實際讀取:

static void print_buffer(const char *buffer, size_t length) 
{ 
    size_t i; 

    for(i = 0; i < length; i++) 
    printf("%02x ", (unsigned int) buffer[i]); 
    putchar('\n'); 
} 

您可以加載一個很短的文件之後做到這一點,僅包含幾個字符。

此外請確保終端設置爲正確的編碼,因此它將您的字符解釋爲UTF-8。

+0

我的終端設置爲UTF-8編碼。該程序通過fgets()將文本文件中每行的所有字符存儲到char數組中。如果我失去字節,我不知道爲什麼或如何修復它......(剛開始學習C btw) – o01

+0

@Eirik,不要使用面向ASCII的fgets()。使用我的文章中的fgetwc()。 –

2

可能您的文本文件是ISO-8559-1編碼,但您的終端是UTF-8。在處理面向字節的文本處理時,這種不匹配是一個標準問題;其他C程序(例如標準的'cat'和'more'命令)會做同樣的事情,它通常不被認爲是錯誤或需要修復的東西。

如果您想要在Unicode字符級別而不是字節上運行,但您需要在整個程序中使用wchar作爲字符類型而不是字符,併爲用戶提供開關以指定傳入的內容文件編碼實際上是。 (雖然有時候可以猜到,但它不是很可靠。)

2

我不知道它是否可以幫助,但如果你確定終端和輸入文件的編碼是相同的,你可以嘗試setlocale()

#include <locale.h> 
… 
setlocale(LC_CTYPE, ""); 
+0

我使用了'setlocale(LC_CTYPE,「UTF-8」);'。儘管shell環境配置正確,但仍需要成功讀取文件。 – lkuty

+0

使用'setlocale(LC_CTYPE,「」)',應根據環境變量設置應修改的語言環境的每個部分。 – jgrocha

+0

噢,是的,對不起,應該是''''而不是'NULL'。 –