fopen/fwrite/fread 对UNICODE字符写入的总结

windows对fopen函数进行了升级,可以支持指定文件的编码格式(ccs参数指定)。

例如:

FILE *fp = fopen("newfile.txt", "rt+, ccs=UTF-8");

当以 ccs 模式打开文件时,进行读写操作的数据应为 UTF-16 编码,存储为 wchar_t 类型。这意味着你应使用如 fgetwsfputws 等宽字符版本的函数进行读写,或者使用fread/fwrite读取和写入wchar_t 类型数据。

  • 我们下面来编写一个例子,文件编码格式指定为UTF-8,写入字符串带中文和英文,代码如下:
#include <stdafx.h>
#include <stdio.h>
void main()
{FILE *g_LogFile = fopen("D:\\UTF8.log", "w,ccs=UTF-8");int num = 10;while (--num > 0){//用fputws和fwrite能得到相同的效果//fputws(L"hunan bowan tech 湖南泊湾科技有限公司\n", g_LogFile);wchar_t szLog[1024] = L"hunan bowan tech 湖南泊湾科技有限公司\n";fwrite(szLog, 2, wcslen(szLog), g_LogFile);}fclose(g_LogFile);
}

执行完上面代码,我们可以得到一个文件,用记事本打开文件如下:

然后用WinHex打开文件查看一下每个字节的数据如下:

从截图可知,确实是将Unicode字符集转成了UTF-8编码格式的字符集,然后写入了文件。

UTF-8编码格式的文件前面有3个字节的文件头。

  • 我们下面来编写另外一个例子,文件编码格UNICODE,写入字符串带中文和英文,代码如下:
#include <stdafx.h>
#include <stdio.h>
void main()
{FILE *g_LogFile = fopen("D:\\UNICODE.log", "w,ccs=UNICODE");int num = 10;while (--num > 0){//fputws(L"hunan bowan tech 湖南泊湾科技有限公司\n", g_LogFile);wchar_t szLog[1024] = L"hunan bowan tech 湖南泊湾科技有限公司\n";fwrite(szLog, 2, wcslen(szLog), g_LogFile);//char szLog[1024] = "xiaoge is very good 我爱中国\n";//fwrite(szLog, 1, 19, g_LogFile);}fclose(g_LogFile);
}

上面代码执行结果如下,记事本打开:

WinHex打开:

从截图可知,写入文件的编码格式为UNICODE编码,UNICODE编码格式的文件前面有2个字节的文件头。

  • 当以 ccs 模式打开文件时,如果读写数据为char类型,则需要写入偶数字节,如果写入奇数字节,则会报错。

下面是写入奇数字节的代码:

#include <stdafx.h>
#include <stdio.h>
void main()
{FILE *g_LogFile = fopen("D:\\UNICODE.log", "w,ccs=UNICODE");int num = 10;while (--num > 0){//fputws(L"hunan bowan tech 湖南泊湾科技有限公司\n", g_LogFile);//wchar_t szLog[1024] = L"hunan bowan tech 湖南泊湾科技有限公司\n";//fwrite(szLog, 2, wcslen(szLog), g_LogFile);char szLog[1024] = "xiaoge is very good 我爱中国\n";fwrite(szLog, 1, 19, g_LogFile);}fclose(g_LogFile);
}

执行上面代码会报错,报错如下:

如果我们将代码改为偶数字节,代码如下:

#include <stdafx.h>
#include <stdio.h>
void main()
{FILE *g_LogFile = fopen("D:\\UNICODE.log", "w,ccs=UNICODE");int num = 10;while (--num > 0){//fputws(L"hunan bowan tech 湖南泊湾科技有限公司\n", g_LogFile);//wchar_t szLog[1024] = L"hunan bowan tech 湖南泊湾科技有限公司\n";//fwrite(szLog, 2, wcslen(szLog), g_LogFile);char szLog[1024] = "xiaoge is very good 我爱中国\n";fwrite(szLog, 1, 20, g_LogFile);}fclose(g_LogFile);
}

代码能执行成功,写入文件用记事本打开如下:

用WinHex打开如下:

从上面截图可知,数据确实成功写入了,文件也是UNICODE编码格式,但是写入的字符集不是UNICODE编码的,所以记事本打开会出现乱码。

从上面的代码执行结果确实验证了前面的结论:用css指定了文件的编码格式,读写数据的类型一定要用wchar_t类型,否则读写的数据是错误的。

  • 当不以 ccs 模式打开文件时,写入wchar_t类型数据,代码如下:
#include <stdafx.h>
#include <stdio.h>
void main()
{FILE *g_LogFile = fopen("D:\\ANSI.log", "w");int num = 10;while (--num > 0){//fputws(L"hunan bowan tech 湖南泊湾科技有限公司\n", g_LogFile);wchar_t szLog[1024] = L"hunan bowan tech 湖南泊湾科技有限公司\n";fwrite(szLog, 2, wcslen(szLog), g_LogFile);//char szLog[1024] = "xiaoge is very good 我爱中国\n";//fwrite(szLog, 1, 20, g_LogFile);}fclose(g_LogFile);
}

执行上面代码,用记事本打开文件如下:

用WinHex打开文件如下:

从上面截图可知,文件编码格式为ANSI。由于编码格式和字节流对应不上,所以记事本显示乱码。

如果我们将写入的字节流改为char类型的数据,编码格式和字节流就能对应上,都为ANSI,此时文件显示也没问题。

  • 我们将写入文件的模式改为wb方式,文件编码格式将根据我们写入字节流的类型推断出来。

例如,我们用wb的模式写入wchar_t类型数据,代码如下:

#include <stdafx.h>
#include <iostream>
void main()
{FILE *g_LogFile = fopen("D:\\AUTO.log", "wb");int num = 10;while (--num > 0){//fputws(L"hunan bowan tech 湖南泊湾科技有限公司\n", g_LogFile);wchar_t szLog[1024] = L"hunan bowan tech 湖南泊湾科技有限公司\n";fwrite(szLog, 2, wcslen(szLog), g_LogFile);//char szLog[1024] = "hunan bowan tech 湖南泊湾科技有限公司\n";//fwrite(szLog, 1, strlen(szLog), g_LogFile);}fclose(g_LogFile);
}

执行上面代码,用记事本打开文件如下:

如果我们用wb的模式写入char类型数据,代码如下:

#include <stdafx.h>
#include <iostream>
void main()
{FILE *g_LogFile = fopen("D:\\AUTO.log", "wb");int num = 10;while (--num > 0){//fputws(L"hunan bowan tech 湖南泊湾科技有限公司\n", g_LogFile);//wchar_t szLog[1024] = L"hunan bowan tech 湖南泊湾科技有限公司\n";//fwrite(szLog, 2, wcslen(szLog), g_LogFile);char szLog[1024] = "hunan bowan tech 湖南泊湾科技有限公司\n";fwrite(szLog, 1, strlen(szLog), g_LogFile);}fclose(g_LogFile);
}​

执行上面代码,用记事本打开文件如下:


综上所述可知:

如果用"w"的模式,写入wchar_t类型字节数据,最好通过ccs指定编码格式。

否则就用“wb”的模式写入。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/191614.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode Hot100之十:239.滑动窗口最大值

题目 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 提示&#xff1a; 1 < nums.length < 10^5 -10^4 < nums[i…

QT专栏1 -Qt安装教程

#本文时间2023年11月18日&#xff0c;Qt 6.6# Qt 安装简要说明&#xff1a; Qt有两个版本一个是商业版本&#xff08;收费&#xff09;&#xff0c;另一个是开源版本&#xff08;免费&#xff09;&#xff1b; 打开安装程序时&#xff0c;通过判断账号是否有公司&#xff0c;安…

centos7安装mongodb

1、下载mongodb https://www.mongodb.com/try/download/community 2、解压 3、重命名 4、创建mongodb的data、logs目录 5、启动mongodb, bin/mongod --port27017 --dbpath/data/program/mongodb/data --logpath/data/program/mongodb/logs/mongodb.log --bind_ip0.0.0.0 --f…

linux 服务器进程、端口查找,nginx 配置日志查找,lsof 命令详解

一 、根据端口号 查看文件的部署位置 1.1 使用查看端口号对应的进程信息 方式一 &#xff1a; 使用netstat命令 netstat -tuln | grep 端口号-t&#xff1a;显示TCP连接 -u&#xff1a;显示UDP连接 -l&#xff1a;仅显示监听状态的连接 -n&#xff1a;以数字形式显示端口…

App测试经典面试题及参考答案

最近整理了一些关于App测试的面试题。 本参照答案是本人在工作实践中总结&#xff0c;仅代表个人观点&#xff0c;如有错误&#xff0c;请谅解。 1、说一些你在测试过程中常用到的adb命名 2、APP测试与web测试的区别&#xff1f; 3、APP闪退有哪些原因造成的&#xff1f; …

人工智能轨道交通行业周刊-第65期(2023.10.30-11.19)

本期关键词&#xff1a;高铁自主创新、智慧城轨、调车司机、大模型垂直应用、大模型幻觉 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通RailMetro轨道…

STL简介

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解c中的STL库 > 毒鸡汤&#xff1a;路难行&a…

Redis 9 数据库

4 设置键的生存时间或过期时间 通过EXPIRE命令或者PEXPIRE命令&#xff0c;客户端可以以秒或者毫秒精度为数据库中的某个键设置生存时间&#xff08;TimeToLive&#xff0c;TTL&#xff09;&#xff0c;在经过指定的秒数或者毫秒数之后&#xff0c;服务器就会自动删除生存时间…

记录联系ThinkPad T490扬声器无声音但插耳机有声音的解决办法

型号&#xff1a;联想ThinkPad T490&#xff0c;系统Win10 64位。 现象&#xff1a;扬声器无声音&#xff0c;插耳机有声音。且右下角小喇叭正常&#xff0c;设备管理器中驱动显示一切也都正常&#xff08;无黄色小叹号&#xff09;。 解决办法&#xff1a; 尝试了各种方法&a…

在vmware中给linux添加硬盘

1.必须在断开linux电源的情况下&#xff0c;才能添加硬盘成功。注&#xff1a;自己好几次在开机状态下添加硬盘都失败了&#xff0c;然后关机后&#xff0c;又试了下&#xff0c;居然成功了。

链式前向星

性质 一种邻接表的写法 关键点&#xff1a; 数据结构 // 边 class Edge {int next; // 指向相同起始点的下一条边int to; // 邻接点int w; // 权重 } Edge[] edge new Edge[9]; // edge[cnt]表示编号为cnt的边// 用数组表示 int[] next new int[MAX]; int[] to new int[M…

【机器学习Python实战】logistic回归

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习python实战 欢迎订阅&#xff01;后面的内容会越来越有意思~ ⭐内容说明&#xff1a;本专栏主要针对机器学习专栏的基础内容进行python的实现&#xff0c;部分…