2011-12-30 56 views
0

我想實現codecvt方面使用ICU從任何字符編碼(ICU支持)轉換爲UTF-8內部。我知道codecvt_byname存在,它可以用來做我想要的一部分,如this example所示。這個例子的問題是它(1)使用寬字符流(我想使用「常規」,面向字節的流)和(2)需要2個流來執行轉換。相反,我要像一個單一的數據流:使用ICU實現我自己的編碼方面

locale loc(locale(), new icu_codecvt("ISO-8859-1")); 
ifstream ifs; 
ifs.imbue(loc); 
ifs.open("/path/to/some/file.txt"); 
// data read from ifs here will have been converted from ISO-8859-1 to UTF-8 

因此,我的魔杖做一個類似的實現,但this使用ICU而不是iconv。 鑑於此,我的實現的do_in()是:

icu_codecvt::result icu_codecvt::do_in(state_type &state, 
             extern_type const *from, extern_type const *from_end, 
             extern_type const *&from_next, intern_type *to, 
             intern_type *to_end, intern_type *&to_next) const { 
    from_next = from; 
    to_next = to; 
    if (always_noconv_) 
    return noconv; 

    our_state *const s = state_store_.get(state); 
    UErrorCode err = U_ZERO_ERROR; 
    ucnv_convertEx(
    s->utf8_conv_, s->extern_conv_, &to_next, to_end, &from_next, from_end, 
    nullptr, nullptr, nullptr, nullptr, false, false, &err 
); 
    if (err == U_TRUNCATED_CHAR_FOUND) 
    return partial; 
    return U_SUCCESS(err) ? ok : error; 
} 

our_state對象維護兩個UConverter*指針,一個用於「外部」編碼(在本例中,ISO-8859-1)和一個用於UTF-8編碼。

我的問題是:

  1. 我應該指定nullptr爲「支點」爲上述緩衝液,或提供自己的?
  2. 我不確定何時,如果有的話,我應該將reset參數(現在是第一個false以上)設置爲true
  3. 我不知道如何知道何時將flush參數(當前是第二個false)設置爲true,即我如何知道何時已達到輸入的結尾。

有一點幫助嗎?

+0

您應該在打開文件之前灌注()您的文件流。如果文件已經打開,很多系統會默默地忽略imbue()(這是因爲關於對話的狀態可能已經丟失)。 – 2011-12-30 15:54:15

+0

完成。其餘的答案? – 2011-12-30 16:01:59

回答

0

該codecvt方面是而不是打算在不同的編碼之間進行轉換。相反,它從外部編碼轉換而來,其中一個字符可能使用多個外部字(通常是字節)編碼爲內部表示,其中每個字符只由一個字表示(例如char,wchar_t,char16_t等)。

從這個角度來看,「結束」內部字符序列是沒有意義的。如果沒有可用的外部單詞,則轉換完成,如果最後一個字符保持不完整,則這是傳輸過程中的錯誤。因此,不需要指出轉換完成,並且相應地沒有接口。這應該澄清,「同花大順」的論點的確應該永遠是「虛假的」。

我意識到UTF-8不太適合用單詞表示一個字符的帳單。但是,這會困擾你使用標準類型處理字符串來處理UTF-8處理。但是,只要你保持清醒的修改,通常情況下工作就OK了。

「重置」參數可能旨在處理在流內搜索。我認爲filebuf應該在尋求時提供一個新的state_type對象。這可能意味着ICU內部機構想要重置。但是,我不知道ICU接口。因此,我也不知道你是否想提供一個數據透視緩衝區。

+0

我最初的想法是有一個轉碼流緩衝區,但這傢伙http://stackoverflow.com/a/8453807/99089說使用codecvt - 誰是對的?或者,如何以「優雅」的方式使用iostreams實現從任意編碼到UTF-8的自動轉換? – 2011-12-30 18:09:47

+0

'char16_t'和'wchar_t' *不*保證爲每個字符一個字。 'char16_t'專門用於具有代理對的UTF-16代碼單元。所以不,這不是每個「字符」的一個16位字。 – 2011-12-30 19:27:35

+0

@Nicol Bolas:實際上wchar_t的意圖是每個字符一個單詞(但Unicode委員會放棄了他們的既定目標,即在Java和Windows決定使用16位wchar_t後立即爲所有字符創建一個16位編碼)。你在概念上對char16_t是正確的,但是流和字符串類仍然假定一個字是一個字符。這是例如反映在codecvt界面中。 – 2011-12-30 19:51:47