Unicode编码检查, 字符计算, Utf8与Utf16互转, GBK字符计算

CUnicodeUtils

#pragma once
#include <stdint.h>
#include <string>class CUnicodeUtils
{
public:// // @brief: 获取UTF16字符个数// @param: pData            数据(UTF16编码, 大端字节序或小端字节序, 可包含BOM)// @param: size             数据长度(字节)// @ret: int                若返回值 >= 0, 表示字符个数, 若返回值 < 0, 表示文本内容不是合法的 UTF16 编码字符串static int32_t GetUtf16Count(const void* pData, size_t size = -1);// // @brief: 获取UTF8字符个数// @param: pData            数据(UTF8编码数据, 可包含BOM)// @param: size             数据长度(字节)// @ret: int                若返回值 >= 0, 表示字符个数, 若返回值 < 0, 表示文本内容不是合法的 UTF8 编码字符串static int32_t GetUtf8Count(const void* pData, size_t size = -1);// // @brief: 获取GBK字符个数// @param: pData            数据(UTF8编码数据, 可包含BOM)// @param: size             数据长度(字节)// @ret: int                若返回值 >= 0, 表示字符个数, 若返回值 < 0, 表示文本内容不是合法的 UTF8 编码字符串static int32_t GetGbkCount(const void* pData, size_t size = -1);// // @brief: 转换为UTF16编码的字符串// @param: pData            数据(UTF8编码数据, 可包含BOM)// @param: size             数据长度(字节)// @ret: std::wstring       UTF16编码的字符串static std::wstring Utf8ToUtf16(const void* pData, size_t size = -1);// // @brief: 转换为UTF8编码的字符串// @param: pData            数据(UTF8编码数据, 可包含BOM)// @param: size             数据长度(字节)// @ret: std::string        UTF8编码的字符串static std::string Utf16ToUtf8(const void* pData, size_t size = -1);private:static void _CodePointToUtf8(uint32_t cp32, uint8_t* pBuf);static int32_t _Utf8ToUtf16(const void* pData, size_t size = -1, std::string* pUtf8 = nullptr, std::wstring* pUtf16 = nullptr);static int32_t _Utf16ToUtf8(const void* pData, size_t size = -1, std::string* pUtf8 = nullptr, std::wstring* pUtf16 = nullptr);static int32_t _GetGbkCount(const void* pData, size_t size = -1, std::string* pGbk = nullptr);
};

CUnicodeUtils.cpp

