win32 读写UTF-8格式的文件的方法

1,写入数据

最开始是在写入数据前先写入三个字节

BYTE btHead[] = { 0xEF,0xBB,0xBF };
::WriteFile(hFile, btHead, 3, &dwWrite, 0);
::WriteFile(hFile, str, lstrlen(str)*sizeof(TCHAR), &dwWrite, 0);

这样写入后文件样式为:
在这里插入图片描述
格式是UTF-8,但后面有个BOM,而且汉字也是乱码,
最后我又测试了下用c语言写入UTF-8数据,

//打开文件,按指定编码格式打开
FILE* fp=fopen("UTF_8Test.txt", "wt+,ccs=UTF-8");//写入数据
TCHAR str[] = TEXT("测试文件,1234,abcd,ABCD");
fwrite(str, sizeof(TCHAR), lstrlen(str), fp);//关闭
fclose(fp);

汉字不是乱码了,但是格式仍然是UTF-8 BOM

这就是不我想要的效果。

最后查找一翻资料后,
1。先把要保存的字符串转化为UTF-8格式的char字符串
2。在写入char字符串到文件中

//lpBuffer是传来的宽字符串的指针
//nBufferLeng是字符串的字符个数(用lstrlen求出的长度)//求字符串转为UTF-8的字符长度
int size = ::WideCharToMultiByte(CP_UTF8, 0, (LPTSTR)lpBuffer, nBufferLeng, NULL, 0, NULL,NULL);//再转为char字符串
char* pTem = new char[size+1];
memset(pTem, 0, size);
::WideCharToMultiByte(CP_UTF8, 0, (LPTSTR)lpBuffer, nBufferLeng, pTem, size, nullptr, nullptr);
pTem[size] = '\0';//最后写入char字符串
bResult = ::WriteFile(m_hFile, pTem, size, &dwWrite, 0);
delete[] pTem;

这样写入文件的效果:

在这里插入图片描述
这样汉字就不会出现乱码了,格式也是UTF-8,没有后面的BOM了

2。读取数据

数据的读取和写入一样,先读取数据到char数组中,再转为UTF-8格式的宽字符串中

//获得文件字节长度
int n = GetFileSize();//写入char数组中
char* pChar = new char[n+1];
bResult = ::ReadFile(m_hFile, pChar, n, &dwRead, 0);
pChar[n] = '\0';//计算字符串转UTF-8的字符长度
int len = MultiByteToWideChar(CP_UTF8, 0, pChar, strlen(pChar), nullptr, 0);//转为TCHAR字符数组
TCHAR* pWChar = new TCHAR[len+1];
memset(pWChar, 0, len);
MultiByteToWideChar(CP_UTF8, 0, pChar, strlen(pChar), pWChar, len);
pWChar[len] = '\0';//拷贝到函数外面的字符指针
lstrcpy((LPTSTR)lpBuffer, pWChar);//清除内存
delete[] pWChar;
delete[] pChar;

读取数据的效果:
在这里插入图片描述

4。完整代码片段

QFile.h文件

//文件操作类
// 对Ascii,Unicode,UTF_8,Binary
// 四种文件格式的读写
class QFile
{
public:QFile();~QFile();
public:enum OpenModule	//文件打开模式{Read = GENERIC_READ,	//只读模式Write = GENERIC_WRITE,	//只写模式WriteRead = GENERIC_WRITE | GENERIC_READ //读写模式};enum FileEncoded //文件编码{enAnsii=0,	//Ansi编码enUnicode,	//Unicode编码enUTF_8,	//UTF——8编码enBinary	//二进制编码};public://以指定模式打开文件BOOL Open(const TCHAR* pFileName, OpenModule openModule);void Close();BOOL FileExists(const TCHAR* pFileName);//检查文件是否存在BOOL CreateNewFile(const TCHAR* pFileName); //创建新文件//以指定编码格式写入数据int WriteFile(void* lpBuffer, int nBufferLeng, FileEncoded encodedType);//以指定编码格式读取数据int ReadFile(void* lpBuffer, int nBufferLeng, FileEncoded encodedType);//获得文件的字节长度int GetFileSize()const;
public:HANDLE m_hFile;
};

