C ftell问题和utf-8打印
我有两个问题: 1) 测试此代码时,buf前面会显示一些额外的字符。(当文件为空时,出于某种原因,fsize设置为3) 2) 该文件包含utf-8字符,在控制台中显示不正确,我尝试将locale设置为LC_ALL,但似乎没有任何效果C ftell问题和utf-8打印,c,utf-8,C,Utf 8,我有两个问题: 1) 测试此代码时,buf前面会显示一些额外的字符。(当文件为空时,出于某种原因,fsize设置为3) 2) 该文件包含utf-8字符,在控制台中显示不正确,我尝试将locale设置为LC_ALL,但似乎没有任何效果 void display_title(void) { FILE *fh; char *buf; long fsize; fh = fopen("title.txt", "r"); if (fh == NULL) {
void display_title(void)
{
FILE *fh;
char *buf;
long fsize;
fh = fopen("title.txt", "r");
if (fh == NULL)
{
fprintf(stderr, "Unable to open title.txt for read\n");
return;
}
fseek(fh, 0L, SEEK_END);
fsize = ftell(fh);
rewind(fh);
buf = malloc(sizeof(char)*fsize);
fread(buf, fsize, 1, fh);
fclose(fh);
fwrite(buf, fsize, 1, stdout);
free(buf);
}
编辑:所以我写了一个函数来检查文件的编码,但有些东西仍然关闭。我已经检查了文件,我知道它是UTF_8,但它没有在我的函数中注册。我觉得某处有一只虫子,但我没有看到
// Check for BOM in file
// ERROR : file too small
// NONE : does not exist
// UTF_8_ENCODING : for utf_8 enoding found
// UTF_16_ENCODING : for utf_16 encoding found
// UTF_32_ENCODING : for utf_32 encoding found
int check_encoding(int fd)
{
char *buf;
off_t fsize;
fsize = lseek(fd, 0L, SEEK_END);
if (fsize < 2)
return ERROR;
buf = (char*)malloc(2 * sizeof(char));
lseek(fd, 0L, SEEK_SET);
read(fd, buf, 2);
if (!strncmp(buf, UTF_16_BE, 2) ||
!strncmp(buf, UTF_16_LE, 2))
{
free(buf);
return UTF_16_ENCODING;
}
if (fsize >= 3)
{
realloc(buf, 3);
if (!strncmp(buf, UTF_8, 3))
{
free(buf);
return UTF_8_ENCODING;
}
}
if (fsize >= 4)
{
realloc(buf, 4);
if (!strncmp(buf, UTF_32_BE, 4) ||
!strncmp(buf, UTF_32_LE, 4))
{
free(buf);
return UTF_32_ENCODING;
}
}
free(buf);
return FALSE;
}
//检查文件中的BOM表
//错误:文件太小
//无:不存在
//UTF_8_编码:找到UTF_8编码
//UTF_16_编码:找到UTF_16编码的
//UTF_32_编码:找到UTF_32编码的
整数校验编码(int fd)
{
char*buf;
关闭fsize;
fsize=lseek(fd,0L,寻道结束);
如果(fsize<2)
返回误差;
buf=(char*)malloc(2*sizeof(char));
lseek(fd,0L,寻道集);
读取(fd,buf,2);
如果(!strncmp(buf,UTF_16_BE,2)||
!strncmp(buf,UTF_16_LE,2))
{
免费(buf);
返回UTF_16_编码;
}
如果(fsize>=3)
{
realloc(buf,3);
如果(!strncmp(buf,UTF_8,3))
{
免费(buf);
返回UTF_8_编码;
}
}
如果(fsize>=4)
{
realloc(buf,4);
如果(!strncmp(buf,UTF_32_BE,4)||
!strncmp(buf,UTF,4))
{
免费(buf);
返回UTF_32_编码;
}
}
免费(buf);
返回FALSE;
}
很难说为什么UTF-8没有正确地显示在您的控制台上,但我认为一个简单的原因是在开始时增加了三个字节:很可能您的文件以
编辑:
对于UTF-8编码文件,BOM(如果存在)将始终为字节序列0xEF、0xBB、0xBF
。因此,如果要处理可能包含或不包含BOM表的文件,可以只读取前三个字节,检查它们的值,如果它们是BOM表,则忽略它们
如果您不知道文件的编码(UTF-8、UTF-16等),可以使用BOM表来确定它。我链接到的维基百科文章展示了它是如何以不同的编码表示的 很难说为什么UTF-8没有正确地显示在控制台上,但我认为在开始时增加三个字节的原因很简单:文件很可能以 编辑: 对于UTF-8编码文件,BOM(如果存在)将始终为字节序列
0xEF、0xBB、0xBF
。因此,如果要处理可能包含或不包含BOM表的文件,可以只读取前三个字节,检查它们的值,如果它们是BOM表,则忽略它们
如果您不知道文件的编码(UTF-8、UTF-16等),可以使用BOM表来确定它。我链接到的维基百科文章展示了它是如何以不同的编码表示的 是否有跨平台的方式来处理BOM?谢谢!这很有道理。我现在就试试。有没有跨平台处理BOM的方法?谢谢!这很有道理。我现在就试试。当然,前面的3个
char
是BOM。OP以文本模式读取文件,但使用的是fread()
,这对二进制文件最有用ftell()
“对于文本流……两个这样的返回值之间的差异不一定是写入或读取字符数的有意义的度量”。C11dr 7.21.9.4 2建议以二进制模式“rb”打开文件。忽略我在其他函数中使用文件ptr,在检查函数中使用描述符的事实。我将其全部更改为描述符。我现在也使用fsize=lseek(fd,0L,SEEK_END)而不是ftell。您需要使用memcmp()
,而不是strncmp()
。替换realloc(buf,3)代码>与lseek(fd,0L,寻道集);realloc(buf,3);读取(fd,buf,3)代码>。与类似,如果(fsize>=4)
。此外,建议不要使用malloc、realloc,只使用char buf[4]
当然,前面的3个char
是BOM。OP以文本模式读取文件,但使用的是fread()
,这对二进制文件最有用ftell()
“对于文本流……两个这样的返回值之间的差异不一定是写入或读取字符数的有意义的度量”。C11dr 7.21.9.4 2建议以二进制模式“rb”打开文件。忽略我在其他函数中使用文件ptr,在检查函数中使用描述符的事实。我将其全部更改为描述符。我现在也使用fsize=lseek(fd,0L,SEEK_END)而不是ftell。您需要使用memcmp()
,而不是strncmp()
。替换realloc(buf,3)代码>与lseek(fd,0L,寻道集);realloc(buf,3);读取(fd,buf,3)代码>。与类似,如果(fsize>=4)
。此外,建议不要使用malloc、realloc,只使用char buf[4]