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

一、基本介绍

在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 编码则是乱码,如下:
在这里插入图片描述

在C语言中,GBK(国标GB2312字符集)UTF-8是两个不同的字符编码体系。GBK通常占用2字节表示汉字,而UTF-8可以是1到4字节。为了计算GBK编码转换为UTF-8后数据长度的变化,我们需要考虑每个GBK字符转换的情况。 对于每一个GBK字符(16位),如果是简体中文常用字符,它对应的是单字节的UTF-8编码,长度不变;但对于一些繁体字、生僻字或者是特殊符号,UTF-8可能会用到3个字节来表示。因此,如果都是常见字符,则长度增加0字节;若包含非常用字符,长度会增加1-2字节。 具体地,你可以遍历GBK字符串,每遇到一个字符,检查其是否是UTF-8的单字节编码。如果是,长度加1;如果不是,长度加3。最后,加上初始GBK字符串的长度就是转换后的UTF-8总长度。 这里是一个简化版的示例函数,假设`GBK_string`是输入的GBK编码字符串: ```c #include <stdio.h> #include <wchar.h> size_t gbk_to_utf8_length(char* GKB_string) { size_t utf8_length = 0; wchar_t wc; // 存储宽字符 for (wc = *GBK_string++; UTF8toutf16(&wc, &wc) == 0; ++GBK_string) { if (wc <= 0x7F) { // 单字节字符(UTF-8utf8_length += 1; } else { utf8_length += 3; // 非常用字符,通常是3字节 } } return utf8_length + (GBK_string - GKB_string); // 加上剩余未处理部分 } int main() { char gbk_str[] = "这是一段GBK字符串"; printf("转换后的UTF-8长度为:%zu\n", gbk_to_utf8_length(gbk_str)); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值