C语言操作UTF-8编码和GBK编码的文件的示例

news2024/11/23 4:50:32

一、基本介绍

在C语言中,处理文件编码(如UTF-8或GBK)时,需要注意C标准库中的文件操作函数(如fopen, fread, fwrite, fclose等)并不直接支持Unicode或特定字符集的编码。这些函数通常处理字节流,而不是字符流,因此需要确保在读取或写入文件时以正确的编码格式处理这些字节。

对于UTF-8编码,由于它是兼容ASCII的,并且是一个变长编码,可以直接使用C标准库的文件操作函数。但是,对于GBK(或GB2312、GB18030),可能需要使用特定的库(如ICU或 iconv)来在C语言中处理这种编码,或者确保操作环境(如操作系统或文本编辑器)能够正确解释这些文件。

二、UTF-8编码文件测试代码

基本的示例简单演示如何在C语言中写入和读取UTF-8编码的文件。

//写入UTF-8文件
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>
  
int main(void)
 {  
        FILE *file = fopen("utf8_text.txt", "w");  
        if (file == NULL) 
        {  
                perror("Error opening file");  
                return EXIT_FAILURE;  
        }  
    
        // UTF-8编码的字符串(对于ASCII字符,UTF-8编码与ASCII相同)  
        const char *text = "你好,世界!";  
        fwrite(text, sizeof(char), strlen(text), file);  
    
        fclose(file);  
        return 0;  
}

在这里插入图片描述
查看写入的文本文件
在这里插入图片描述
如果切换为别的格式,则会显示乱码,如下:
在这里插入图片描述

//读取UTF-8文件
#include <stdio.h>  
#include <stdlib.h>  
  
#define BUFFER_SIZE 1024  
  
int main(void) 
{  
        FILE *file = fopen("utf8_text.txt", "r");  
        if (file == NULL) 
        {  
                perror("Error opening file");  
                return EXIT_FAILURE;  
        }  
    
        char buffer[BUFFER_SIZE];  
        size_t n = fread(buffer, sizeof(char), BUFFER_SIZE - 1, file);  
        if (n > 0) 
        {  
                buffer[n] = '\0'; // 确保字符串以null结尾  
                printf("%s\n", buffer);  
        }  
    
        fclose(file);  
        return 0;  
}

注意:源文件和终端/控制台都支持UTF-8编码。如果环境不支持UTF-8,需要配置编译器、IDE或终端来正确显示UTF-8编码的文本。

三、GBK编码文件测试代码

如果源字符串已经是GBK编码的字节序列(即已经有了一个unsigned char[]数组,它包含了正确的GBK编码的字节),可以直接使用 fwrite 来写入文件。
如果是一个UTF-8编码的字符串,需要先将其转换为GBK编码的字节序列。这通常需要使用一个库来完成,比如Linux 下的 iconv库
示例:将UTF-8字符串转换为GBK并写入文件。

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <iconv.h>  
  
int main(void) 
{  
        // 原始UTF-8编码的字符串  
        const char *utf8_text = "你好,世界!";  
        size_t utf8_len = strlen(utf8_text);  
    
        // 转换输出缓冲区的大小(可能需要调整以适应实际转换的大小)  
        size_t gbk_size = 4 * utf8_len + 1; // 假设GBK编码的字符最多是UTF-8的4倍长,再加一个null终止符  
        unsigned char gbk_buffer[gbk_size];  
    
        // 初始化iconv_t转换描述符  
        iconv_t cd = iconv_open("GBK", "UTF-8");  
        if (cd == (iconv_t)-1) 
        {  
                perror("iconv_open");  
                return EXIT_FAILURE;  
        }  
    
        // 转换UTF-8到GBK  
        char *inbuf = (char *)utf8_text;  
        size_t inbytesleft = utf8_len;  
        char *outbuf = (char *)gbk_buffer;  
        size_t outbytesleft = gbk_size;  
        size_t result = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);  
        if (result == (size_t)-1)
        {  
                perror("iconv");  
                iconv_close(cd);  
                return EXIT_FAILURE;  
        }  
    
        // 确保字符串以null结尾(如果转换后的长度小于缓冲区大小)  
        *outbuf = '\0';  
    
        // 写入GBK编码的文件  
        FILE *file = fopen("gbk_text.txt", "wb"); // 使用二进制模式写入  
        if (file == NULL) 
        {  
                perror("Error opening file");  
                iconv_close(cd);  
                return EXIT_FAILURE;  
        }  
        fwrite(gbk_buffer, 1, outbuf - (char *)gbk_buffer, file); // 写入转换后的数据(不包括null终止符)  
        fclose(file);  
    
        // 关闭iconv转换描述符  
        iconv_close(cd);  
    
        return 0;  
}

