[QT_024]Qt学习之QByteArray详解

2023-11-15

 本文转自:《Qt编程指南》        作者:奇先生

Qt编程指南,Qt新手教程,Qt Programming Guide

本节学习 QByteArray 的两种用法,第一种作为字符串处理类,类似 QString ,但 QByteArray 内部字符编码不确定,所以要慎用。第二种是作为纯的字节数组,里面可以包含多个 '\0' ,经常用于网络数据的接收和发送。

3.4.1 QByteArray和char


Qt 最常用的字符串类是内码固定的 QString,而针对传统类似 C 语言 char* 的字符串,Qt 提供了 QByteArray 类来处理。QString 的字符单元是 QChar,QByteArray 的字节单元是 char。头文件 <QByteArray> 不仅自身以类的形式提供,它还针对传统 C 语言的字符串函数做了安全版本的封装,都加了 q 字母前缀,如 qstrlen、qstrncmp、qstrcpy,这些是全局函数,专门处理传统 C 语言的 char* 字符串,用法与 C 语言风格完全类似,比较简单,本节就不介绍了。本节主要介绍 QByteArray 类的使用。

QByteArray 类可以处理以 '\0' 结尾的传统字符串,包括 UTF-8 编码和其他如 GBK、Big5 等多字节编码的字符串,在作为字符串使用时,QByteArray 内部字符编码格式是不限定的,可以是任意编码的,所以程序员自己必须要事先确定程序会用到哪些编码的 QByteArray 。因为 Qt5 源文件规定是 UTF-8 编码的,所以 QByteArray 内部使用 UTF-8 编码的字符串居多。QByteArray 在赋值、传参数、返回值时也是使用隐式共享机制提高运行效率,只有字符串发生修改时才会执行深拷贝。

在文件处理、网络数据收发等场景,QByteArray 类是作为纯字节数组来使用的,里面可以包含任意数据,比如一堆 '\0',这时不要拿它当字符串看,它的存储长度与 qstrlen 计算的长度经常不一致。对于网络数据收发,QByteArray 经常配合 QDataStream 使用,对 Qt 数据类型做串行化(Serializing)。
 

3.4.2 QByteArray作为字符串使用


QByteArray 类作为字符串使用时,它会自动在字符串末尾添加 '\0' ,末尾的 '\0' 不计入字符串长度。QByteArray 字符串的内部编码是不固定的,比如前面 QString 的 toLocal8Bit 和 toUtf8 函数返回的对象全是 QByteArray 类型。QByteArray 字符串的数据来源可能有:

  • ①源代码里的字符串,这时 QByteArray 内码与源文件的编码有关,UTF-8 编码源文件生成的很可能就是 UTF-8 编码的字符串。
  • ②本地文本文件,从文件读取的字符串与该文件使用的字符编码有关,Linux 上常用 UTF-8,而 Windows 经常使用 ANSI 多字节编码,简体 Windows 系统一般是 GBK,而繁体默认是 Big5。
  • ③网页数据,网页本身也是文本文件,有它自己的文本编码格式,这时网页文件编码格式决定 QByteArray 字符串的编码格式。

我们这里示范的是第一种,全部用 UTF-8 编码的 QByteArray 字符串。QByteArray 类关于字符串处理的成员函数基本和 QString 类的一样,函数名和参数都是类似的。但注意因为 QByteArray 内码不确定,它没有 arg 函数,也没有字符编码转换的函数。QByteArray 关于字符串处理的函数就不枚举了,和上一节 QString 的差不多,下面直接看示例代码:

void TestStr() //内码 UTF-8

