user-0 提问: C语言用fgets读取utf-8编码文本文件出现问题

回复:
user: user-1
content: 引用 4 楼 qq423399099 的回复:windows下利用标准库fopen以UTF-8格式打开一个文件,要注意下面几个问题.  1.如果文件编码为UNICODE(UTF-8),有两种情况: 1)没有BOM头,调用fopen必须指定css=UTF-8. 2)有BOM头,调用fopen不要指定css=UTF-8. 2.文件编码为其它格式(如ANSI),调用fopen必须指定css=UTF-8.  fopen打开其它UNICODE(如UTF-16LE,UNICODE)等,与此类似,只是BOM头不相同. 例如 记事本中如果保存编码格式为Unicode big endian，则无法使用 ccs=UNICODE 这个功能 如果用了ccs=UNICODE，则必须使用宽字符格式的相应函数，即便文件本身编码是ANSI格式 虽然没遇到过，但是赞一个

user: user-2
content: 是不是   数组的最后一位不是0啊

user: user-3
content: fgets是读取文本文件的

user: user-4
content: 引用 10 楼 zcmerlin 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:]  Flag      No BOM (or new file)  BOM: UTF-8  BOM: UTF-16 UNICODE   ANSI                  UTF-8       UTF-16LE      UTF-8     UTF-8                 UTF-8       UTF-16LE      UTF-16LE  UTF-16LE              UTF-8       UTF-16LE         用的就是，fopen（FILE *p_file,  "r,  ccs = utf-8"）; 可是不行。。。编译就没通过，错误提示就是截图里那样[/quote]  #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <wchar.h>   #define MAX_SIZE    64 int main(void) {     FILE *p_source = NULL;     char *fname = "2.txt";     wchar_t buffer[MAX_SIZE] = { 0 };      if((p_source = fopen(fname, "r,ccs=utf-8")))     {         while(!feof(p_source))         {             wchar_t *src = fgetws(buffer, MAX_SIZE, p_source);             if (!src) {                 printf("return NULL\n");                 break;             } else                 printf("%s\n", src);         }         printf("\n");     }      fclose(p_source);      return 0 ; }  需要添加头文件<wchar.h> 如果使用fgets读取，会直接返回NULL，即出错。使用fgetws打开是可以的，同样缓存也要做调整。 对于wchar_t类型的数据如何输出到终端，还需要查一下，使用%s，编译器本身就会提警告。

user: user-0
content: 引用 9 楼 paschen 的回复:应该读取到wchar_t中试了下，貌似并不行，不知道是哪里的问题

user: user-0
content: 引用 6 楼 zhao4zhong1 的回复: Flag      No BOM (or new file)  BOM: UTF-8  BOM: UTF-16 UNICODE   ANSI                  UTF-8       UTF-16LE      UTF-8     UTF-8                 UTF-8       UTF-16LE      UTF-16LE  UTF-16LE              UTF-8       UTF-16LE         用的就是，fopen（FILE *p_file,  "r,  ccs = utf-8"）; 可是不行。。。编译就没通过，错误提示就是截图里那样

user: user-5
content: 应该读取到wchar_t中

user: user-0
content: 引用 7 楼 zcmerlin 的回复:[quote=引用 4 楼 qq423399099 的回复:] windows下利用标准库fopen以UTF-8格式打开一个文件,要注意下面几个问题.  1.如果文件编码为UNICODE(UTF-8),有两种情况: 1)没有BOM头,调用fopen必须指定css=UTF-8. 2)有BOM头,调用fopen不要指定css=UTF-8. 2.文件编码为其它格式(如ANSI),调用fopen必须指定css=UTF-8.  fopen打开其它UNICODE(如UTF-16LE,UNICODE)等,与此类似,只是BOM头不相同. 例如 记事本中如果保存编码格式为Unicode big endian，则无法使用 ccs=UNICODE 这个功能 如果用了ccs=UNICODE，则必须使用宽字符格式的相应函数，即便文件本身编码是ANSI格式  不是很明白，试了下，好像还是不行，代码如下： #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h>  int main(void) { 	FILE *p_source = NULL; 	char *fname = "e:\\source"; 	wchar_t buffer[10] = { 0 };  	if(p_source = fopen(fname, "r, ccs = utf - 8")) 	{ 		while(!feof(p_source)) 		{ 			printf("%s", fgetws(buffer, 10, p_source)); 		} 		printf("\n"); 	}  	fclose(p_source);  	system("pause"); 	return 0 ; }  已改为wchar_t，fgetws，但结果依然是失败，提示如下：    文件打开方式不可用  原问题是这样的：  文本文件为utf-8 无bom编码格式，文本内容包含英文字母和中文标点  C语言编写的程序想计算每行的字符个数，但是英文字母和中文标点在utf-8无bom的编码格式下的字节长度不同  造成的结果是含中文标点的行，计算的字符不准确  所以在想怎么样让程序准确判断每行的字符个数  另，把文本文件改为ansi后，输入了几个汉字，可以识别汉字，是不是说明fopen，fgets这些是以ansi编码格式读取文件的呢？[/quote]  对了，操作环境：windows7，vs2012

