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

news2024/11/24 13:01:45

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.coloradmin.cn/o/1224327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

订阅号和服务号有什么区别

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;我们都知道&#xff0c;服务号一个月只能发4次文章&#xff0c;但是订阅号每天都能发文章。不过在接收消息这一方面&#xff0c;服务号群发的消息有消息提醒&#xff0c;并显示在对话框&#xff1b…

ARDUINO UNO 12颗LED超酷流水灯效果

效果代码&#xff1a; #define t 30 #define t1 20 #define t2 100 #define t3 50 void setup() { // set up pins 2 to 13 as outputs for (int i 2; i < 13; i) { pinMode(i, OUTPUT); } } /Effect 1 void loop() { effect_1(); effect_1(); effect_…

视频剪辑技巧:轻松搞定视频随机合并,一篇文章告知所有秘诀

在视频制作的过程中&#xff0c;视频随机合并是一种创新的剪辑手法&#xff0c;它打破了传统的线性剪辑模式&#xff0c;使得视频剪辑更加灵活和有趣。通过将不同的视频片段随机组合在一起&#xff0c;我们可以创造出独特的视觉效果和情感氛围。这种剪辑方式让观众在观看视频时…

Redis 9 数据库

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

腾讯云服务器新用户优惠怎么领?附腾讯云新用户优惠领取链接

大家好&#xff0c;今天我们来聊聊腾讯云服务器的优惠活动&#xff01;如果你是腾讯云的新用户&#xff0c;那么你一定不能错过这个机会&#xff01; 首先&#xff0c;新用户可以领取双十一9999代金券&#xff0c;这可是一大笔钱啊&#xff01;而且&#xff0c;你还可以另外再…

sort()方法详解

作用 对数组进行排序&#xff0c;默认情况下&#xff0c;将元素转换为字符串&#xff0c;然后按照它们的UTF-16码值升序排序。 语法 sort() 元素是字符串时 默认排序时根据字典顺序进行排序的 元素是字母字符串时&#xff0c;按照字母进行升序&#xff0c; const stringAr…

Spring学习③__Bean管理

目录 IOC接口ApplicationContext 详解IOC操作Bean管理基于xml方式基于xml方式创建对象基于xml方式注入属性使用set方法进行注入通过有参数的构造进行注入p 名称空间注入&#xff08;了解&#xff09; 基于xml方式注入其他类型属性xml 注入数组类型属性 IOC接口 IOC思想基于IOC…

LM(大模型)应用开发利器之LangChain,带你走进AI世界

原文&#xff1a;LLM&#xff08;大模型&#xff09;应用开发利器之LangChain&#xff0c;带你走进AI世界 - 简书 LangChain组件图 LangChain 是什么 首先 LangChain 是一个框架&#xff0c;这个框架是用来让开发者进行 LLMs &#xff08;大语言模型&#xff09;应用开发的。…

【操作系统】磁盘物理地址怎么表示

常见主存物理地址是一串01串&#xff0c;那磁盘物理地址呢&#xff1f; 磁盘物理地址由以下组成&#xff1a; 柱面号磁头号扇区号 重点知识点辨析&#xff1a; 磁盘物理地址的翻译是由磁盘驱动程序进行的&#xff0c;目的是将逻辑上的蔟号转化为上述的物理地址 408真题溯源…

现在的各类解释非常混乱,到底什么是智慧城市?

智慧城市&#xff0c;简单来说&#xff0c;就是运用先进的信息和通信技术&#xff0c;让城市管理更加智能、高效&#xff0c;让市民的生活更加便捷、舒适。 在我们日常生活中&#xff0c;智慧城市带来的改变无处不在。 想象一下&#xff0c;当你早上醒来&#xff0c;你的手机已…

我叫:冒泡排序【JAVA】

1.什么是冒泡排序&#xff1f; 冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后&#xff08;从下标较小的元素开始)&#xff0c;依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。 2.来个实战应用 我们…

Microsoft SQL Server Management Studio(2022版本)启动无法连接到服务器

Microsoft SQL Server Management Studio&#xff08;2022版本&#xff09;启动无法连接到服务器 解决方法&#xff1a; 打开SQL Server 2022 配置管理器。 启动即可。

原来机械硬盘比内存慢10万倍

我们都知道机械硬盘的速度很慢&#xff0c;内存的速度很快&#xff0c;那么不同存储器之间的差距到底有多大呢&#xff1f; 我们先来看一幅图&#xff1a; CPU访问寄存器的时间是0.3纳秒&#xff0c;访问L1高速缓存的时间是1纳秒&#xff0c;访问L2高速缓存的时间是4纳秒… 秒…

【LeetCode刷题-双指针】--259.较小的三数之和

259.较小的三数之和 方法&#xff1a;排序双指针 class Solution {public int threeSumSmaller(int[] nums, int target) {Arrays.sort(nums);int k 0;for(int i 0;i<nums.length;i){int start i 1,end nums.length - 1;while(start < end){int sum nums[start] …

Canal+Kafka实现MySQL与Redis数据同步(一)

CanalKafka实现MySQL与Redis数据同步&#xff08;一&#xff09; 前言 在很多业务情况下&#xff0c;我们都会在系统中加入redis缓存做查询优化。 如果数据库数据发生更新&#xff0c;这时候就需要在业务代码中写一段同步更新redis的代码。 这种数据同步的代码跟业务代码糅合…

【Java程序员面试专栏 专业技能篇】Java SE核心面试指引

关于Java SE部分的核心知识进行一网打尽&#xff0c;包括四部分&#xff1a;基础知识考察、面向对象思想、核心机制策略、Java新特性&#xff0c;通过一篇文章串联面试重点&#xff0c;并且帮助加强日常基础知识的理解&#xff0c;全局思维导图如下所示&#xff1a;

微服务实战系列之Nacos

导语 欢迎来到 “Nacos” 的世界&#xff01; Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称&#xff0c;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单…

合成事件在san.js中的应用

一、 什么是合成事件 DOM3 Event 新增了合成事件(CompositionEvent ), 用于处理通常使用 IME 输入时的复杂输入序列。 二、合成事件常见事件 compositionstart&#xff1a;文本合成系统如 IME&#xff08;即输入法编辑器&#xff09;开始新的输入合成时会触发 compositionst…

【STM32】DMA(直接存储器访问)

一、DMA本质 在ADC中使用FIFO&#xff08;先进先出&#xff09;&#xff0c;当FIFO快满的时候&#xff0c;产生一个中断。在中断的时候将数据传输到SRAM&#xff0c;但是此时还是需要CPU的参与&#xff0c;但是CPU就不会一直在等待。【但是这个方法还是不能完全解决问题】 此时…

【代码随想录】算法训练计划25

1、216. 组合总和 III 题目&#xff1a; 找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9 每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 思路&am…