{
    //数值与字符串转换
    int nDec = 800;
    QByteArray basDec;
    basDec.setNum(nDec);    //数值转字符串
    qDebug()<<basDec;
    QByteArray basReal = "125.78999";
    double dblReal = basReal.toDouble();    //字符串转数值
    qDebug()<<fixed<<dblReal;

    //运算符
    QByteArray basABCD = "ABCD";
    QByteArray basXYZ = "XYZ";
    qDebug()<<(basABCD < basXYZ);   //二者字符编码一致才能比较!
    qDebug()<<(basABCD == basXYZ);
    qDebug()<<(basABCD >= basXYZ);
    qDebug()<<(basABCD + basXYZ);

    //子串处理
    QByteArray basHanzi = "1234打印汉字";
    //作为字符串时 QByteArray::length() 和 qstrlen() 一致
    qDebug()<<basHanzi.length()<<"\t"<<qstrlen( basHanzi.data() );
    //重复
    QByteArray basMoreHanzi = basHanzi.repeated(2);
    qDebug()<<basMoreHanzi.count("1234"); //统计次数
    qDebug()<<basMoreHanzi.startsWith("1234");  //开头判断
    qDebug()<<basMoreHanzi.endsWith("汉字");     //结尾判断
    qDebug()<<basMoreHanzi.indexOf("1234");   //从左边查出现位置
    qDebug()<<basMoreHanzi.lastIndexOf("1234"); //从右边查出现位置
    //替换
    basMoreHanzi.replace("1234", "一二三四");
    qDebug()<<basMoreHanzi;

    //切割字符串
    QByteArray basComplexFile = "   /home/user/somefile.txt  \t\t ";
    QByteArray basFileName = basComplexFile.trimmed();  //剔除两端空白
    qDebug()<<basFileName;
    //分隔得到新的 QByteArray 对象列表
    QList<QByteArray> baList = basFileName.split('/');
    //打印
    for(int i=0; i<baList.length(); i++)
    {
        qDebug()<<i<<"\t"<<baList[i];
    }
    //没有段落函数
}


上面测试函数第一段是数值与字符串互相转换的,比较简单,打印结果是:

"800"

125.789990


浮点数转换时,定点计数法和科学计数法都是可以接受的,上面示范的是定点数。这些函数声明和功能都可以查阅 QByteArray 类的帮助文档。

第二段代码是运算符函数的,需要注意的是一定要在确定字符串内部字符编码的情况下,才能进行比较和拼接,上面用的全是 UTF-8 。不能将不同编码格式的字符串比较,因为得到的结果没意义,反而会造成误导。上面比较运算符的打印结果为:

true

false

false

"ABCDXYZ"


第三段是子串查询处理的,注意只有当 QByteArray 作为字符串处理时,它的 length() 函数计算的长度才会和全局函数 qstrlen() 计算的结果一致。子串部分打印的结果为:

16     16

2

true

true

0

16

"一二三四打印汉字一二三四打印汉字"


上面示范的 basMoreHanzi.replace("1234", "一二三四") ,这种形式的替换函数会对所有匹配的子串进行替换,它的声明是:

QByteArray &    replace(const char * before, const char * after)

如果要对指定位置的子串替换,需要换一个声明形式的 replace 函数,比如:

QByteArray &    replace(int pos, int len, const char * after)这个函数会对指定位置 pos 开始的长度为 len 的子串进行替换,这个函数声明只做一次替换。
对于 replace 函数,必须注意字符编码的问题,UTF-8 的英文字符占用 1 字节,汉字通常是 3 字节,这种不确定性在替换函数和其他分隔子串函数时尤其需要注意,因为 3 字节的汉字如果被截断,就成错误的字符,造成信息损失。因此尽量不要用 QByteArray 类来处理字符串,尤其是涉及分割和替换的。QString 类的字符长度是固定的,所以最适合做字符串处理。

最后一段代码是子串分隔的,trimmed 函数功能也是去除两端的空白区域,split 函数将字符串分隔为多个子串之后按照 QList<QByteArray> 类型返回,QList 是一个模板类,QList<QByteArray> 就是存储多个 QByteArray 对象的列表,可以直接用中括号 [] 访问里面的各个对象。最后一段代码打印的结果如下:

"/home/user/somefile.txt"

0     ""

1     "home"

2     "user"

3     "somefile.txt"


分隔结果与上一节 QString 是一样的,对于开头 '/' 左边没有字符的情况,一样会分出来一个空字符串对象。因为一般用 QString 来处理文本字符串,QByteArray 类没有 section 函数,所以字符串处理时优先用 QString 类。
 

3.4.3 QByteArray作为字节数组使用


在读写文件、网络数据收发过程中经常将 QByteArray 作为缓冲区存储字节数据,这时候 QByteArray 就是纯的字节数组,里面可以包含任意个 '\0' 字节。下面以网络数据传输为例讲解,比如网络传输过程中既要传输数值类型 int、double,又要传输字符串类型 char*,对于普通的 C++ ,最常用的是自定义一个结构体:

struct NetData

{
    int nVersion;
    double dblValue;
    char strName[256];
};