#include "CUnicodeUtils.h"// ANSI GBK 编码标准
// 第一字节(称为高字节)的范围: 0x81 - 0xFE
// 第二字节(称为低字节)的范围: 0x40 - 0xFE (不含0x7F)
// 
// 汉字区
// GBK/2:0XBOA1-F7FE 收录 GB 2312 汉字 6763 个,按原序排列
// GBK/3:0X8140-AOFE,收录 CJK 汉字 6080 个
// GBK/4:0XAA40-FEAO,收录 CJK 汉字和增补的汉字 8160 个
// 
// 图形符号区
// GBK/1:0XA1A1-A9FE,除 GB 2312 的符号外,还增补了其它符号
// GBK/5:0XA840-A9AO,扩除非汉字区
// 
// 用户自定义区
// GBK 区域中的空白区,用户可以自己定义字符// UTF-8 编码标准
// 
// 1字节 U+0000000 - U+0000007F 0xxxxxxx
// 2字节 U+0000080 - U+000007FF 110xxxxx 10xxxxxx
// 3字节 U+0000800 - U+0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
// 4字节 U+0010000 - U+001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// 5字节 U+0200000 - U+03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// 6字节 U+4000000 - U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx// UTF16 编码标准
// 
// 基本多语言平面(U+0000 - U+FFFF)
// U+000000 - U+00D7FF
// U+00D800 - U+00DFFF 保留区域
// U+00E000 - U+00FFFF 
// U+010000 - U+10FFFF 
// 
// 辅助平面(U+10000 - U+10FFFF)
// 1.码位减去 0x10000,得到20位的代理值(0x00 - 0xFFFFF)
// 2.高10位(范围0 - 0x3FF)加 0xD800 得到高位代理(0xD800 - 0xDBFF)
// 3.低10位(范围0 - 0x3FF)加 0xDC00 得到低位代理(0xDC00 - 0xDFFF)int32_t CUnicodeUtils::GetUtf16Count(const void* pData, size_t size/* = -1*/)
{return _Utf16ToUtf8(pData, size);
}int32_t CUnicodeUtils::GetUtf8Count(const void* pData, size_t size/* = -1*/)
{return _Utf8ToUtf16(pData, size);
}int32_t CUnicodeUtils::GetGbkCount(const void* pData, size_t size/* = -1*/)
{std::string strResult8;int32_t nLength = _GetGbkCount(pData, size, &strResult8);return nLength;
}std::wstring CUnicodeUtils::Utf8ToUtf16(const void* pData, size_t size/* = -1*/)
{std::string strResult8;std::wstring strResult16;int32_t nLength = _Utf8ToUtf16(pData, size, nullptr, &strResult16);return strResult16;
}std::string CUnicodeUtils::Utf16ToUtf8(const void* pData, size_t size/* = -1*/)
{std::string strResult8;std::wstring strResult16;int32_t nLength = _Utf16ToUtf8(pData, size, &strResult8, nullptr);return strResult8;
}void CUnicodeUtils::_CodePointToUtf8(uint32_t cp32, uint8_t* pBuf)
{// 1字节 0xxxxxxxif (cp32 >= 0x00000000 && cp32 <= 0x0000007F){pBuf[0] = (uint8_t)cp32;pBuf[1] = 0;}// 2字节 110xxxxx 10xxxxxxif (cp32 >= 0x00000080 && cp32 <= 0x000007FF){pBuf[0] = ((cp32 >>  6) & 0x1F) | 0xC0;pBuf[1] = ((cp32 & 0x3F)) | 0x80;pBuf[2] = 0;}// 3字节 1110xxxx 10xxxxxx 10xxxxxxif (cp32 >= 0x00000800 && cp32 <= 0x0000FFFF){pBuf[0] = ((cp32 >> 12) & 0x0F) | 0xE0;pBuf[1] = ((cp32 >>  6) & 0x3F) | 0x80;pBuf[2] = ((cp32 & 0x3F)) | 0x80;pBuf[3] = 0;}// 4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxxif (cp32 >= 0x00010000 && cp32 <= 0x001FFFFF){pBuf[0] = ((cp32 >> 18) & 0x07) | 0xF0;pBuf[1] = ((cp32 >> 12) & 0x3F) | 0x80;pBuf[2] = ((cp32 >>  6) & 0x3F) | 0x80;pBuf[3] = ((cp32 & 0x3F)) | 0x80;pBuf[4] = 0;}// 5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxxif (cp32 >= 0x00200000 && cp32 <= 0x03FFFFFF){pBuf[0] = ((cp32 >> 24) & 0x03) | 0xF8;pBuf[1] = ((cp32 >> 18) & 0x3F) | 0x80;pBuf[2] = ((cp32 >> 12) & 0x3F) | 0x80;pBuf[3] = ((cp32 >>  6) & 0x3F) | 0x80;pBuf[4] = ((cp32 & 0x3F)) | 0x80;pBuf[5] = 0;}// 6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxxif (cp32 >= 0x04000000 && cp32 <= 0x7FFFFFFF){pBuf[0] = ((cp32 >> 30) & 0x01) | 0xFC;pBuf[1] = ((cp32 >> 24) & 0x3F) | 0x80;pBuf[2] = ((cp32 >> 18) & 0x3F) | 0x80;pBuf[3] = ((cp32 >> 12) & 0x3F) | 0x80;pBuf[4] = ((cp32 >>  6) & 0x3F) | 0x80;pBuf[5] = ((cp32 & 0x3F)) | 0x80;pBuf[6] = 0;}
}int32_t CUnicodeUtils::_Utf8ToUtf16(const void* pData, size_t size/* = -1*/, std::string* pUtf8/* = nullptr*/, std::wstring* pUtf16/* = nullptr*/)
{const uint8_t* pCpData = (const uint8_t*)pData;std::wstring strOut16;  // 输出UTF16std::string strOut8;    // 输出UTF8uint32_t cp32 = 0;      // UNICODE码点int32_t nByteCount = 0;     // 字节计数int32_t nChCount = 0;       // 字符计数bool fResult = true;    // 操作结果bool fBom = true;       // BOM(Byte Order Mark)while ((0 != *pCpData) && (0 != size)){uint8_t ch = *pCpData;// 普通 Ascii 也是 UTF-8 一部分if (ch < 0x7F){cp32 = ch;nChCount++;}else{// 检查 UTF-8 首字节if (0 == nByteCount){cp32 = 0;if (ch >= 0xC0){uint8_t u8CodeMask  = 0xC0;     // 11000000uint8_t u8DataMask = 0x1F;      // 000xxxxxint nCount = 2;                 // 有效字节数量: 2-6// 检索字符使用的字节数量while(u8CodeMask <= 0xFC){uint8_t u8MaskMax = u8CodeMask | u8DataMask;if (ch >= u8CodeMask && ch <= u8MaskMax){cp32 = ch & u8DataMask;nByteCount = nCount;break;}u8CodeMask = (u8CodeMask >> 1) | 0x80;u8DataMask = u8DataMask >> 1;nCount++;}if (0 == nByteCount){fResult = false;break;}if (0xEF == ch && 3 == nByteCount){fBom = true;}nByteCount--;}else{fResult = false;break;}}else{// 非首字节掩码: 10xxxxxxif (0x80 != (ch & 0xC0)){fResult = false;break;}// BOM处理if (fBom){if (0xBB != ch && 2 == nByteCount){fBom = false;}if (0xBF != ch && 1 == nByteCount){fBom = false;}}cp32 = cp32 << 6;cp32 |= ch & 0x3F;nByteCount--;if (0 == nByteCount){// 跳过BOMif (fBom){fBom = false;pCpData++;continue;}nChCount++;}}}if (0 == nByteCount){uint8_t szBuf[7] = { 0 };if (pUtf8){_CodePointToUtf8(cp32, szBuf);strOut8 += (const char*)szBuf;}if (pUtf16){if (cp32 < 0x10000){strOut16.push_back((uint16_t)(cp32 & 0xFFFF));}else{uint16_t cp = (uint16_t)(cp32 - 0x10000);uint16_t cp32Hi = (uint16_t)(cp >> 10) + 0xD800;uint16_t cp32Lo = (uint16_t)(cp & 0x3FF) + 0xDC00;strOut16.push_back(cp32Hi);strOut16.push_back(cp32Lo);}}}pCpData++;if (-1 != size){size--;}}if (!fResult){return -1;}if (pUtf8){*pUtf8 = std::move(strOut8);}if (pUtf16){*pUtf16 = std::move(strOut16);}return nChCount;
}int32_t CUnicodeUtils::_Utf16ToUtf8(const void* pData, size_t size/* = -1*/, std::string* pUtf8/* = nullptr*/, std::wstring* pUtf16/* = nullptr*/)
{const uint16_t* pCpData = (const uint16_t*)pData;std::wstring strOut16;          // 输出UTF16std::string strOut8;            // 输出UTF8uint32_t cp32 = 0;              // 32位码点uint16_t cp32Hi = 0;            // 32位码点高10位uint16_t cp32Lo = 0;            // 32位码点低10位uint16_t cp16 = 0;              // 16位码点int32_t nByteCount = 0;         // 字节计数int32_t nChCount = 0;           // 字符计数bool fBigEndian = false;        // 是否大端字节序bool fLittleEndian = false;     // 是否小端字节序bool fResult = true;            // 操作结果if (-1 != size){if ((size < 2) || (0 != (size % 2))){return -1;}}while ((0 != *pCpData) && (0 != size)){cp16 = *pCpData;// BOM检查if (0xFFFE == cp16 || 0xFEFF == cp16){if (0 == nByteCount){if (0xFFFE == cp16) // 大端字节序 (Big Endian){fBigEndian = true;}if (0xFEFF == cp16) // 小端字节序 (Little Endian){fLittleEndian = true;}}else{fResult = false;break;}// 不可能同时存在两种字节序if (fBigEndian && fLittleEndian){fResult = false;break;}pCpData++;if (-1 != size){size -= 2;}continue;}if (fBigEndian){cp16 = ((cp16 >> 8) | (cp16 << 8));}//检查是否为基本多语言平面(U+0000 - U+FFFF)if (!(cp16 >= 0xD800 && cp16 <= 0xDFFF)){if (cp32Hi > 0) // 高位码点后必须跟着低位码点{fResult = false;break;}cp32 = cp16;nChCount++;}else{if (0 == nByteCount){//检查是否为辅助平面(U+10000 - U+10FFFF)if (cp16 >= 0xD800 && cp16 <= 0xDBFF)   //检查高位代理(0xD800 - 0xDBFF){cp32Hi = (cp16 - 0xD800);nByteCount = 1;}else{fResult = false;break;}}else{if (1 == nByteCount) // 高位码点后必须接着低位码点{if (cp16 >= 0xDC00 && cp16 <= 0xDFFF)   //检查低位代理(0xDC00 - 0xDFFF){cp32Lo = (cp16 - 0xDC00);cp32 = 0x10000 + ((uint32_t)cp32Hi << 10 | cp32Lo);cp32Lo = 0;cp32Hi = 0;}else{fResult = false;break;}}nByteCount--;if (0 == nByteCount){nChCount++;}}}// 转换为 UTF 编码if (0 == nByteCount){uint8_t szBuf[7] = { 0 };if (pUtf8){_CodePointToUtf8(cp32, szBuf);strOut8 += (const char*)szBuf;}if (pUtf16){if (cp32 < 0x10000){strOut16.push_back((uint16_t)(cp32 & 0xFFFF));}else{uint16_t cp = (uint16_t)(cp32 - 0x10000);uint16_t cpHi = (uint16_t)(cp >> 10) + 0xD800;uint16_t cpLo = (uint16_t)(cp & 0x3FF) + 0xDC00;strOut16.push_back(cpHi);strOut16.push_back(cpLo);}}}pCpData++;if (-1 != size){size -= 2;}}if (!fResult){return -1;}if (pUtf8){*pUtf8 = std::move(strOut8);}if (pUtf16){*pUtf16 = std::move(strOut16);}return nChCount;
}int32_t CUnicodeUtils::_GetGbkCount(const void* pData, size_t size/* = -1*/, std::string* pGbk/* = nullptr*/)
{const uint8_t* pCpData = (const uint8_t*)pData;std::string strOutGbk;      // 输出UTF8uint16_t gbkCode = 0;       // GBK编码int32_t nByteCount = 0;     // 字节计数int32_t nChCount = 0;       // 字符计数bool fResult = true;        // 操作结果while ((0 != *pCpData) && (0 != size)){uint8_t ch = *pCpData;if (ch < 0x7F){gbkCode = ch;nChCount++;}else{// 检查 UTF-8 首字节if (0 == nByteCount){gbkCode = 0;// 第1字节: 0x81 - 0xFEif (ch >= 0x81 && ch<=0xFE){gbkCode = ch;nByteCount = 1;}else{fResult = false;break;}}else{if (1 == nByteCount){// 第2字节: 0x40 - 0xFE (不包括0x7F)if (!(ch >= 0x40 && ch<=0xFE) || 0x7F == ch){fResult = false;break;}}gbkCode = gbkCode << 8;gbkCode |= ch;nByteCount--;if (0 == nByteCount){nChCount++;}}}if (0 == nByteCount){if (gbkCode <= 0x7F){strOutGbk.push_back((uint8_t)gbkCode);}else{strOutGbk.push_back(gbkCode >> 8);strOutGbk.push_back(gbkCode & 0xFF);}}pCpData++;if (-1 != size){size--;}}if (!fResult){return -1;}if (pGbk){*pGbk = std::move(strOutGbk);}return nChCount;
}