QFile.cpp文件

//写入数据
int QFile::WriteFile(void* lpBuffer, int nBufferLeng, FileEncoded encodedType)
{if (lpBuffer == nullptr)return -1;if (m_hFile == INVALID_HANDLE_VALUE)return -1;DWORD dwWrite = 0;BOOL bResult = FALSE;//编码UTF-8的写入if (encodedType == enUTF_8){int size = ::WideCharToMultiByte(CP_UTF8, 0, (LPTSTR)lpBuffer, nBufferLeng, NULL, 0, NULL,NULL);char* pTem = new char[size];memset(pTem, 0, size);::WideCharToMultiByte(CP_UTF8, 0, (LPTSTR)lpBuffer, nBufferLeng, pTem, size, nullptr, nullptr);pTem[size] = '\0';bResult = ::WriteFile(m_hFile, pTem, size, &dwWrite, 0);return bResult ? dwWrite : -1;}//Unicode编码先写入两个字节,再写入数据if (encodedType == enUnicode){BYTE btHead[] = { 0xFF,0xFE };bResult = ::WriteFile(m_hFile, btHead, 2, &dwWrite, 0);}//其他的都是直接写入数据bResult = ::WriteFile(m_hFile, lpBuffer, nBufferLeng, &dwWrite, 0);return bResult ? dwWrite : -1;
}//读取数据
int QFile::ReadFile(void* lpBuffer, int nBufferLeng, FileEncoded encodedType)
{if (lpBuffer == nullptr)return -1;if (m_hFile == INVALID_HANDLE_VALUE)return -1;DWORD dwRead = 0;BOOL bResult = FALSE;//编码格式UTF-8的读取if (encodedType == enUTF_8){char* pChar = new char[nBufferLeng +1];bResult = ::ReadFile(m_hFile, pChar, nBufferLeng, &dwRead, 0);pChar[nBufferLeng] = '\0';int len = MultiByteToWideChar(CP_UTF8, 0, pChar, strlen(pChar), nullptr, 0);TCHAR* pWChar = new TCHAR[len+1];memset(pWChar, 0, len);MultiByteToWideChar(CP_UTF8, 0, pChar, strlen(pChar), pWChar, len);pWChar[len] = '\0';lstrcpy((LPTSTR)lpBuffer, pWChar);delete[] pWChar;delete[] pChar;return bResult ? dwRead : -1;}//编码Unicode,先跳过前两个字节再读取数据if (encodedType == enUnicode){SetFilePointer(m_hFile, 2, 0, FILE_BEGIN);}bResult = ::ReadFile(m_hFile, lpBuffer, nBufferLeng, &dwRead, 0);return bResult ? dwRead : -1;
}//…………

5。使用

//1.写入数据
QFile f;
f.Open(Utf_8Txt, QFile::Write);TCHAR str[] = TEXT("测试数据,1234,ABCD");
f.WriteFile(str, lstrlen(str), QFile::enUTF_8);f.Close();//2.读取数据
QFile f;
f.Open(Utf_8Txt, QFile::Read);TCHAR str[20] = { 0 };
int nLeng = f.GetFileSize();f.ReadFile(str, nLeng, QFile::enUTF_8);f.Close();MessageBox(nullptr, str, TEXT("数据的读取"), 0);

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

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

相关文章

网络协议--TCP连接的建立与终止

18.1 引言 TCP是一个面向连接的协议。无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。本章将详细讨论一个TCP连接是如何建立的以及通信结束后是如何终止的。 这种两端间连接的建立与无连接协议如UDP不同。我们在第11章看到一端使用UDP向另一端发…

jsp 网上订餐Myeclipse开发mysql数据库web结构java编程计算机网页项目

