ICU比较与iconv编码的字符串不正确

时间:2016-04-14 05:21:34

标签: unicode icu iconv

我正在尝试使用ICU的比较API比较两个Unicode字符串,其中字符串已通过iconv实用程序转换为UTF16LE。

以下是代码:

#include <iconv.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include "unicode/coll.h"
#include "unicode/utypes.h"
#include "unicode/ucnv.h"     /* C   Converter API    */
#include "unicode/ustring.h"  /* some more string fcns*/
#include "unicode/uchar.h"    /* char names           */
#include "unicode/uloc.h"
#include "unicode/unistr.h"

using namespace std;
using namespace icu;

const size_t BUF_SIZE=1024;

class IConv {

    iconv_t ic_;

    public:
        IConv (const char* to, const char* from)
           : ic_(iconv_open(to,from)) {
              if ( iconv_t(-1) == ic_ )
                 cout << "iconv_open failed: " << errno << endl;
              }

        ~IConv ()
        { if ( iconv_t(-1) != ic_) iconv_close(ic_); }
        bool convert (char* input, char* output, size_t& out_size) {
            size_t inbufsize = strlen(input)+1;
            return
                  (size_t(-1)
                    != iconv(ic_, &input, &inbufsize, &output, &out_size))
                && (0U == inbufsize);
        }
};

void
icu_compare(UnicodeString str1, UnicodeString str2)
{
    UErrorCode success = U_ZERO_ERROR;
    Collator *collator = Collator::createInstance("UTF16LE", success);
    collator->setStrength(Collator::SECONDARY);

    if (collator->compare(str1, str2) == 0) {
        cout << "Strings are equal" << endl;
    } else {
        cout << "Strings are unequal" << endl;
    }
}

int main(void)
{
    char local_encoding[BUF_SIZE];
    char str1[BUF_SIZE];
    char str2[BUF_SIZE];
    char enc_str1[BUF_SIZE];
    char enc_str2[BUF_SIZE];

    cout << "Local encoding: " << endl;
    cin >> local_encoding;
    cout << "String1: " << endl;
    cin >> str1;
    cout << "String2: " << endl;
    cin >> str2;

    IConv ic("UTF16LE", local_encoding);
    bool ret;
    size_t outsize = BUF_SIZE;

    ret = ic.convert(str1, enc_str1, outsize);
    if (ret == false) {
        cout << "iconv failed: " << errno << endl;
    }
    else {
        for ( int i = 0 ; i < (BUF_SIZE - outsize) ; ++i )
           if ( enc_str1[i] )
               cout << "enc_str1[" << i << "]=[" << int(enc_str1[i]) << "]("
                  << enc_str1[i] << ")\n";
    }

    ret = ic.convert(str2, enc_str2, outsize);
    if (ret == false) {
        cout << "iconv failed: " << errno << endl;
    }
    else {
        for ( int i = 0 ; i < (BUF_SIZE - outsize) ; ++i )
           if ( enc_str2[i] )
                cout << "enc_str2[" << i << "]=[" << int(enc_str2[i]) << "]("
                       << enc_str2[i] << ")\n";
    }

    UnicodeString us1 = UNICODE_STRING_SIMPLE(enc_str1);
    UnicodeString us2 = UNICODE_STRING_SIMPLE(enc_str2);

    cout << "Unicode 1: " << us1.getBuffer() << endl;
    cout << "Unicode 2: " << us2.getBuffer() << endl;

    icu_compare(us1, us2);

    return ret ? 1 : 0;
}

输出:

$ ./a.out
Local encoding:
ISO_8859-1
String1:
tägelîch
String2:
tägelîch
enc_str1[0]=[116](t)
enc_str1[2]=[-61](▒)
enc_str1[4]=[-92](▒)
enc_str1[6]=[103](g)
enc_str1[8]=[101](e)
enc_str1[10]=[108](l)
enc_str1[12]=[-61](▒)
enc_str1[14]=[-82](▒)
enc_str1[16]=[99](c)
enc_str1[18]=[104](h)
enc_str2[0]=[116](t)
enc_str2[2]=[-61](▒)
enc_str2[4]=[-92](▒)
enc_str2[6]=[103](g)
enc_str2[8]=[101](e)
enc_str2[10]=[108](l)
enc_str2[12]=[-61](▒)
enc_str2[14]=[-82](▒)
enc_str2[16]=[99](c)
enc_str2[18]=[104](h)
Unicode 1: 0x7ffffacd0e50
Unicode 2: 0x7ffffacd0e20
Strings are equal

有趣的是,即使输入字符串相同,unicode字符串似乎也不同。

但是,当输入字符串不同时,输出为:

$ ./a.out
Local encoding:
ISO_8859-1
String1:
tägelîch
String2:
tägelîck
enc_str1[0]=[116](t)
enc_str1[2]=[-61](▒)
enc_str1[4]=[-92](▒)
enc_str1[6]=[103](g)
enc_str1[8]=[101](e)
enc_str1[10]=[108](l)
enc_str1[12]=[-61](▒)
enc_str1[14]=[-82](▒)
enc_str1[16]=[99](c)
enc_str1[18]=[104](h)
enc_str2[0]=[116](t)
enc_str2[2]=[-61](▒)
enc_str2[4]=[-92](▒)
enc_str2[6]=[103](g)
enc_str2[8]=[101](e)
enc_str2[10]=[108](l)
enc_str2[12]=[-61](▒)
enc_str2[14]=[-82](▒)
enc_str2[16]=[99](c)
enc_str2[18]=[107](k)
Unicode 1: 0x7ffffeb27ff0
Unicode 2: 0x7ffffeb27fc0
Strings are equal

当它们不是时,它们被视为相等。我错过了什么?

谢谢!

0 个答案:

没有答案