[字符编码]windwos下使用libiconv转换编码格式(二)
在http://t.csdnimg.cn/PLUuz笔记中实现了常用编码格式转换的功能,但这还是一个demo。因为代码中向libiconv库函数传递的字符串是存放在堆空间中的(我也是从网上找例子测试,是否一定要开辟堆空间存放还有待考证),如果一次性转换的字节数很巨大的话,就会导致内存空间不足,进而引发功能异常。
所以,对于需要大量转换的数据,应该采取分段多次转换的方法。
经过观察,有的编码格式每个字符对应的字节是固定的,这样分段是容易的。比如GB2312格式,一个字符占两个字节,那么每次处理的字节数就是2的整倍数即可。
除了上面说的字节数固定的情况,还有向utf8这种字符字节数会变化的情况,这种转换则需要复杂些的处理。
#include <iostream>#include <fstream> #include <string> #include <bitset> #include "iconv.h" //包函libiconv库头文件//导入libiconv库#pragma comment(lib,"libiconv.lib")bool readfile(const std::string& _filepath, std::string& _filecontent){bool res = false;std::ifstream file(_filepath);if (!file.is_open()) { // 检查文件是否成功打开 std::cerr << "无法打开文件" << _filepath << std::endl;}else {std::string line;while (std::getline(file, line)) { // 逐行读取文件内容 _filecontent += line;}res = true;}file.close(); // 关闭文件return res;}//使用 libiconv 进行int TransCore(const char* _pdesc, const char* _psrc, const char* _pstrin, size_t ilen, char* _pstrout, size_t* _polen){const char** ppin = &_pstrin;char** ppout = &_pstrout;iconv_t cd = iconv_open(_pdesc, _psrc);if (cd == (iconv_t)-1) {return -1;}memset(_pstrout, 0, *_polen);int res = iconv(cd, ppin, &ilen, ppout, _polen);std::cout <<__FUNCTION__<< " exec res = " << res << std::endl;iconv_close(cd);return res;}/*desc 目标编码字符串src 源编码字符串_strin 转换前内容_strout 转换后内容*/bool TransEncodeFormat(const char* _desc, const char* _src, const std::string& _strin, std::string& _strout) {bool res = false;if (_desc == nullptr || _src == nullptr || _strin.empty()) {std::cout << "入参不符合要求" << std::endl;return res;}size_t inlen = _strin.length();#ifdef LOGstd::cout << "需要转换的内容 : [" << _strin << "]" << std::endl;std::cout << "需要转换的字节数 : [" << inlen << "]" << std::endl;#endifsize_t outlen = inlen * 10;char* tempout = new char[outlen];if (TransCore(_desc, _src, _strin.c_str(), inlen, tempout, &outlen) == 0 && tempout != nullptr) {res = true;}#ifdef LOGstd::cout << "转换后的内容 : [" << tempout << "]" << std::endl;#endifstd::string temp(tempout);_strout = tempout;delete[] tempout;tempout = nullptr;return res;}/*描述 : 在_strin字符串是正确的utf8格式的情况下,分段将utf8字符转换成其他编码格式内容_desc : 目标编码格式_strin : 被转换的uft8字符串内容_strout: 转换后字符串内容_segnum: 一段字符串字节个数,默认是100字节返回值 : true 转换成功 false转换失败*/bool SegmentTransUtf8ToOther(const char* _desc, const std::string& _strin, std::string& _strout, const int& _segnum = 100) {const char* _src = "UTF-8";size_t _transcounter = 0;if (_strin.size() == 0) {//没有内容就返回_strout.clear();return true;}if (_segnum <= 0) {return false;}if (_strin.size() <= _segnum) {//字符串小于等于_segnumstd::cout << "第" << ++_transcounter << "段转换" <<",转换字节数"<< _strin.size() << std::endl;if (TransEncodeFormat(_desc, _src, _strin, _strout) == false) {return false;}}else {//字符串大于_segnumint leftpos = 0; //左边界位置int endpos = _strin.size() - 1; // 结束位置while (leftpos <= endpos) { int rightpos = 0;//右边界位置int remainingbytes = endpos - leftpos + 1; //左边界到结束剩余的字节数std::string outemp;if (remainingbytes <= _segnum) {//剩余字节数小于_segnumrightpos = endpos;std::string temp = _strin.substr(leftpos, remainingbytes); std::cout << "第" << ++_transcounter << "段转换" << ",转换字节数" << temp.size() << std::endl;if (TransEncodeFormat(_desc, _src, temp, outemp) == false) {return false;}_strout += outemp;} else {rightpos = leftpos + (_segnum - 1);const char lastbyte = _strin[rightpos];//通过要截取的最后一个字节 判断截取字符串是否完整if (((char)(lastbyte | 0x7f) == (char)0x7f) && ((char)(lastbyte & 0x00) == (char)0x00)) {//最后一个字节是 0XXX XXXXstd::string temp = _strin.substr(leftpos, rightpos - leftpos + 1);std::cout << "第" << ++_transcounter << "段转换" << ",转换字节数" << temp.size() << std::endl;if (TransEncodeFormat(_desc, _src, temp, outemp) == false) {return false;}_strout += outemp;} else if (((char)(lastbyte | 0xbf) == (char)0xbf) && ((char)(lastbyte & 0x80) == (char)0x80)) {//最后一个字节是 10XX XXXXwhile (1) {rightpos = rightpos + 1;if (rightpos > endpos) {//判断rightpos是否超出边界return false;}const char lastbytetemp = _strin[rightpos];if (((char)(lastbytetemp | 0xbf) == (char)0xbf) && ((char)(lastbytetemp & 0x80) == (char)0x80)) {//最后一个字节是 10XX XXXX}else {//最后一个字节不是 10XX XXXX 那么就少截取一个并跳出while循环rightpos = rightpos - 1;break;}}//whileif (rightpos < 0 || rightpos < leftpos) {//rightpos 上面进行了减法所以判断一下return false;}std::string temp = _strin.substr(leftpos, rightpos - leftpos + 1);std::cout << "第" << ++_transcounter << "段转换" << ",转换字节数" << temp.size() << std::endl;if (TransEncodeFormat(_desc, _src, temp, outemp) == false) {return false;}_strout += outemp;} else if (((char)(lastbyte | 0xdf) == (char)0xdf) && ((char)(lastbyte & 0xc0) == (char)0xc0)) {//最后一个字节是 110X XXXXrightpos = rightpos + 1;if (rightpos > endpos) {//判断rightpos是否超出边界return false;}std::string temp = _strin.substr(leftpos, rightpos - leftpos + 1);std::cout << "第" << ++_transcounter << "段转换" << ",转换字节数" << temp.size() << std::endl;if (TransEncodeFormat(_desc, _src, temp, outemp) == false) {return false;}_strout += outemp;} else if (((char)(lastbyte | 0xef) == (char)0xef) && ((char)(lastbyte & 0xe0) == (char)0xe0)) {//最后一个字节是 1110 XXXXrightpos = rightpos + 2;if (rightpos > endpos) {//判断rightpos是否超出边界return false;}std::string temp = _strin.substr(leftpos, rightpos - leftpos + 1);std::cout << "第" << ++_transcounter << "段转换" << ",转换字节数" << temp.size() << std::endl;if (TransEncodeFormat(_desc, _src, temp, outemp) == false) {return false;}_strout += outemp;} else if (((char)(lastbyte | 0xf7) == (char)0xf7) && ((char)(lastbyte & 0xf0) == (char)0xf0)) {//最后一个字节是 1111 0XXXrightpos = rightpos + 3;if (rightpos > endpos) {//判断rightpos是否超出边界return false;}std::string temp = _strin.substr(leftpos, rightpos - leftpos + 1);std::cout << "第" << ++_transcounter << "段转换" << ",转换字节数" << temp.size() << std::endl;if (TransEncodeFormat(_desc, _src, temp, outemp) == false) {return false;}_strout += outemp;}}leftpos = rightpos + 1;}}std::cout << __FUNCTION__ << " exec success" << std::endl;return true;}int main(int argc, char* argv[]){{std::string filecontent;std::string transcontent;std::string gbkfilepath = "./test-file/utf-8.txt";readfile(gbkfilepath, filecontent);std::cout << " ./test-file/utf-8.txt 内容字节数 = " << filecontent.size() << std::endl;bool res = SegmentTransUtf8ToOther("GBK", filecontent, transcontent, 1000);std::cout << " transcontent 内容字节数 = " << transcontent.size() << std::endl;std::cout << " transcontent GBK 内容[" << transcontent <<"]" << std::endl;std::cout << "====================================================" << std::endl;}{std::string filecontent;std::string transcontent;std::string gbkfilepath = "./test-file/utf-8.txt";readfile(gbkfilepath, filecontent);std::cout << " ./test-file/utf-8.txt 内容字节数 = " << filecontent.size() << std::endl;bool res = SegmentTransUtf8ToOther("GB18030", filecontent, transcontent, 1000);std::cout << " transcontent 内容字节数 = " << transcontent.size() << std::endl;std::cout << " transcontent GB18030 内容[" << transcontent << "]" << std::endl;std::cout << "====================================================" << std::endl;}{std::string filecontent;std::string transcontent;std::string gbkfilepath = "./test-file/utf-8.txt";readfile(gbkfilepath, filecontent);std::cout << " ./test-file/utf-8.txt 内容字节数 = " << filecontent.size() << std::endl;bool res = SegmentTransUtf8ToOther("GB2312", filecontent, transcontent, 1000);std::cout << " transcontent 内容字节数 = " << transcontent.size() << std::endl;std::cout << " transcontent GB2312 内容[" << transcontent << "]" << std::endl;std::cout << "====================================================" << std::endl;}return 0;}
相关文章:
[字符编码]windwos下使用libiconv转换编码格式(二)
在http://t.csdnimg.cn/PLUuz笔记中实现了常用编码格式转换的功能,但这还是一个demo。因为代码中向libiconv库函数传递的字符串是存放在堆空间中的(我也是从网上找例子测试,是否一定要开辟堆空间存放还有待考证),如果一次性转换的字节数很巨大的话,就会导致内存空间不足,进而引…...
textile 语法
1、文字修饰 修饰行内文字 字体样式textile 语法对应的 XHTML 语法实际显示效果加强*strong*<strong>strong</strong>strong强调_emphasis_<em>emphasis</em>emphasis加粗**bold**<b>bold</b>bold斜体__italics__<i>italics</i…...
【快速开发】使用SvelteKit
自我介绍 做一个简单介绍,酒架年近48 ,有20多年IT工作经历,目前在一家500强做企业架构.因为工作需要,另外也因为兴趣涉猎比较广,为了自己学习建立了三个博客,分别是【全球IT瞭望】,【…...
【docker笔记】docker常用命令
1、帮助启动类命令 1.1 启动、重启、查询当前状态、停止 systemctl start docker systemctl stop docker systemctl restart docker systemctl status docker1.2 设置开机启动 systemctl enable docker1.3 查看docker概要信息 docker info1.4 查看docker帮助文档 docker -…...
API 接口怎样设计才安全?
设计安全的API接口是确保应用程序和数据安全的重要方面之一。下面是一些设计安全的API接口的常见实践: 1. 身份验证和授权: 使用适当的身份验证机制,如OAuth、JWT或基本身份验证,以确保只有经过身份验证的用户可以访问API。实施…...
网站被CC攻击了怎么办?CC攻击有什么危害
网络爆炸性地发展,网络环境也日益复杂和开放,同时各种各样的恶意威胁和攻击日益增多,其中网站被CC也是常见的情况。 CC攻击有什么危害呢? 被CC会导致: 1.访问速度变慢:网站遭受CC攻击后,由于…...
Docker - 镜像 | 容器 日常开发常用指令 + 演示(一文通关)
目录 Docker 开发常用指令汇总 辅助命令 docker version docker info docker --help 镜像命令 查看镜像信息 下载镜像 搜索镜像 删除镜像 容器命令 查看运行中的容器 运行容器 停止、启动、重启、暂停、恢复容器 杀死容器 删除容器 查看容器日志 进入容器内部…...
要参加微软官方 Copilot 智能编程训练营了
GitHub Copilot 是由 GitHub、OpenAI 和 Microsoft 联合开发的生成式 AI 模型驱动的。 GitHub Copilot 分析用户正在编辑的文件及相关文件的上下文,并在编写代码时提供自动补全式的建议。 刚好下周要参加微软官方组织的 GitHub Copilot 工作坊-智能编程训练营&…...
Python入门学习篇(五)——列表字典
1 列表 1.1 定义 ①有序可重复的元素集合 ②可以存放不同类型的数据 ③个人理解:类似于java中的数组1.2 相关方法 1.2.1 获取列表长度 a 语法 len(列表名)b 示例代码 list2 [1, 2, "hello", 4] print(len(list2))c 运行结果 1.2.2 获取列表值 a 语法 列表名…...
React尝鲜
组件 React的组件就是一个js函数,函数内部return一个由jsx语法创建的html代码片段。 //MyComp.js export default function MyComp(){return (<h1>我是新组件MyComp</h1>) } 在需要引入组件的地方import导入组件,并放在相应位置 //App.js…...
锯齿云服务器租赁使用教程
首先登陆锯齿云账号 网盘上传数据集与代码 随后我们需要做的是将所需要的数据集与代码上传到网盘(也可以直接在租用服务器后将数据集与代码传到服务器的硬盘上,但这样做会消耗大量时间,造成资源浪费) 点击工作空间:…...
HarmonyOS和OpenHarmony的区别
1.概要 众所周知,鸿蒙是华为开发的一款分布式操作系统。因为开发系统,最重要的是集思广益,大家共同维护。为了在IOS和Android之间生存,鸿蒙的茁壮成长一定是需要开源,各方助力才能实现。 在这种思想上,…...
Redis Stream消息队列之基本语法与使用方式
前言 本文的主角是Redis Stream,它是Redis5.0版本新增加的数据结构,主要用于消息队列,提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证…...
制造行业定制软件解决方案——工业信息采集平台
摘要:针对目前企业在线检测数据信号种类繁多,缺乏统一监控人员和及时处置措施等问题。蓝鹏测控开发针对企业工业生产的在线数据的集中采集分析平台,通过该工业信息采集平台可将企业日常各种仪表设备能够得到数据进行集中分析处理存储…...
[python]用python实现对arxml文件的操作
目录 关键词平台说明一、背景二、方法2.1 库2.2 code 关键词 python、excel、DBC、openpyxl 平台说明 项目Valuepython版本3.6 一、背景 有时候需要批量处理arxml文件(ARXML 文件符合 AUTOSAR 4.0 标准),但是工作量太大,阔以考虑用python。 二、方…...
pdf 在线编辑
https://smallpdf.com/edit-pdf#rapp 参考 https://zh.wikihow.com/%E5%B0%86%E5%9B%BE%E5%83%8F%E6%8F%92%E5%85%A5PDF...
自然语言处理(NLP):理解语言,赋能未来
目录 前言1 什么是NLP2 NLP的用途3 发展历史4 NLP的基本任务4.1 词性标注(Part-of-Speech Tagging)4.2 命名实体识别(Named Entity Recognition)4.3 共指消解(Co-reference Resolution)4.4 依存关系分析&am…...
FastAPI使用loguru时,出现重复日志打印的解决方案
首先看图,发现每个日志都被打印了3条。其实这个和uvicorn日志打印的设计有关,在uvicorn中有多个logger,分别是uvicorn、uvicorn.error、uvicorn.access 而LOGGING默认有一个属性propagate,这个属性为True时,子日志记录…...
构建每个聚类的profile和deletion_mean特征
通过summarize_clusters函数构建每个聚类的protein[cluster_profile]和protein[cluster_deletion_mean]特征。目的是把extra_msa信息反映到msa中。 集成函数数据处理流程: sample_msa ->make_masked_msa -> nearest_neighbor_clusters -> summarize_clu…...
Milvus数据一致性介绍及选择方法
1、Milvus 时钟机制 Milvus 通过时间戳水印来保障读链路的一致性,如下图所示,在往消息队列插入数据时, Milvus 不光会为这些插入记录打上时间戳,还会不间断地插入同步时间戳,以图中同步时间戳 syncTs1 为例࿰…...
效率倍增:用快马平台一键生成极客日报推荐的高效开发工具与脚本
最近在极客日报上看到不少提升开发效率的小技巧,比如用Prettier统一代码风格、配置Git Hooks自动化检查等等。但每次看完想实践时,总得花时间查文档、写配置,挺麻烦的。于是我用InsCode(快马)平台做了个工具生成器,能直接把日报里…...
PrivLLM 协变混淆:隐私保护的 LLM 推理高效实现
用户接入云上大模型(LLM)时,通常面临端-云数据交互如提示词上传等隐私泄露风险。常规脱敏和加密手段难以同时保障数据安全隐私和推理高效准确,陷入“安全”与“智能”不可兼得的困局。为此,字节跳动安全研究团队提出了…...
PyTorch 2.8镜像环境配置:CUDA 12.4与cuDNN 8+版本兼容性验证指南
PyTorch 2.8镜像环境配置:CUDA 12.4与cuDNN 8版本兼容性验证指南 1. 镜像环境概述 PyTorch 2.8深度学习镜像是一个经过深度优化的通用计算环境,专为现代AI工作负载设计。这个镜像最显著的特点是完美适配了NVIDIA最新的CUDA 12.4和cuDNN 8版本ÿ…...
Gemma-3-12B-IT WebUI保姆级教程:多模型切换与Gemma-3-27B对比体验
Gemma-3-12B-IT WebUI保姆级教程:多模型切换与Gemma-3-27B对比体验 1. 开篇:为什么你需要一个更聪明的AI助手? 想象一下,你手头有一个能写代码、能解答技术难题、还能陪你聊天的AI助手。它运行在你自己的服务器上,数…...
Omni-Vision Sanctuary 模拟电路设计可视化:与 Multisim 仿真结果结合生成原理图效果图
Omni-Vision Sanctuary 模拟电路设计可视化:与 Multisim 仿真结果结合生成原理图效果图 1. 电子工程师的文档痛点 在电子设计领域,工程师们经常面临一个共同的烦恼:花大量时间完成的电路仿真和分析,最终呈现给团队或客户的文档却…...
FGA智能自动战斗全攻略:解放双手,高效玩转F/GO
FGA智能自动战斗全攻略:解放双手,高效玩转F/GO 【免费下载链接】FGA FGA - Fate/Grand Automata,一个为F/GO游戏设计的自动战斗应用程序,使用图像识别和自动化点击来辅助游戏,适合对游戏辅助开发和自动化脚本感兴趣的程…...
3步掌握Vortex:让250+游戏模组管理像专业开发者一样简单
3步掌握Vortex:让250游戏模组管理像专业开发者一样简单 【免费下载链接】Vortex Vortex: Nexus-Mods开发的游戏模组管理器,用于简化模组的安装和管理过程。 项目地址: https://gitcode.com/gh_mirrors/vor/Vortex 价值定位:重新定义游…...
从变砖到重生:红魔全系9008深度救砖指南与实战解析
1. 什么是9008模式?为什么能救砖? 当你发现红魔手机卡在开机界面、反复重启甚至完全黑屏时,大概率是遇到了传说中的"变砖"。这时候高通芯片隐藏的9008模式就是最后的救命稻草。简单来说,9008模式相当于电脑的BIOS界面&…...
Pinyin-pro 3.15.1版本避坑指南:老项目兼容性问题解决方案
Pinyin-pro 3.15.1版本避坑指南:老项目兼容性问题解决方案 在技术迭代飞快的今天,前端开发者常常面临一个尴尬局面:新发布的工具库在功能上令人惊艳,却因为底层依赖或语法特性与老项目环境不兼容而无法直接使用。Pinyin-pro作为中…...
Flask-base实战案例:从零构建功能完备的博客系统
Flask-base实战案例:从零构建功能完备的博客系统 【免费下载链接】flask-base A simple Flask boilerplate app with SQLAlchemy, Redis, User Authentication, and more. 项目地址: https://gitcode.com/gh_mirrors/fl/flask-base Flask-base是一个功能强大…...