选题目的 本设计课题为网上订餐系统设计与实现,提供无纸化点餐、支付,实现点餐快捷,方便管理。餐厅电子化是目前的潮流和趋势,大多数企业都将公司内部运营流程电子化。网上订餐管理系统应运而生,能够有效提高公司的管…

SpringBoot集成与应用Neo4j

文章目录 前言集成使用定义实体配置定义Repository查询方法方式一:Query方式二:Cypher语法构建器方式三:Example条件构建器方式四:DSL语法 自定义方法自定义接口继承自定义接口实现自定义接口neo4jTemplateNeo4jClient 自定义抽象…

要在VMware(虚拟机)上获取相机连接状态并显示在主界面上,您可以使用以下步骤:

在VM上安装相机驱动程序:确保VM中已安装对应的相机驱动程序,以便能够连接和使用相机。 检查相机连接状态:在VM中,打开设备管理器(Device Manager)并检查相机是否显示为已连接状态。如果显示为已连接&#…

2024年湖北黄冈建安ABC建筑企业专职安全员报名事项

2024年湖北黄冈建安ABC建筑企业专职安全员报名事项 专职安全员一般是指从事安全管理方面的工作,普遍的是建筑施工行业,建筑工地安全员,专职安全员C证,黄冈建筑安全员ABC-建筑单位在黄冈,只能在黄冈报考建筑安全员ABC。…

【Amazon】跨AWS账号资源授权存取访问

文章目录 一、实验框架图二、实验过程说明三、实验演示过程1、在A账号中创建S3存储桶2、在A账号创建S3存储桶访问策略3、在A账号创建信任开发账号的角色4、在B账号为用户添加内联策略5、在B账号中切换角色,以访问A账号中的S3资源 四、实验总结 一、实验框架图 本次…

保姆级安装Jdk,Tomact,Mysql在linux中并且部署项目

🌟在这里,我要推荐给大家我的专栏《Linux》。🎯🎯 🚀无论你是编程小白,还是有一定基础的程序员,这个专栏都能满足你的需求。我会用最简单易懂的语言,带你走进代码的世界,…

【机器学习合集】模型设计之注意力机制动态网络 ->(个人学习记录笔记)

文章目录 注意力机制1. 注意力机制及其应用1.1 注意力机制的定义1.2 注意力机制的典型应用 2. 注意力模型设计2.1 空间注意力机制2.2 空间注意力模型2.3 通道注意力机制2.4 空间与通道注意力机制2.5 自注意力机制2.5 级联attention 动态网络1. 动态网络的定义2. 基于丢弃策略的…

SpringBoot----自定义Start

一,为什么要定义Start 向阿里云OSS如果我们要引入的话很麻烦,所以我们可以自定义一些组件, 然后我们只需要在pom文件中引入对应的坐标就可以 二,怎么定义(以阿里云OSS为例) 1, 定义两个组件模块…

【前端早早聊直播回顾】Harmony Next 与 Flutter 的不解之缘

Hello 大家好,我是 Flutter GDE 郭树煜,本次要分享的话题是关于鸿蒙与 Flutter 的故事,可能没接触过的会感觉有点懵,Harmony 和 Flutter 有啥关系,它们怎么会被放到一起讲了呢?接下来就让我们来聊聊这个问题…

秒级启动的集成测试框架

本文介绍了一种秒级启动的集成测试框架,使用该框架可以方便的修改和完善测试用例,使得测试用例成为测试过程的产物。 背景 传统的单元测试,测试的范围往往非常有限,常常覆盖的是一些工具类、静态方法或者较为底层纯粹的类实现&…

第04章_运算符

第04章_运算符 讲师:尚硅谷-宋红康(江湖人称:康师傅) 官网:http://www.atguigu.com 1. 算术运算符 算术运算符主要用于数学运算,其可以连接运算符前后的两个数值或表达式,对数值或表达式进行…