user: user-0
content: 引用 4 楼 qq423399099 的回复:windows下利用标准库fopen以UTF-8格式打开一个文件,要注意下面几个问题.  1.如果文件编码为UNICODE(UTF-8),有两种情况: 1)没有BOM头,调用fopen必须指定css=UTF-8. 2)有BOM头,调用fopen不要指定css=UTF-8. 2.文件编码为其它格式(如ANSI),调用fopen必须指定css=UTF-8.  fopen打开其它UNICODE(如UTF-16LE,UNICODE)等,与此类似,只是BOM头不相同. 例如 记事本中如果保存编码格式为Unicode big endian，则无法使用 ccs=UNICODE 这个功能 如果用了ccs=UNICODE，则必须使用宽字符格式的相应函数，即便文件本身编码是ANSI格式  不是很明白，试了下，好像还是不行，代码如下： #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h>  int main(void) { 	FILE *p_source = NULL; 	char *fname = "e:\\source"; 	wchar_t buffer[10] = { 0 };  	if(p_source = fopen(fname, "r, ccs = utf - 8")) 	{ 		while(!feof(p_source)) 		{ 			printf("%s", fgetws(buffer, 10, p_source)); 		} 		printf("\n"); 	}  	fclose(p_source);  	system("pause"); 	return 0 ; }  已改为wchar_t，fgetws，但结果依然是失败，提示如下：    文件打开方式不可用  原问题是这样的：  文本文件为utf-8 无bom编码格式，文本内容包含英文字母和中文标点  C语言编写的程序想计算每行的字符个数，但是英文字母和中文标点在utf-8无bom的编码格式下的字节长度不同  造成的结果是含中文标点的行，计算的字符不准确  所以在想怎么样让程序准确判断每行的字符个数  另，把文本文件改为ansi后，输入了几个汉字，可以识别汉字，是不是说明fopen，fgets这些是以ansi编码格式读取文件的呢？

user: user-6
content: Flag      No BOM (or new file)  BOM: UTF-8  BOM: UTF-16 UNICODE   ANSI                  UTF-8       UTF-16LE      UTF-8     UTF-8                 UTF-8       UTF-16LE      UTF-16LE  UTF-16LE              UTF-8       UTF-16LE

user: user-6
content: In Visual C++ 2005, fopen supports Unicode file streams. A flag specifying the desired encoding may be passed to fopen when opening a new file or overwriting an existing file, like this:  fopen("newfile.txt", "rw, ccs=<encoding>");  Allowed values of the encoding include UNICODE, UTF-8, and UTF16-LE. If the file is already in existence and is opened for reading or appending, the Byte Order Mark (BOM) is used to determine the correct encoding. It is not necessary to specify the encoding with a flag. In fact, the flag will be ignored if it conflicts with the type of the file as indicated by the BOM. The flag is only used when no BOM is present or if the file is a new file. The following table summarizes the modes used in for various flags given to fopen and Byte Order Marks used in the file.  Flag      No BOM (or new file)  BOM: UTF-8  BOM: UTF-16 UNICODE   ANSI                  UTF-8       UTF-16LE      UTF-8     UTF-8                 UTF-8       UTF-16LE      UTF-16LE  UTF-16LE              UTF-8       UTF-16LE         If mode is "a, ccs=<encoding>", fopen will first try to open the file with both read and write access. If it succeeds, it will read the BOM to determine the encoding for this file; however, if it fails, it will use the default encoding for the file. In either case, fopen will then re-open the file with write-only access. (This applies to mode a only, not a+.)

user: user-7
content: windows下利用标准库fopen以UTF-8格式打开一个文件,要注意下面几个问题.  1.如果文件编码为UNICODE(UTF-8),有两种情况: 1)没有BOM头,调用fopen必须指定css=UTF-8. 2)有BOM头,调用fopen不要指定css=UTF-8. 2.文件编码为其它格式(如ANSI),调用fopen必须指定css=UTF-8.  fopen打开其它UNICODE(如UTF-16LE,UNICODE)等,与此类似,只是BOM头不相同. 例如 记事本中如果保存编码格式为Unicode big endian，则无法使用 ccs=UNICODE 这个功能 如果用了ccs=UNICODE，则必须使用宽字符格式的相应函数，即便文件本身编码是ANSI格式

user: user-0
content: 引用 1 楼 qq423399099 的回复:你的文件的后缀名呢？  是编码方式的问题吧，fgets以ascii编码读取，但文本是utf-8编码，所以在遇到中文字符时出现乱码，不知道我分析错了没？ 另，如果原因是这样的话，怎样让程序以utf-8读取文件呢

user: user-0
content: 引用 1 楼 qq423399099 的回复:你的文件的后缀名呢？ 并没有

user: user-7
content: 你的文件的后缀名呢？