main.cpp

// CUnicodeUtils.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include "CUnicodeUtils.h"int main()
{char szUtf16Little[] = { 0x3C,0xD8,0x0D,0xDF,0x55,0x00,0x6E,0x00,0x69,0x00,0x63,0x00,0x6F,0x00,0x64,0x00,0x65,0x00,0x16,0x7F,0x01,0x78,0x4B,0x6D,0xD5,0x8B, 0x00,0x00 };char szUtf16Big[] = { 0xD8,0x3C,0xDF,0x0D,0x00,0x55,0x00,0x6E,0x00,0x69,0x00,0x63,0x00,0x6F,0x00,0x64,0x00,0x65,0x7F,0x16,0x78,0x01,0x6D,0x4B,0x8B,0xD5,0xD8,0x3C,0xDF,0x0D };char szUtf8[] = u8"🌍Unicode编码测试";int nUtf16Length = CUnicodeUtils::GetUtf16Count(szUtf16Little);nUtf16Length = CUnicodeUtils::GetUtf16Count(szUtf16Big);int nUtf8Length = CUnicodeUtils::GetUtf8Count(szUtf8);wchar_t* lpStr = (wchar_t*)szUtf16Little;std::string str8 = CUnicodeUtils::Utf16ToUtf8(szUtf16Little);std::wstring str16 = CUnicodeUtils::Utf8ToUtf16(szUtf8);int nGbkLength = CUnicodeUtils::GetGbkCount("789\xCC\x80");std::string str8Test;str8Test.push_back(0xEF);str8Test.push_back(0xBB);str8Test.push_back(0xBF);str8Test += str8;for (int i = 0; i < 10000; i++){str8 = CUnicodeUtils::Utf16ToUtf8(szUtf16Little);str16 = CUnicodeUtils::Utf8ToUtf16(szUtf8);}return 0;
}

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

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

