Unicode ICU compare与iconv编码的字符串不正确

Unicode ICU compare与iconv编码的字符串不正确,unicode,icu,iconv,Unicode,Icu,Iconv,我尝试使用ICU的compare 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

我尝试使用ICU的compare 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;
}
有趣的是,即使输入字符串相同,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
如果字符串不相等,则认为它们相等。我错过了什么


谢谢

us1
us2
的长度都是1,它们的第一个字符分别是
enc_str1
enc_str2
。这可能就是字符串被视为相等的原因。我正在研究如何正确分配UnicodeString对象。如果使用“转换”字符串
enc_str1
enc_str2
初始化
UnicodeString
,则UnicodeString的长度为1。如果使用
str1
str2
对其进行初始化,则
us1
us2
的长度为8。可能是
enc_str1
enc_str2
中第一个字符
t
的第二个字节中的0(NULL)导致UnicodeString将其视为字符串的结尾?我需要一种方法将
enc_str1
enc_str2
转换为UnicodeString对象,以便ICU将其视为UTF16字符串。再三考虑,在对象构造期间,
UnicodeString
不会将
str1
str2
转换为UTF16吗?很抱歉有这么多评论,但我会在这些想法出现时发布它们。
$ ./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