发数据时就将数值赋值给结构体对象的成员变量,字符串就用 strcpy 函数塞进去。这种方式可行,但缺乏灵活性,下次如果要传个不同的数据组合,就得重新定义。
Qt 对这类组合数据的打包方法就叫串行化(Serializing),在 Qt 帮助文档的索引里输入关键词 Serializing 就可以看到关于 Qt 串行化的帮助主题(Serializing Qt Data Types),除了 C++ 基本数值类型,Qt 还对大量自身的类对象做了串行化。串行化得到一个字节数组 QByteArray ,可以直接用于发送。Qt 串行化数据接收就是发送的逆过程,都是通过 QDataStream 流实现。下面简单示范一对函数,首先是串行化输出:

QByteArray TestSerialOut()

{
    //数据
    int nVersion = 1;
    double dblValue = 125.78999;
    QString strName = QObject::tr("This an example.");
    //字节数组保存结果
    QByteArray baResult;
    //串行化的流
    QDataStream dsOut(&baResult, QIODevice::ReadWrite);  //做输出,构造函数用指针
    //设置Qt串行化版本
    dsOut.setVersion(QDataStream::Qt_5_0);//使用Qt 5.0 版本流
    //串行化输出
    dsOut<<nVersion<<dblValue<<strName;

    //显示长度
    qDebug()<<baResult.length()<<"\t"<<qstrlen(baResult.data());
    //返回对象
    return baResult;
}

该函数里给定了三个数据:整数、浮点数和字符串对象,通过流 dsOut 将三个数据打包存到字节数组 baResult 里。对于串行化输出,QDataStream 的构造函数是以字节数组的指针和读写模式 QIODevice::ReadWrite 为参数,其构造函数声明为:

QDataStream(QByteArray * a, QIODevice::OpenMode mode)

然后设置串行化流的版本兼容,上面代码使用的是 Qt 5.0 版本的流格式;流格式设置好之后,就可以用 << 将数据输出到流里面,QDataStream 类的函数会将数据打包好存到字节数组里面,最后返回这个字节数组对象就行了。
以字节数组方式使用的 QByteArray 对象,它的长度是不能用 qstrlen 之类的函数计算的,上面函数打印的结果如下:

48     0


字节数组实际占用 48 字节空间,而 qstrlen 函数计算的是 0,因为该字节数组第一个字节就是 '\0' 。
该函数返回的 baResult 就包含了三个要发送的数据,baResult 里面具体的数据格式不需要关心,收发两端 setVersion 的版本号一致就可以了。使用串行化就不再需要自定义结构体,所以用起来很方便。
网络收发过程到后面网络专题的学习再讲,现在仅学习一下串行化输出和输入的函数,baResult 数据的解析函数如下:

void TestSerialIn(const QByteArray& baIn)

{
    //输入流
    QDataStream dsIn(baIn); //只读的流,构造函数用常量引用
    //设置Qt串行化版本
    dsIn.setVersion(QDataStream::Qt_5_0);//使用Qt 5.0 版本流
    //变量
    int nVersion;
    double dblValue;
    QString strName;
    //串行化输入
    dsIn>>nVersion>>dblValue>>strName;

    //打印
    qDebug()<<nVersion;
    qDebug()<<fixed<<dblValue;
    qDebug()<<strName;
}

对于输入流的构造,参数是常量引用,其声明如下:

QDataStream(const QByteArray & a)


这个声明是针对只读的输入流。输入流定义好之后,同样是设置流的版本号,要与输出端的一致。然后使用 >> 从输入流提取数据即可。上面函数打印的结 果如下:

1

125.789990

"This an example."


可见与输出函数里的完全一样。对于 Qt 程序的网络通信,都可以类似上面方法对数据进行打包和解析,是比较方便的。

QByteArray 有针对数据处理的一些函数,比如基 64 转换和压缩解压函数:fromBase64、toBase64、qCompress、qUncompress 等,这些函数可以到使用的时候再查帮助文档。
 

3.4.4 QByteArray和QString合理的使用方式


因为 QByteArray 既可以用作字符串,又可以用作字符数组,它的使用方式比较多。而且作为字符串时,它内部的字符编码格式又是不固定的,所以 QByteArray 有诸多的不确定性。Qt 帮助文档里面明确说了,如果要做字符串方面的处理,都应当使用 QString ,除非是嵌入式系统里面内存有限,不得不用 QByteArray 的情况。对于本地化编码的字符串,可以用 QString::fromLocal8Bit 函数将字符串源转为 QString 对象;对于 UTF-8 编码的字符串,可以用 QString::fromUtf8 函数实现转换。如果要反过来转换,就 用对应的 to*** 函数。通常情况下有这些函数就够用了。