相关文章

MySQL日期类型选择建议

我们平时开发中不可避免的就是要存储时间&#xff0c;比如我们要记录操作表中这条记录的时间、记录转账的交易时间、记录出发时间、用户下单时间等等。你会发现时间这个东西与我们开发的联系还是非常紧密的&#xff0c;用的好与不好会给我们的业务甚至功能带来很大的影响。所以…

对话型AI:Auto Possess Player Auto Possess AI

Auto Possess Player “Auto Possess Player” 是一个常见于游戏开发&#xff0c;尤其是在 Unreal Engine 中的术语。它指的是一个功能或设置&#xff0c;使得一个特定的角色或对象在游戏开始时自动接管玩家的控制权。以下是一些关键点&#xff1a; 含义 自动控制&#xff…

STM32外设之ADC应用--寄存器开发

1.ADC简介 模数转换器&#xff08;Analog-to-Digital Converter&#xff0c;简称ADC&#xff09;是一种重要的电子设备&#xff0c;它能够将模拟信号转换为数字信号。是一种将连续变化的模拟信号转换为离散的数字信号的电子设备。这种转换使得模拟信号可以在数字系统中进行处理…

A-23OH型树脂在汽车涂装行业溶剂回收中的应用

随着汽车制造业的不断发展&#xff0c;市场竞争愈发激烈。为了提升生产柔性、生产效率和成本效益&#xff0c;同时确保喷漆质量并满足日益增长的非标和定制化设计需求&#xff0c;汽车生产商需要寻求更加高效、环保的解决方案。 其中&#xff0c;水性涂料的应用已经成为一种趋势…

