交替读取为 char* 和 wchar_t*
Posted
技术标签:
【中文标题】交替读取为 char* 和 wchar_t*【英文标题】:Alternate reading as char* and wchar_t* 【发布时间】:2017-10-18 23:22:49 【问题描述】:我正在尝试编写一个解析 ID3 标签的程序,用于教育目的(所以请深入解释,因为我正在努力学习)。到目前为止,我取得了巨大的成功,但遇到了编码问题。
读取 mp3 文件时,所有文本的默认编码为 ISO-8859-1。所有标头信息(帧 ID 等)都可以在该编码中读取。
这就是我的做法:
ifstream mp3File("../myfile.mp3");
mp3File.read(mp3Header, 10); // char mp3Header[10];
// .... Parsing the header
// After reading the main header, we get into the individual frames.
// Read the first 10 bytes from buffer, get size and then read data
char encoding[1];
while(1)
char frameHeader[10] = 0;
mp3File.read(frameHeader, 10);
ID3Frame frame(frameHeader); // Parses frameHeader
if (frame.frameId[0] == 'T') // Text Information Frame
mp3File.read(encoding, 1); // Get encoding
if (encoding[0] == 1)
// We're dealing with UCS-2 encoded Unicode with BOM
char data[frame.size];
mp3File.read(data, frame.size);
这是一个糟糕的代码,因为data
是一个char*
,它的内部应该是这样的(将不可显示的字符转换为 int):
char = [0xFF, 0xFE, C, 0, r, 0, a, 0, z, 0, y, 0]
两个问题:
-
前两个字节是什么? - 已回答。
如何从我已经打开的文件中读取 wchar_t?然后继续阅读其余部分?
编辑澄清:我不确定这是否是正确的方法,但基本上我想做的是.. 将前 11 个字节读取到 char 数组(标题+编码),然后读取接下来的 12字节到 wchar_t 数组(歌曲的名称),然后接下来的 10 个字节到 char 数组(下一个标题)。这可能吗?
【问题讨论】:
前两个字节看起来像一个 UTF-16 字节顺序标记,BOM。其余与 UTF-16 编码一致。 UCS2 是 UTF-16 的子集,代码中的注释确实说“UCS-2 编码的 Unicode with BOM”;您是如何在不知道其含义的情况下生成该代码的? 在您以任何人都能识别的格式编写该代码后,我会看看这个。只是为什么。 您是否错过了该代码中间带有
的行?
是的,肯定缺少
现在更正了,我的错!
【参考方案1】:
我想出了一个不错的解决方案:创建一个新的 wchar_t 缓冲区并成对添加 char 数组中的字符。
wchar_t* charToWChar(char* cArray, int len)
char wideChar[2];
wchar_t wideCharW;
wchar_t *wArray = (wchar_t *) malloc(sizeof(wchar_t) * len / 2);
int counter = 0;
int endian = BIGENDIAN;
// Check endianness
if ((uint8_t) cArray[0] == 255 && (uint8_t) cArray[1] == 254)
endian = LITTLEENDIAN;
else if ((uint8_t) cArray[1] == 255 && (uint8_t) cArray[0] == 254)
endian = BIGENDIAN;
for (int j = 2; j < len; j+=2)
switch (endian)
case LITTLEENDIAN: wideChar[0] = cArray[j]; wideChar[1] = cArray[j + 1]; break;
default:
case BIGENDIAN: wideChar[1] = cArray[j]; wideChar[0] = cArray[j + 1]; break;
wideCharW = (uint16_t)((uint8_t)wideChar[1] << 8 | (uint8_t)wideChar[0]);
wArray[counter] = wideCharW;
counter++;
wArray[counter] = '\0';
return wArray;
用法:
if (encoding[0] == 1)
// We're dealing with UCS-2 encoded Unicode with BOM
char data[frame.size];
mp3File.read(data, frame.size);
wcout << charToWChar(data, frame.size) << endl;
【讨论】:
您的解决方案可能仅适用于英语和其他拉丁语。 UCS-2 和 UTF-16 是不同的。 UCS-2 已过时。 UTF-8 和 UTF-16 应该可以处理所有语言。 我已经用英语、希伯来语、俄语和简体中文对其进行了测试。效果很好。另外,我也无能为力,因为有些 ID3v2 标签是这样编码的。 这很奇怪!那么它必须是UCS-2。 我认为您的代码适用于 UCS-2 或 UTF-16(在此特定用途中),但您可以缩短它。以上是关于交替读取为 char* 和 wchar_t*的主要内容,如果未能解决你的问题,请参考以下文章