c语言 - 缺少 fseek 和 Microsoft 的 CRT UNICODE 支持的问题



我正在尝试使用unicode流读取一个UTF8编码的文本文件。这很好,但fseek似乎有一个错误,用以下简单的文件和程序演示:

我正在读取的文本文件:

ABC

文件的原始内容

EF BB BF 41 42 43 0D 0A 

正如您所看到的,该文件包含UTF-8 BOM和字符ABC,后面跟一行的末尾。

该程序使用UNICODE支持打开文件,然后读取一行并显示缓冲区的原始内容,这是预期的。然后它搜索到开头并再次读取该行,但这次缓冲区的内容不同;在缓冲区的开头有两个字节,它们实际上是UTF-16小端编码文件的BOM。

程序

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *input = _wfopen(L"utf8filewithbom.txt", L"r, ccs=UTF-8");
if (input == NULL)
{
printf("Can't open filen");
return 1;
}
unsigned char buffer[100];
fgetws((wchar_t*)buffer, _countof(buffer) / 2, input);
printf("First 4 bytes of buffer: %02x %02x %02x %02xn", buffer[0], buffer[1], buffer[2], buffer[3]);
fseek(input, 0, SEEK_SET);
fgetws((wchar_t*)buffer, _countof(buffer) / 2, input);
printf("First 4 bytes of buffer: %02x %02x %02x %02xn", buffer[0], buffer[1], buffer[2], buffer[3]);
fclose(input);
}

预期输出:

First 4 bytes of buffer: 41 00 42 00
First 4 bytes of buffer: 41 00 42 00

实际输出:

First 4 bytes of buffer: 41 00 42 00
First 4 bytes of buffer: ff fe 41 00

这是Microsoft CRT中的错误还是我做错了什么?

我正在使用Visual Studio 2019 16.4.3。

我尝试过但没有改变的事情:

  • 使用"rt, ccs=UTF-8"而不是"r, ccs=UTF-8"
  • 读取UTF-16 little-endian编码的文件,而不是UTF-8编码的文件

根据fseek:上的Microsoft文档

CRT打开以字节顺序标记(BOM(开头的文件时,文件指针位于BOM之后(即文件实际内容的开头(。如果必须将fseek放在文件的开头,请使用ftell获取初始位置,并使用fseek获取初始位置而不是位置0。

基本上,只需将代码调整为(更改/添加行的注释(:

FILE *input = _wfopen(L"utf8filewithbom.txt", L"r, ccs=UTF-8");
if (input == NULL)
{
printf("Can't open filen");
return 1;
}
const long postbomoffset = ftell(input); // Store post-BOM offset
unsigned char buffer[100];
fgetws((wchar_t*)buffer, _countof(buffer) / 2, input);
printf("First 4 bytes of buffer: %02x %02x %02x %02xn", buffer[0], buffer[1], buffer[2], buffer[3]);
fseek(input, postbomoffset, SEEK_SET);  // Seek to post-BOM offset, not raw beginning
fgetws((wchar_t*)buffer, _countof(buffer) / 2, input);
printf("First 4 bytes of buffer: %02x %02x %02x %02xn", buffer[0], buffer[1], buffer[2], buffer[3]);
fclose(input);

最新更新