Maven 快速入门

Maven 快速入门 一、简介1、概述2、特点3、工作原理4、常用命令5、生命周期6、优缺点&#x1f388; 面试题 二、安装和配置1、安装2、环境配置3、命令测试是否安装成功4、功能配置5、idea配置本地 maven6、maven 工程依赖包查询网站 三、基于IDEA创建Maven工程1、maven 工程中的…

Spring 的依赖注入的最常见方式

在 Spring 中&#xff0c;依赖注入的方式有多种选择。下面我们来逐一分析它们的特点、适用场景和注意事项&#xff1a; 1. 构造函数注入 构造函数注入要求在对象创建时提供所有依赖。这种方式确保依赖在对象创建后不可变&#xff0c;特别适合必须强制存在的依赖。所有依赖在对…

常用代码整理

字符串操作相关函数的实现 gets puts strlen strcat strncat strcpy strncpy strcmp strncmp memcpy 内存大小端判断 类型强制转换 联合 排序 选择排序 冒泡排序 插入排序 快速排序 先选一个基准值&#xff0c;通过双指针扫描并交换元素将数组划分为两部分&#xff0c;左…

6.计算机网络_UDP

UDP的主要特点&#xff1a; 无连接&#xff0c;发送数据之前不需要建立连接。不保证可靠交付。面向报文。应用层给UDP报文后&#xff0c;UDP并不会抽象为一个一个的字节&#xff0c;而是整个报文一起发送。没有拥塞控制。网络拥堵时&#xff0c;发送端并不会降低发送速率。可以…

gitee建立/取消关联仓库

目录 一、常用指令总结 二、建立关联具体操作 三、取消关联具体操作 一、常用指令总结 首先要选中要关联的文件&#xff0c;右击&#xff0c;选择Git Bash Here。 git remote -v //查看自己的文件有几个关联的仓库git init //初始化文件夹为git可远程建立链接的文件夹…