对于文件读写和网络数据收发,这些一般都是用 QByteArray 对象作为输入输出缓冲区,并且可以利用 QDataStream 做串行化,将多个数据打包成 QByteArray 。通常情况下,对于纯字节数据的处理使用 QByteArray 。

在有些情况下,需要 QString 和 QByteArray 对多种编码格式字符串进行转换,需要二者协作,下面给个协作的示例:

void TestCooperation()

{
    //源字符串
    QString strSrc = QObject::tr("1234abcd 千秋萬載 壹統江湖");
    //转为 UTF-8
    qDebug()<<strSrc.toUtf8();

    //明确地转为 GB18030
    QTextCodec *codecGB = QTextCodec::codecForName("GB18030");
    QByteArray strGB = codecGB->fromUnicode(strSrc); //转为GB18030
    qDebug()<<strGB;
    qDebug()<<codecGB->toUnicode(strGB);  //转回QString

    //明确地转为 Big5
    QTextCodec *codecBig5 = QTextCodec::codecForName("Big5");
    QByteArray strBig5 = codecBig5->fromUnicode(strSrc); //转为Big5
    qDebug()<<strBig5;
    qDebug()<<codecBig5->toUnicode(strBig5);    //转回QString
}

除了 QString 自带的 to*** 等函数实现不同字符编码的转换,更为专业的是 QTextCodec 类,专门用于不同文本编码格式的转换。上面示例函数以源字符串 strSrc 为起点,首先实现与 GB18030 编码互相转换,然后实现与 Big5 编码互相转换。
获取编码器的语法格式是:

QTextCodec  *codecGB = QTextCodec::codecForName("GB18030");

codecGB 是保存编码器的指针,静态函数 QTextCodec::codecForName 根据指定的编码名称获取相应的编码器,示例的是 "GB18030"。如果要将 QString 转成其他编码的 QByteArray,就用 fromUnicode 函数,反过来就用 toUnicode 函数。
上面对 GB18030 和 Big5 都做了示范,打印的结果如下图所示:


qDebug 打印 QString 对象和 UTF-8 字符串时汉字不会乱码,而 GB18030 和 Big5 等编码的汉字会乱码,只有数字、英文字符等 ASCII 码是正常显示的。

