松江网站建设,上海废弃物备案网站,暴走漫画网站建设目的,网站设计作品如何在 Qt 中使用 uchardet 库 文章目录 如何在 Qt 中使用 uchardet 库一、简介二、uchardet库的下载三、在Qt中直接调用四、编译成库文件后调用4.1 编译工具下载4.2 uchardet源码编译4.3 测试编译文件4.4 Qt中使用 五、一些小问题5.1 测试文件存在的问题5.2 uchardet库相关 六…如何在 Qt 中使用 uchardet 库 文章目录 如何在 Qt 中使用 uchardet 库一、简介二、uchardet库的下载三、在Qt中直接调用四、编译成库文件后调用4.1 编译工具下载4.2 uchardet源码编译4.3 测试编译文件4.4 Qt中使用 五、一些小问题5.1 测试文件存在的问题5.2 uchardet库相关 六、写在最后 一、简介
相信对编程熟悉的朋友有时候都会碰到这样一个问题——乱码。
大家应该都知道这是由于文件编码格式不正确导致的相关问题即在文件编写和阅读的时候采取的编码格式不同于是造成了我们阅读上的困难。
对于众多编译器都有转文件编码与识别文件编码的相关功能因此我们经常看到他们的身影。 如上图所示分别为 windows记事本、Notepad、VsCode 所提供的文件编码格式识别。
而在网上搜索到的绝大多数方式是使用 python 中的 chardet 模块进行文件编码格式的判断。其实该库就是我们本次使用的 uchardet 库其只是被开发者适配成了 python 版本。由于有关该库的 C 使用示例太少所以就有了这篇文章希望能给各位大佬提供思路
那么我在这里简单介绍一下 uchardet 库。 uchardetUniversal Charset Detector是一个强大的开源项目它可以帮助我们自动识别文本的字符集编码。 uchardet 基于 Mozilla 的 CharDet 算法该算法经过大量实际数据训练具有高度的准确性。其核心功能是通过分析字节序列的统计特性判断出最可能的字符编码类型支持如 UTF-8、GBK、ISO-8859-1 等多种常见的字符集。 项目采用 C 编写易于跨平台集成并且拥有简洁的 API 接口使得开发者可以轻松地将 uchardet 整合到他们的应用中。此外项目还提供了 Python 绑定方便 Python 开发者使用。 项目地址下载方式后续过程中我会进行阐述因此不用着急下载 BYVoid/uchardet: An encoding detector library ported from Mozilla (github.com) uchardet / uchardet · GitLab 项目网站主页 uchardet (www.freedesktop.org) 以上信息来源为以下文章感谢作者分享 探索高效字符检测深入理解uchardet-CSDN博客 由此我们对 uchardet 有了初步的认识那么如何将其应用到项目工程中是本文的重点。这里我将使用 Qt 对该库进行操作同理使用 C 亦可实现。
在项目开始之前简单介绍一下我所使用的配置环境 开发平台 Window 10Qt 5.12.3 编译环境 MinGW 64-bit
二、uchardet库的下载
由于网上资料实在是太少所以说下载也是一件难事不过本文推荐以下下载方式 Index of /software/uchardet/releases (www.freedesktop.org) 如无法点击跳转可自行复制网址https://www.freedesktop.org/software/uchardet/releases/ 打开以后得到如下页面 截至本文章撰写时间 2024/6/27其版本更新到 0.0.8 而我们需要下载的是 uchardet-0.0.8.tar.xz这是稳定的发行版可以正常使用。这里对新手朋友说一句不要直接从 Github 上下载而要去里面的 Release 下载否则你下载的文件大概率无法运行。因为没有 Release 的项目大概率正在开发其中不免存在或多或少的问题盲目尝试不会让我们事半功倍
回归正题对上述下载的文件解压以后得到如下图所示的文件结构。 那么到这里该库的源码下载完成后续我们将对其进行使用。
三、在Qt中直接调用
这种方法可以实现功能但不推荐。因为直接使用其源码文件导入到 Qt 中会增加很多文件对我们的阅读体验不是很好但这里也做介绍感兴趣的朋友可以阅读。 新建 Qt 项目将 uchardet 源码中的 src 文件夹复制到 Qt 项目文件中 然后在 Qt 中按照如下步骤添加库文件 如图所示在项目文件夹上 右键点击 Add Existing Directory。 如图所示对 uchardet.cpp 文件取消勾选。 对项目中已有的文件取消勾选然后点击 OK此时我的项目结构为 我在 UI 文件中创建了一个按钮用来测试该库是否可行如下所示 对按钮使用转到槽实现其 released 槽函数。 在 widget.h 文件中进行如下更改 #ifndef WIDGET_H
#define WIDGET_H#include QWidget#include QFileDialog
#include QDebug/* 增加 uchardet 库头文件 */
#include src/uchardet.hnamespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent nullptr);~Widget();private slots:void on_pushButton_released();private:Ui::Widget *ui;
};#endif // WIDGET_H 对 widget.cpp 文件中对按钮的槽函数进行实现 /*! * File : widget.cpp* Brief : 按钮槽函数* Details : 详细说明* Param : 参数* Return : 返回值* Author : Liu Jiahao* Date : 2024-06-27 16:42:05* Version : v1.1* Copyright : Copyright By Liu Jiahao, All Rights Reserved* */
void Widget::on_pushButton_released()
{QString filePath QFileDialog::getOpenFileName(nullptr, 选择文件, ../, 所有文件 (*.*));if (filePath.isEmpty()) {return;}QFile file(filePath);// 文件打开成功if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {QByteArray buff file.readAll();uchardet_t ud uchardet_new();uchardet_handle_data(ud, buff.constData(), buff.size());uchardet_data_end(ud);const char* encoding uchardet_get_charset(ud);QString result QString::fromLatin1(encoding);uchardet_delete(ud);qDebug() 该文件的编码格式为 result;}file.close();
}
由此完成了对该库的调用这种方法较为简单缺点就是会导入大量的源代码。
当我们运行程序点击按钮打开一个文件后将会打印出该文件的编码格式其运行结果如下图所示 这里我做了一个简单的动图用于演示实现效果如下所示
四、编译成库文件后调用
在 Qt 中最常用的一般都是将所需库编译后调用而 uchardet 也是可以进行这样的操作的只不过实现起来有一点繁琐需要我们自己进行编译。
4.1 编译工具下载
我们编译需要使用 MinGW-w64 进行编译因此需要对该文件进行下载。 Releases · niXman/mingw-builds-binaries (github.com) 如无法点击跳转可自行复制网址https://github.com/niXman/mingw-builds-binaries/releases 截至本文章撰写时间 2024/6/27其版本更新到 13.2.0 我们可以看到下图所示的内容 各个版本有何区别感兴趣的朋友可以自行搜索这里将不再赘述本文着重讲解如何使用 uchardet望谅解
这里我电脑是 64 位的故我下载 x86_64-13.2.0-release-win32-seh-ucrt-rt_v11-rev0.7z下载后解压得到以下文件信息 任意一个盘都可以我这里直接解压在了 C 盘大家不要学我 尽量解压到一个自己好找的地方后续需要使用这个地址 然后打开 设置-系统-系统信息-高级系统设置-环境变量按照图中所示步骤进行点击 我这里电脑没有装中文但界面几乎一致。 我之前将其解压到 C:/mingw64/ 目录下因此这里我需要向环境变量中加入其 bin 文件如下所示 此时我们打开控制台快捷键 win R 后输入 cmd 最后回车在其中输入 gcc -v 得到以下信息 即证明安装完成但还有一步需要操作。
打开 MinGW-w64 的安装目录进入其 bin 文件找到 mingw32-make.exe 文件将其复制一份重命名为 make.exe如下所示 这样做是为了我们后续使用命令时能够方便的使用 make 命令而不是 mingw32-make 此时再次使用控制台输入 make -v 或者 mingw32-make -v 都能输出以下内容 至此结束安装编译工具的工作。接下来需要编译 uchardet 源码。
4.2 uchardet源码编译
同样打开控制台这里我们需要提前将源码文件复制一份这样方便我们出错后有回转的余地而不是每次都要重新下载源码。我这里将复制的源码文件夹命名为 uchardet-copy然后输入命令行去到复制源码的文件夹命令如下
cd 复制后源码文件夹的路径运行结果如图所示 此后依次输入以下命令
mkdir build
cd build
cmake .. -G MinGW Makefiles
make不出意外的话将会在 uchardet-copy/build/ 目录中生成类似的文件结构
4.3 测试编译文件
后续一切操作都是基于我复制源码的文件夹即 uchardet-copy 文件夹下的 首先需要我们进入 uchardet-copy/build/src 目录下找到 libuchardet.dll 文件将其复制到 uchardet-copy/build/test 中 打开控制台进入 uchardet-copy/build/test 目录中同样使用 cd 命令 cd 写入自己文件路径然后在 uchardet-copy/build/test 目录中新建一个文件我这里新建的 a.txt 文件默认采用的是 UTF-8 编码格式此时命令窗口中输入你想检测的文件我使用以下命令行 uchardet-tests.exe a.txt得到以下内容 可以看到其编码格式为 UTF-8检测结果正确
由此可以看到我们编译结果成功其他编码格式相关的测试大家可以自行验证这里不再赘述
4.4 Qt中使用
通过上一步编译后我们已经得到了相关的 .a 和 .dll 文件其路径位于我上述所讲的 uchardet-copy/build/src 文件夹将 .a 以及 .dll 复制到我们新建的 Qt 项目文件中。
这里需要注意的是由于我电脑是64位的我下载的 MinGW 也是64位版本因此编译出的 dll 文件也是用于64位操作系统的。所以建立 Qt 项目时注意所需 Qt 编译环境应当是 MinGw 64-bit
除此之外还需要添加 .h 文件其路径位于 uchardet-copy/src 文件夹内同样需要将其复制到我们自己的 Qt 项目文件夹中我这里新建了文件夹 uchardet 并将相关文件复制在该文件中如下所示 然后我们需要在工程文件中导入该动态库具体操作不予细说这里只介绍重要部分。 导入动态库 具体在 .pro 文件中添加的东西为 win32: LIBS -L$$PWD/uchardet/ -luchardetINCLUDEPATH $$PWD/uchardet
DEPENDPATH $$PWD/uchardet与本文第三小节类似在 UI 文件中添加一个按钮 具体代码也与第三小节类似这里简单赘述 在 widget.h 中有以下代码 #ifndef WIDGET_H
#define WIDGET_H#include QWidget#include QDebug
#include QFileDialog#include uchardet/uchardet.hnamespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent nullptr);~Widget();private slots:void on_pushButton_released();private:Ui::Widget *ui;
};#endif // WIDGET_H 在 widget.c 文件中实现其槽函数 /*!* File : widget.cpp* Brief : 打开文件槽函数* Details : 详细说明* Param : 参数* Return : 返回值* Author : Liu Jiahao* Date : 2024-06-28 14:43:15* Version : v1.1* Copyright : Copyright By Liu Jiahao, All Rights Reserved**/
void Widget::on_pushButton_released()
{QString filePath QFileDialog::getOpenFileName(nullptr, 选择文件, ../, 所有文件 (*.*));if (filePath.isEmpty()) {return;}QFile file(filePath);// 文件打开成功if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {QByteArray buff file.readAll();uchardet_t ud uchardet_new();uchardet_handle_data(ud, buff.constData(), buff.size());uchardet_data_end(ud);const char* encoding uchardet_get_charset(ud);QString result QString::fromLatin1(encoding);uchardet_delete(ud);qDebug() 该文件的编码格式为 result;}file.close();
}其运行结果也与第三小节类似只是采用了不同的调库方式这里就不再进行赘述。 值得注意的是该库并不能确保百分百检测出的文件类型正确同时文件中如果没有文本信息也是无法检测出来的。
五、一些小问题
在对该库的使用过程也发现一些或多或少的小问题在这一小节将进行阐述。
5.1 测试文件存在的问题
细心的朋友可能会注意到在 uchardet/test 中有很多文件夹如下所示 其中均为不同语言的不同编码格式文件例如 en 为英语其中包含文件 ascii.txt也就意味着该文件编码格式为 ascii但是我们将此文件复制到 uchardet-copy/build/test 中进行测试的时候发现其并不能输出任何东西如下所示 通过对 uchardet-copy/test 中 uchardet-tests.c 文件的阅读其中包含以下代码
/* In a unit test, 0 means success, other returned values mean failure. */
success (strcmp(charset, expected_charset) ! 0);
if (success) {fprintf(stderr, success: %d, Got %s, expected %s\n, success, charset, expected_charset);
}通过对这代码的分析可以知道charset 为检测出的文件编码格式类型而 expected_charset 为期望的文件编码格式类型。再往上看有以下代码
expected_charset strrchr(filename, /);
if (expected_charset NULL)
{expected_charset filename;
}
else
{expected_charset;
}
expected_charset strtok(expected_charset, .);我们通过阅读这段代码可以知道其进行的操作是把你输入的文件名去后缀并保存起来使其成为 expected_charset 变量。
那么上述问题迎刃而解例如我们输入的文件名是 ascii.txt经过其检测后得出其编码格式为 ascii那么对于 success (strcmp(charset, expected_charset) ! 0); 这一句代码而言得到的结果 success 必定为 0故没有输出。
可以看的出来作者这样做的目的是当文件编码格式和文件名相同时判定为真则不进行输出。当文件编码格式和文件名不相同时判定为假输出错误信息。
其实这对我们开发而言并没有多大关系也不影响我们使用这个库进行编码识别的操作只是我在开发过程中遇到这个问题的一些感想。希望能对本文读者有所帮助
5.2 uchardet库相关
由于编码格式众多且繁杂且该库长时间没有进行更新难免会有一些小问题导致识别文件编码格式不准确。但这都是在我们可以承受的范围之内。
另外肯定有人好奇我怎么知道这个库为什么这么用。实际上我在网上找了大量资料对于该库的描述实在是太少偶然间看到一位大佬写的文章C 自动检测编码_uchardet c±CSDN博客
顿时恍然大悟于是我也去查看了 Notepad 的源码文件 并且notepad 为了解决该库无法识别出 UTF-8 BOM、UTF-16BE BOM、UTF-16LE BOM 的问题专门对这几个类型进行了单独的判断 那么综合来讲该库的性能以及使用体验还是不错的大家感兴趣可以自行尝试。
六、写在最后
本文介绍了 如何在Qt中使用uchardet库同时该库也可适用于C。以及使用过程中存在的一些小问题。
本文中的代码后续会逐步开源欢迎关注敬请期待
欢迎广大读者提出问题以及修改意见本人看到后会给予回应欢迎留言后续会逐步进行开源 另外由于文章是作者手打的文字有些地方可能文字会出错望谅解也可私信联系我我对其进行更改。 个人CSDN账号刘梓谦_-CSDN博客 Gitee刘佳豪 (liu-jiahaohappy) - Gitee.com GitHubJiahao-Liu29 (github.com)