①示例中的gbk_size是一个估计值,需要根据实际情况调整它以确保转换后的数据不会溢出缓冲区。
②使用iconv函数时,输入和输出缓冲区都是char * 类型,但在这里我们将其强制转换为unsigned char * 来避免可能的符号扩展问题。在大多数情况下,这不会造成问题,因为iconv只关心字节,而不关心它们的符号。
③写入文件时使用了二进制模式(“wb”),以确保不会进行任何字符到字节的转换(例如换行符的转换)。

测试结果:
在这里插入图片描述
改成 UTF-8 编码则是乱码,如下:
在这里插入图片描述

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

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

相关文章

FreeRTOS基础(十一):消息队列

本文将详细全方位的讲解FreeRTOS的消息队列&#xff0c;其实在FreeRTOS中消息队列的重要性也不言而喻&#xff0c;与FreeRTOS任务调度同等重要&#xff0c;因为后面的各种信号量基本都是基于消息队列的。 目录 一、消息队列的简介 1.1 产生的原因 1.2 消息队列的解决办法 …

防病毒克星——白名单可信系统

白名单作为一种网络安全措施&#xff0c;其核心概念在于限制用户只能访问网络所有者定义的受信任内容。这种机制在保护系统免受恶意软件、病毒等攻击方面发挥着重要作用。然而&#xff0c;关于白名单是否可以防病毒的问题&#xff0c;实际上涉及了多个方面的考虑。 首先&#x…

B=2W,奈奎斯特极限定理详解

一直没搞明白奈奎斯特极限定理的含义&#xff0c;网上搜了很久也没得到答案。最近深思几天后&#xff0c;终于有了点心得。顺便吐槽一下&#xff0c;csdn的提问栏目&#xff0c;有很多人用chatgpt秒回这个事&#xff0c;实在是解决不了问题&#xff0c;有时候人的问题大多数都是…

台式机安装Windows 11和Ubuntu 22双系统引导问题

一、基本情况 1.1、硬件情况 电脑有2个NVMe固态硬盘&#xff0c;1个SATA固态硬盘&#xff0c;1个机械硬盘。其中一个NVMe固态硬盘是Windows系统盘&#xff0c;另一个NVMe固态为Windows软件和文件盘&#xff0c;SATA固态硬盘为Ubuntu专用&#xff0c;机械硬盘为数据备份盘。 …

Java | Leetcode Java题解之第136题只出现一次的数字

题目&#xff1a; 题解&#xff1a; class Solution {public int singleNumber(int[] nums) {int single 0;for (int num : nums) {single ^ num;}return single;} }

Ubuntu下安装和配置Redis

目录 1、更新软件包 2、安装Redis 3、启动 Redis临时服务 4、测试Redis服务 5、配置redis服务 6、Redis服务控制命令 1、更新软件包 执行sudo apt-get update更新软件包 sudo apt-get update2、安装Redis 执行sudo apt-get install redis-server 安装命令 sudo apt i…

CLion配置

下载环境&#xff1a;MinGW-w64 - for 32 and 64 bit Windows - Browse Files at SourceForge.net 解压后找一个位置存放&#xff0c;一般放在和ide同一目录&#xff0c;方便查找 个人习惯配置调整&#xff1a; 项目创建 修改ide解码形式 项目右下角一般默认是utf8 文件编码改…

【C++题解】1074 - 小青蛙回来了

问题&#xff1a;1074 - 小青蛙回来了 类型&#xff1a;需要找规律的循环 题目描述&#xff1a; 关于小青蛙爬井的故事&#xff0c;你应该早就听过了&#xff1a;井深10 尺&#xff0c;小青蛙从井底向上爬&#xff0c;每个白天向上爬 3 尺&#xff0c;每个晚上又滑下来 2 尺&…

