【发布时间】:2018-12-29 19:56:21
【问题描述】:
是否可以在转换时使用 ICU 检测编码错误,或者是否有必要在转换前或后检查转换?
鉴于设置了从 UTF8 到 UTF32 的转换的初始化:
#include <stdio.h>
#include "unicode/ucnv.h" /* C Converter API */
static void eval(UConverter* from, UConverter* to);
int main(int argc, char** argv)
{
UConverter* from;
UConverter* to;
UErrorCode status;
/* Initialize converter from UTF8 to Unicode ___________________________*/
status = U_ZERO_ERROR;
from = ucnv_open("UTF-8", &status);
if( ! from || ! U_SUCCESS(status) ) return 1;
status = U_ZERO_ERROR;
to = ucnv_open("UTF32", &status);
if( ! to || ! U_SUCCESS(status) ) return 1;
/*______________________________________________________________________*/
eval(from, to);
return 0;
}
然后,通过ucnv_convertEx 应用转换
static void eval(UConverter* from, UConverter* to)
{
UErrorCode status = U_ZERO_ERROR;
uint32_t drain[1024];
uint32_t* drain_p = &drain[0];
uint32_t* p = &drain[0];
/* UTF8 sequence with error in third byte ______________________________*/
const char source[] = { "\xED\x8A\x0A\x0A" };
const char* source_p = &source[0];
ucnv_convertEx(to, from, (char**)&drain_p, (char*)&drain[1024],
&source_p, &source[5],
NULL, NULL, NULL, NULL, /* reset = */TRUE, /* flush = */TRUE,
&status);
/* Print conversion result _____________________________________________*/
printf("source_p: source + %i;\n", (int)(source_p - &source[0]));
printf("status: %s;\n", u_errorName(status));
printf("drain: (n=%i)[", (int)(drain_p - &drain[0]));
for(p=&drain[0]; p != drain_p ; ++p) { printf("%06X ", (int)*p); }
printf("]\n");
}
如果source 包含不允许的 UTF8 代码单元序列,该函数应该以某种方式报告错误。将上述片段存储在“test.c”中并使用
$ gcc test.c $(icu-config --ldflags) -o test
./test 的输出是(令人惊讶的):
source_p: source + 5;
status: U_ZERO_ERROR;
drain: (n=5)[00FEFF 00FFFD 00000A 00000A 000000 ]
因此,没有检测到错误的明显迹象。错误检测能比手动检查内容更优雅吗?
【问题讨论】:
-
您可以设置错误回调。 q.v. userguide.icu-project.org/conversion/…
-
@Eljay,您介意修饰上面的代码片段以应用回调进行错误检测吗?在文档中,我不清楚“oldAction”是什么。
-
如果您有
C++11,您可以使用标准库进行此转换,这确实表示编码错误。 -
(平心而论,关于您的示例,可以轻松检查 UTF8 编码错误,并且它根本不需要外部库。但我想您正在寻找更通用的解决方案。)跨度>
-
文本元数据(字符编码)通信失败、存储或传输过程中的数据损坏以及之前的 mojibake 错误的可能性与您从一种编码转换为另一种编码的需要完全无关。
标签: c++ c unicode character-encoding icu