概括来说,QByteArray 作为字符串使用时,相关函数类似上一节 QString 的函数。因为 QByteArray 自身具有很多的不确定性,所以涉及到字符串处理的都优先用 QString。
在文件输入输出和网络数据收发等情景,一般用 QByteArray 作为缓冲区,配合 QDataStream 串行化使用。
对于特定字符编码的转换,Qt 提供专门的类 QTextCodec ,可以参考本节的示例进行转码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[QT_024]Qt学习之QByteArray详解 的相关文章

  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐

  • 指针 中 数组指针,指针数组,数组传参,指针传参

    1 指针数组 指针数组是一个数组 里面每个元素是指针 初始化如下 2 数组指针 指向数组的指针 形式如下int p 5 因为 比 优先级高 因此表示一个指针必须给 p带上括号 赋初值如下 3 数组指针的应用 include
  • Invalid bound statement (not found): com.lu.tech.eduservice.mapper.EduCourseMapper.queryById

    baseMapper中没有queryById 方法 使用selectById
  • EmlParse:一款超轻量级的批量解析EML格式电子邮件的工具

    工具特点 1 绿色纯天然 无任何依赖库 文件大小不到150K 2 可批量解析EML格式的电子邮件 3 可提取EML文件中的正文和附件到指定目录 4 可生成HTML格式的邮件列表清单 方便用户进行离线阅读 5 可生成JSON格式的邮件列表清单
  • ipv6 inet_pton功能说明

    基于VS2017 include
  • SpringBoot中事务配置

    做个学习笔记 SpringBoot创建的项目由于不存在xml配置文件了 对于用惯Spring的xml配置事务犯了难 百度了下 大多文章都是用 Transactional对每一个方法或类手动添加任务 这样很麻烦 就自己摸索了下 实现了对指定切
  • 2022年美赛C题翻译+思路分享

    MCM C 交易策略 思路在后面 背景 市场交易者频繁买卖波动性资产 目标是最大化其总回报 每次买卖通常都会有佣金 两种这样的资产是黄金和比特币 图 1 黄金每日价格 每金衡盎司美元 资料来源 伦敦金银市场协会 2021 年 9 月 11
  • 灰狼优化算法(GWO)(解决TSP问题,代码完整免费)

    算法背景 灰狼优化算法 GWO 由澳大利亚格里菲斯大学学者 Mirjalili 等人于2014年提出来的一种群智能优化算法 灵感来自于灰狼群体捕食行为 优点 较强的收敛性能 结构简单 需要调节的参数少 容易实现 存在能够自适应调整的收敛因子
  • MYSQL的四种连接查询学习笔记

    内连接 inner join 或者 join 外连接 1 左连接 left join 或者 left outer join 2 右连接 right join 或者 right outer join 3 完成外连接 full join 或者
  • QT TCP简单的通信示例

    TCP服务端 第一步 创建监听套接字的QTcpSever QTcpServer m tsTcpServer 第二部步 listen 监听是否有新的连接进来 int iMyport 如果有新的客户端连接的话 会触发信号newConnectio
  • Appium 环境搭建安装 java sdk 和 Android SDK

    java sdk 下载 java sdk 在官网上下载https www oracle com java technologies downloads java8 windows 无脑下一步安装 但要看清楚安装目录 配置全局变量要用 我的是
  • 关于队列的几个小算法

    1 用静态数组实现队列的基本操作 思路 创建3个变量 start end size size用来查看数组中数据的数量 从而实现添加和删除的长度控制 当添加数据时 如果end size 1 说明end已经指向最后一位 所以 end end s
  • css基础--位移和定位2(鼠标位置,滚动条位置)

    获取鼠标指针的页面位置 e pageX e clientX 获取鼠标指针在元素内的位置 e offsetX e layerX 获取滚动条的位置 self pageXOffset document documentElement docume
  • GCC编译器(2)

    接GCC编译器 1 4 警告选项 在编译过程中 编译器的报错和警告信息对于程序员来说是非常重要的信息 GCC包含完整的出错检查和警告提示功能 它可以帮助Linux程序员尽快找出错误的或潜在的错误代码 从而写过更优美的代码 GCC的编译器警告
  • 纯干货!!!Python开发必备!!!70+本图书合集(PDF+源码)

    纯干货 Python开发必备 70 本图书合集 PDF 源码 合集包含了从入门到精通 Web 安全 算法 人工智能 游戏 爬虫等一系列技术的专业书籍 其中有多本图书被程序员奉为圭臬 例如 Python编程从入门到实践 笨办法学Python
  • 9、区块链简介

    区块链 Blockchain 在2008年由署名为中本聪的作者在 比特币 一种点对点的电子现金系统 一文提出 指的是一种在对等网络环境下 通过透明和可信规则 构建防伪造 防篡改和可追溯的块链式数据结构 实现和管理事务处理的模式 区块链本质上
  • 【译】IPSEC.CONF(5) - IPsec配置

    NAME ipsec conf IPsec配置 DESCRIPTION ipsec conf指定了Openswan IPsec子系统的大多数配置和控制信息 include ipsec conf 包含指定的配置文件 CONN SECTIONS
  • 【使用 flink-cdc 将数据从 mysql 同时同步到 redis, elastisearch, clickhouse】

    要从 MySQL 同时同步到 Redis Elasticsearch 和 Clickhouse 可以使用 Flink CDC 和 Flink Table API 来实现 首先 需要在 Flink 中配置 CDC 数据源 使其能够连接到 My
  • WIndows10系统 安装Anaconda、Pycharm以及在其中导入Pytorch环境(NVIDIA GPU版本)

    WIndows10系统 安装Anaconda Pycharm以及在其中导入Pytorch环境 NVIDIA GPU版本 1 判断电脑是否具有GPU 2 安装Anaconda 3 创建虚拟环境 3 1 利用conda命令创建虚拟环境 4 GP
  • MySQL——卸载重装MySQL失败?

    该问题通常是因为MySQL卸载时 没有完全清除相关信息导致的 解决办法是 把以前的安装目录删除 如果之前安装并未单独指定过服务安装目录 则默认安装目录是 C Program Files MySQL 彻底删除该目录 同时删除MySQL的Dat
  • [QT_024]Qt学习之QByteArray详解

    本文转自 Qt编程指南 作者 奇先生 Qt编程指南 Qt新手教程 Qt Programming Guide 本节学习 QByteArray 的两种用法 第一种作为字符串处理类 类似 QString 但 QByteArray 内部字符编码不确