kafka安装流程

安装kafka前需要安装zookeeper zookeeper安装教程 1.新建一个logs文件夹 2.修改配置文件 3.修改listeners参数 4.以管理员身份启动kafka服务 .\bin\windows\kafka-server-start.bat .\config\server.properties 如果报 输入行太长。 命令语法不正确。 解决方案如下&#x…

全流程透明双语大语言模型MAP-Neo,4.5T 高质量数据训练

前言 近年来&#xff0c;大语言模型 (LLM) 已经成为人工智能领域最热门的研究方向之一&#xff0c;并在各种任务中展现出前所未有的性能。然而&#xff0c;由于商业利益的驱动&#xff0c;许多最具竞争力的模型&#xff0c;例如 GPT、Gemini 和 Claude&#xff0c;其训练细节和…

codeforces round 949 div2

A Turtle and Piggy Are Playing a Game 题目&#xff1a; 思路&#xff1a;输出2的幂次b使得2^b为最大的不超过x的数 代码&#xff1a; #include <iostream>using namespace std;const int N 2e5 10;void solve() {int l, r;cin >> l >> r;if(r % 2) …

哈希表和二维矩阵的结合-2352. 相等行列对(新思路、新解法)

题目链接及描述 . - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/equal-row-and-column-pairs/description/?envTypest…

制作AI问答机器人的优势和技巧

AI问答机器人已经成为我们生活和工作中的得力助手&#xff0c;应用在社会各个不同的领域中&#xff0c;它们能帮助我们快速获取信息&#xff0c;以提高做事效率&#xff0c;很多企业为了让企业的运营更加高效&#xff0c;为了从众多竞争对手中脱颖而出&#xff0c;纷纷开始制作…

VirtualBox 虚拟机中的 centos7 系统拉取 docker 镜像常见报错及解决方法

一、拉取镜像时报错&#xff1a;Error response from daemon: Get "https://registry-1.docker.io/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority 原因&#xff1a;&#xff08;文心一言给出的原因&#xff09; 这个错误…

ctfshow web

红包题第二弹 <?phpif(isset($_GET[cmd])){$cmd$_GET[cmd];highlight_file(__FILE__);if(preg_match("/[A-Za-oq-z0-9$]/",$cmd)){die("cerror");}if(preg_match("/\~|\!|\|\#|\%|\^|\&|\*|\(|\)|\&#xff08;|\&#xff09;|\-|\_|\{|\}|\…

JVM运行时数据区 - 程序计数器

运行时数据区 Java虚拟机在执行Java程序的过程中&#xff0c;会把它管理的内存划分成若干个不同的区域&#xff0c;这些区域有各自的用途、创建及销毁时间&#xff0c;有些区域随着虚拟机的启动一直存在&#xff0c;有些区域则随着用户线程的启动和结束而建立和销毁&#xff0…

c#vb代码互转工具

下载地址&#xff1a; https://download.csdn.net/download/wgxds/88979921

【MMU】——MMU 相关的 CP15 寄存器

文章目录 MMU 相关的 CP15 寄存器C1(System Control Register)C2(Translation Table Base Control Register)C3(Domain Access Control Register)C5(Data Fault Status Register)C6(Data Fault Address Register)C9C10MMU 相关的 CP15 寄存器 寄存器作用寄存器 C1 中…

信息系统项目管理师0147:工具与技术(9项目范围管理—9.3规划范围管理—9.3.2工具与技术)

点击查看专栏目录 文章目录 9.3.2 工具与技术 9.3.2 工具与技术 专家判断 规划范围管理过程中&#xff0c;应征求具备如下领域相关专业知识或接受过相关培训的个人或小组 的意见&#xff0c;涉及的领域包括&#xff1a;以往类似项目&#xff1b;特定行业、学科和应用领域的信息…

Linux操作系统:Spark在虚拟环境下的安装及部署

将Spark安装到指定目录 // 通过wget下载Spark安装包 $ wget https://d3kbcqa49mib13.cloudfront.net/spark-2.1.1-bin-hadoop2.7.tgz // 将spark解压到安装目录 $ tar –zxvf spark-2.1.1-bin-hadoop2.7.tgz –C /usr/local/ // 重命名 $ mv /usr/local/spark-2.1.1-bin-hado…