C 标准指定
ftell()
返回以二进制模式打开文件时从文件开头开始的字符位置。
...获取流的文件位置指示器的当前值 由流指向。对于二进制流,该值是来自的字符数 文件的开头。对于文本流,其文件位置指示符包含未指定的 信息,可由 fseek 函数用于返回文件位置指示符 流到 ftell 调用时的位置;两个这样的区别 返回值不一定是写入字符数的有意义的度量 或阅读。
如果文本文件具有宽字符,例如
ñ
,则ñ
之后的任何字符的位置将大于文本文件中相应的列。具体来说,我在这里所说的位置是指,如果将文本文件读取为符号的线性序列,则对应的列。
例如,字符串
" ñ ñññ a ñ a"
有 12 个字符,但在此循环内打印 ftell()
:
void printPosition(FILE *file){
int c;
long i;
while((c=fgetc(file)) != EOF){
i = ftell(file);
printf("%c %i\n", c, i);
}
}
给出输出:
1
├ 2
▒ 3
4
├ 5
▒ 6
├ 7
▒ 8
├ 9
▒ 10
11
a 12
13
├ 14
▒ 15
16
a 17
我尝试以文本/二进制读取模式打开,并得到相同的结果。
如果您的平台支持
UTF-8
兼容的语言环境,您可以使用宽字符逐字符读取文件。
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
int main() {
{
char *r = setlocale(LC_ALL, "C.UTF-8");
if (!r) {
perror("Could not setlocale to UTF-8");
return EXIT_FAILURE;
}
}
// Create a temporary file with the content.
{
const char str[] = " ñ ñññ a ñ a";
FILE *f = fopen("/tmp/temp", "w");
assert(f);
int r = fwrite(str, 1, strlen(str), f);
assert(r == strlen(str));
r = fclose(f);
assert(r == 0);
}
// Read the file
{
FILE *f = fopen("/tmp/temp", "r");
assert(f);
unsigned counter = 0;
wint_t c;
while ((c = fgetwc(f)) != WEOF) {
printf("Character %lc at position %u\n", c, counter);
counter++;
}
int r = fclose(f);
assert(r == 0);
}
}
执行程序会在 godbolt 上给出输出 https://godbolt.org/z/ojbK8MeEd :
Character at position 0
Character ñ at position 1
Character at position 2
Character ñ at position 3
Character ñ at position 4
Character ñ at position 5
Character at position 6
Character a at position 7
Character at position 8
Character ñ at position 9
Character at position 10
Character a at position 11