transformer的基础知识

transformer的基础知识 transformer网络结构图 seq2seq 一般Seq2seq会分成两部分:Encoder、Decoder。 Encoder Transformer 中的 Encoder 就是用的 Self-attention。 encoder的内部结构 补充:block的内部结构主要由self-attention和全连接神经网络所构成。 在原来的论…

TSmaster CAN的E2E检验配置

文章目录 一. 自定义E2E校验算法1. 导入DBC文件2. 模拟报文发送3. 自定义E2E算法 问题&#xff1a;C代码编辑器中 数据库头文件为空问题&#xff1a;C代码编辑器中 程序启动和暂停按钮为灰色 一. 自定义E2E校验算法 1. 导入DBC文件 点击载入CAN数据库&#xff0c;在弹窗中选择…

添加卡巴斯基杀毒软件(KES)的更新源

最近不知道怎么了&#xff0c;家里的电脑卡巴斯基&#xff08;KES&#xff09;怎么更新都更新不了&#xff0c;在网上找到了几个卡巴斯基的服务器: 添加步骤&#xff1a; 1.双击右下角的卡巴斯基图标。 2.依次按如下图示添加&#xff1a; 以下这步是最关键的&#xff0c;一定要…

HDU Ignatius‘s puzzle

题目大意&#xff1a;f&#xff08;x&#xff09;5*x^1313*x^5k*a*x&#xff0c;输入一个无负整数 k&#xff08;k<10000&#xff09;&#xff0c;要找到最小的非负整数 a&#xff0c;将任意整数 x &#xff0c;65|f&#xff08;x&#xff09;&#xff0c;如果不存在该 a&am…

矩阵AB=0

矩阵AB0的性质 一、二的证明 这里还有一种说法 三、四的证明 详情请跳转五

linux环境下的程序设计与git操作

目录 前言&#xff1a; 进度条小程序&#xff1a; 先介绍几个背景知识 代码实现 Git操作 总结 其他指令 前言&#xff1a; 本文将重点介绍1. linux下的程序设计&#xff0c;并使用linux下的几个函数接口。实现一个简单的小程序 2.本着开源精神&#xff0c;进行git操作。…

数据同步工具Sqoop原理及场景优化

目录 0 数据同步策略 1 数据同步工具 ​编辑 2 Sqoop同步数据原理分析 2.1 原理分析 2.2 Sqoop基本使用分析 3 切片逻辑 3.1 MR切片逻辑 3.2 Hive CombineInputformat切片逻辑 3.3 实验1:Map任务并行度分析1 3.4 实验2: Map任务并行度分析2 3.5 实验3:Map任务并行…

SDIO - DWC MSHC 电压切换和频率切换

背景 我们的sdio访问sd card过去一直跑在低频上&#xff0c;HS50M。前段时间给eMMc添加了HS200模式&#xff0c;eMMc的总线模式定义是这样的&#xff1a; 可以看到1.8V的IO 电压可以支持所有模式&#xff0c;我们过去的芯片&#xff0c;由硬件部门放到evb上&#xff0c;其IO …

【学习笔记】什么是MongoDB

文章目录 MongoDB 简介体系结构数据模型MongoDB 的特点 MongoDB 简介 学习一个东西就跟认识一个人一样&#xff0c;下面有情MongoDB来做个自我介绍 大家好&#xff0c;俺是MongoDB&#xff0c;是一个开源、高性能、无模式的文档型数据库&#xff0c;当初的设计俺就是用于简化开…

Redis-03 持久化(RDB, AOF,混合持久化)及原理

1&#xff0c;持久化 Redis的持久化是必须的&#xff0c;当Redis服务宕机后&#xff0c;如果没有持久化&#xff0c;重启服务后redis中的数据都将丢失&#xff0c;所有的数据操作都将直连数据库&#xff0c;系统性能会大幅降低&#xff0c;所以在使用Redis做缓存服务时必须持久…

LabVIEW离心泵振动监控与诊断系统

利用LabVIEW结合数据采集与处理技术&#xff0c;构建了一套高效、低成本的振动监测与诊断系统&#xff0c;有效提升了测试精度与设备可靠性。 项目背景 在化工生产中&#xff0c;离心泵作为关键设备&#xff0c;其稳定运行对保障生产安全与效率至关重要。由于传统振动测试系统…