Qt 压缩/解压文件
前面讲了很多Qt的文件操作,文件操作自然就包括压缩与解压缩文件了,正好最近项目里要用到压缩以及解压缩文件,所以就研究了一下Qt如何压缩与解压缩文件。
QZipReader/QZipWriter
QZipReader 和 QZipWriter 类提供了用于读取和写入 ZIP 格式文件的功能,这个是qt自带的,试了一下个人感觉并不好用。
首先QZipReader/QZipWriter是在Qt5.14之后才引入的,而且使用需要用到gui-private这个模块,搜了一下,在 Qt 中,gui-private 模块是 Qt 框架中的一个私有模块,通常不是为公共使用而设计的。该模块包含了一些 Qt GUI 框架内部使用的实现细节、私有接口和工具类,而不是为外部开发者提供的公共 API。一般来说,Qt 将其功能模块划分为公共模块和私有模块。公共模块包含了开发者可以直接使用的公共 API,而私有模块则包含了框架内部的实现细节和工具类,这些类通常不应该被外部开发者直接使用。所以才不推荐使用。直接看代码:
首先pro文件包含对应模块:
QT +=gui-private
头文件包含:
#include <QtGui/private/qzipreader_p.h>
#include <QtGui/private/qzipwriter_p.h>
压缩函数:
/*** @brief 压缩文件* @param fileNames 需要压缩的文件绝对路径* @param path 压缩后的文件的绝对路径*/
void zip_compress(const QStringList &fileNames, const QString &path) {QZipWriter *zipWriter = new QZipWriter(path);foreach (const QString &fileName, fileNames) {if (fileName.isEmpty()) continue;QFileInfo fileInfo(fileName);if (!fileInfo.exists()) continue;QFile file(fileName);if (!file.open(QIODevice::ReadOnly)) continue;zipWriter->addFile(fileInfo.fileName(), file.readAll());file.close();}zipWriter->close();if (zipWriter) {delete zipWriter;zipWriter = nullptr;}
}
解压函数:
/*** @brief 解压缩文件* @param fileName 需要解压缩的文件* @param path 解压后文件存放的目录*/
void zip_decompress(const QString &fileName, const QString &path) {if (fileName.isEmpty()) {return;}QFileInfo fileInfo(fileName);if (!fileInfo.exists()) {return;}QZipReader *reader = new QZipReader(fileName);foreach (const QZipReader::FileInfo &info, reader->fileInfoList()) {if (!info.isDir) {QString filePath =QDir::cleanPath(path + QDir::separator() + info.filePath);QFile file(filePath);if (!file.open(QIODevice::WriteOnly)) {continue;}file.write(reader->fileData(info.filePath));file.close();} else {QString dirName =QDir::cleanPath(path + QDir::separator() + info.filePath);QDir dir(dirName);if (!dir.exists()) dir.mkdir(dirName);}}reader->close();if (reader) {delete reader;reader = nullptr;}
}
7z
常用的解压软件比较多,例如winrar、7z、bandzip等等,其中7z是支持命令行形式的,详细命令可以看一下这两篇文章:
7z 命令行详解_7z命令-CSDN博客
前面我的这篇文章:Qt外部调用进程类QProcess的使用_windows qt 调用其它进程-CSDN博客
就介绍过Qt如何通过QProcess调用外部进程,所以可以先安装7z然后使用QProcess调用7z应用程序,通过传参形式来压缩和解压缩文件,直接看代码:
压缩函数:
/*** @brief z7_compress 压缩函数* @param fileNames 需要压缩的文件的绝对路径* @param path 压缩后生成的压缩文件的绝对路径*/
void z7_compress(const QStringList &fileNames, const QString &path) {QProcess process(0);QStringList args;args.append("a");args.append(path);args.append(fileNames);args.append("-mx=3");process.start("7z.exe", args);//注意7z.exe的路径process.waitForStarted();process.waitForFinished();
}
解压缩函数:
/*** @brief z7_decompress 解压缩函数* @param fileName 需要解压缩的压缩包路径* @param path 解压缩后生成的目录*/
void z7_decompress(const QString &fileName, const QString &path) {QProcess process(0);QStringList args;args.append("x");args.append(fileName);args.append("-o" + path);args.append("-aoa");process.start("7z.exe", args);//注意7z.exe的路径process.waitForStarted();process.waitForFinished();
}
ZLib
Qt压缩和解压缩文件也可以借助第三方库,zlib或者libzip,这里只介绍zlib。libzip有兴趣的也可以自己下去研究。
zlib 是一个开源的数据压缩库,广泛用于许多应用程序和系统中。以下是关于 zlib 的详细介绍:
-
功能:
- zlib 库提供了数据压缩和解压缩的功能,支持使用 DEFLATE 算法进行数据压缩。
- zlib 提供了简单的 API,易于集成到各种应用程序中。
- zlib 还支持在压缩数据中添加校验和,以确保数据的完整性。
-
特点:
- 高效性:zlib 使用 DEFLATE 算法进行数据压缩,具有较高的压缩比和压缩速度。
- 跨平台性:zlib 可以在各种操作系统上运行,包括 Windows、Linux、macOS 等。
- 开源性:zlib 是一个开源库,使用 zlib 的应用程序可以遵循 zlib 的开源许可协议。
-
使用场景:
- zlib 可用于在应用程序中对数据进行压缩,减小数据传输和存储的大小。
- zlib 还可用于处理压缩文件格式,如 ZIP、PNG、HTTP 的 gzip 压缩等。
- zlib 也常用于实时数据流的压缩,如网络传输中的数据压缩。
-
API:
- zlib 提供了一组简单的 C 函数来进行数据压缩和解压缩,如
compress(),uncompress(),deflate(),inflate()等。 - zlib 还提供了一些工具函数和数据结构,如
z_stream结构体用于维护压缩和解压缩的状态。
- zlib 提供了一组简单的 C 函数来进行数据压缩和解压缩,如
首先需要下载zlib源码,zlib官网,下载之后解压然后准备编译:

使用Cmake:

注意cmake对应vs,我电脑vs装的是VS2022,所以我这里选的是2022。
然后先Configure再Generate等待完成:
然后进入生成目录使用VS打开对应工程文件:

编译生成:
注意debug和relase版本以及平台。
对应生成的库文件以及导入库文件:

建立这样的一个文件目录结构,然后准备在代码中使用:

注意:zconf.h这个文件在cmake生成的文件目录里面 。dll动态库文件放在可执行文件同级目录下。
在工程文件中引入对应头文件以及库文件:
#引入zlib头文件和库
INCLUDEPATH += $PWD/zlib/includewin32 {LIBS += -L$$PWD/zlib/libCONFIG(release, debug|release) {LIBS += -lzlib}CONFIG(debug, debug|release) {LIBS += -lzlibd}
}
试一下zlib的压缩以及解压字符串函数。
压缩字符串:
static QByteArray compress(const QByteArray &data) {z_stream zs;memset(&zs, 0, sizeof(zs));if (deflateInit(&zs, Z_BEST_COMPRESSION) != Z_OK) { return QByteArray(); }zs.next_in = (Bytef *)data.constData();zs.avail_in = data.size();int ret;char outbuffer[32768];QByteArray outstring;do {zs.next_out = reinterpret_cast<Bytef *>(outbuffer);zs.avail_out = sizeof(outbuffer);ret = deflate(&zs, Z_FINISH);if (outstring.size() < zs.total_out) {outstring.append(outbuffer, zs.total_out - outstring.size());}} while (ret == Z_OK);deflateEnd(&zs);if (ret != Z_STREAM_END) { return QByteArray(); }return outstring;
}
解压缩字符串:
static QByteArray decompress(const QByteArray &data) {z_stream zs;memset(&zs, 0, sizeof(zs));if (inflateInit(&zs) != Z_OK) { return QByteArray(); }zs.next_in = (Bytef *)data.constData();zs.avail_in = data.size();int ret;char outbuffer[32768];QByteArray outstring;do {zs.next_out = reinterpret_cast<Bytef *>(outbuffer);zs.avail_out = sizeof(outbuffer);ret = inflate(&zs, 0);if (outstring.size() < zs.total_out) {outstring.append(outbuffer, zs.total_out - outstring.size());}} while (ret == Z_OK);inflateEnd(&zs);if (ret != Z_STREAM_END) { return QByteArray(); }return outstring;
}
测试压缩一个长字符串:
zlib的压缩与解压缩文件目前我网上搜的只能压缩和解压缩单个的,多个的目前没有找到,简单看一下压缩和解压缩的函数。
bool compress(const QString &fileName, const QString &zipFileName) {QFile inputFile(fileName);if (!inputFile.open(QIODevice::ReadOnly)) { return false; }gzFile zipFile = gzdopen(inputFile.handle(), "wb");if (!zipFile) { return false; }char buffer[1024];int bytesRead;while ((bytesRead = inputFile.read(buffer, sizeof(buffer))) > 0) {gzwrite(zipFile, buffer, bytesRead);}gzclose(zipFile); // 关闭文件句柄inputFile.close(); // 关闭输入文件return true;
}bool decompress(const QString &zipFileName, const QString &fileName) {QFile inputFile(zipFileName);if (!inputFile.open(QIODevice::ReadOnly)) { return false; }QFile outputFile(fileName);if (!outputFile.open(QIODevice::WriteOnly)) { return false; }gzFile zipFile = gzdopen(inputFile.handle(), "rb");if (!zipFile) { return false; }char buffer[1024];int bytesRead;while ((bytesRead = gzread(zipFile, buffer, sizeof(buffer))) > 0) {if (outputFile.write(buffer, bytesRead) != bytesRead) { return false; }}gzclose(zipFile);inputFile.close();outputFile.close();return true;
}
那如果要压缩多个文件怎么办?这里可以使用QuaZip。
QuaZip
QuaZIP 是一个用于 Qt 框架的 C++ 库,它提供了对 ZIP 归档文件的读写功能。QuaZIP 是基于 zlib 和 minizip 库的封装,使得在 Qt 项目中可以方便地处理 ZIP 文件。也就是说QuaZIP是基于zlib的,使用QuaZIP的前提是已经编译好了zlib,zlib的编译前面已经讲了。这里直接开始讲QuaZIP的编译与使用。
首先下载QuaZIP,QuaZIP官网。下载之后进行解压:

可以看到里面有pro文件也有vs工程文件也有CMakeLists.txt文件,我们直接使用QtCreator来进行编译。首先因为QuaZIP依赖zlib,所以把刚刚编译的zlib文件放进来:

这个文件夹结构跟刚刚一样。
我们只编译库,所以进到这个目录:
把对应头文件放进来:

对应工程文件添加引入zlib:

然后开始编译生成对应debug和release版的库文件和导入库文件:

同样方法创建一个quazip文件夹,然后拷贝对应头文件以及导入库文件:

新建一个工程,将对应quazip文件放进工程文件夹内容,然后对应pro文件引入quazip头文件以及相关导入库文件:
INCLUDEPATH += $PWD/quazip/includewin32 {LIBS += -L$$PWD/quazip/libCONFIG(release, debug|release) {LIBS += -lquazip}CONFIG(debug, debug|release) {LIBS += -lquazipd}
}
对应动态库文件放入到可执行文件同级目录下:
注意:别忘了zlib的库文件,我测试用的debug版,所以理论上只放debug版对应zlib和QuaZIP的库文件就够了。
QuaZIP压缩和解压缩文件已经封装好了方法,比如将指定目录内的所有子目录以及文件压缩到指定压缩包内方法:
\param fileCompressed The name of the archive.\param dir The directory to compress.\param recursive Whether to pack the subdirectories as well, orjust regular files.\return true if success, false otherwise.*/static bool compressDir(QString fileCompressed, QString dir = QString(), bool recursive = true);
对应的解压方法:
/**\param fileCompressed The name of the archive.\param dir The directory to extract to, the current directory ifleft empty.\return The list of the full paths of the files extracted, empty on failure.*/static QStringList extractDir(QString fileCompressed, QString dir = QString());/// Get the file list.
写一个简单的测试程序。
界面ui:
头文件:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_openDir_clicked();void on_compress_clicked();void on_selectZip_clicked();void on_decompress_clicked();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
源文件:
#include "mainwindow.h"
#include "quazip/include/JlCompress.h"
#include "ui_mainwindow.h"#include <QDebug>
#include <QDir>
#include <QFileDialog>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);
}MainWindow::~MainWindow() { delete ui; }void MainWindow::on_openDir_clicked() {QString dirPath =QFileDialog::getExistingDirectory(nullptr, QString(), QString());ui->dePath->setText(dirPath);
}void MainWindow::on_compress_clicked() {if (ui->dePath->text().isEmpty()) return;QDir deDir(ui->dePath->text());if (!deDir.exists()) return;if (deDir.isEmpty()) return;QString zipFileName = QDir::cleanPath(deDir.absolutePath() + QDir::separator() + deDir.dirName() + ".zip");bool r = JlCompress::compressDir(zipFileName, deDir.absolutePath());if (r)qDebug() << "compress success";elseqDebug() << "compress fail";
}void MainWindow::on_selectZip_clicked() {QString zipFileName = QFileDialog::getOpenFileName(nullptr, QString(), QString(), "Code Files (*.zip *.7z)");if (zipFileName.isEmpty()) return;ui->zipPath->setText(zipFileName);
}void MainWindow::on_decompress_clicked() {if (ui->zipPath->text().isEmpty()) return;QString zipFileName = ui->zipPath->text();if (!QFile::exists(zipFileName)) return;QFileInfo zipFileInfo(zipFileName);QString deDirPath =QDir::cleanPath(zipFileInfo.absolutePath() + QDir::separator() +zipFileInfo.completeBaseName());QDir deDir(deDirPath);if (!deDir.exists()) QDir().mkpath(deDirPath);QStringList fileList = JlCompress::extractDir(zipFileInfo.absoluteFilePath(),deDir.absolutePath());if (!fileList.isEmpty())qDebug() << "decompress success";elseqDebug() << "decompress fail";
}
测试一下:

没有问题,这个测试文件的代码我会上传,仅供参考,我编译的zlib以及QuaZIP的库文件也在里面,建议自己编译,因为平台或者编译软件可能与我不同,我的环境是Windows,VS2022,Qt5.15.2。
其他相关压缩以及解压缩这里就不做介绍了,有兴趣的可以下去自己研究一下。
相关文章:
Qt 压缩/解压文件
前面讲了很多Qt的文件操作,文件操作自然就包括压缩与解压缩文件了,正好最近项目里要用到压缩以及解压缩文件,所以就研究了一下Qt如何压缩与解压缩文件。 QZipReader/QZipWriter QZipReader 和 QZipWriter 类提供了用于读取和写入 ZIP 格式文…...
【leetcode刷题之路】面试经典150题(8)——位运算+数学+一维动态规划+多维动态规划
文章目录 20 位运算20.1 【位运算】二进制求和20.2 【位运算】颠倒二进制位20.3 【位运算】位1的个数20.4 【位运算】只出现一次的数字20.5 【哈希表】【位运算】只出现一次的数字 II20.6 【位运算】数字范围按位与 21 数学21.1 【双指针】回文数21.2 【数学】加一21.3 【数学】…...
JetBrains全家桶激活,分享 WebStorm 2024 激活的方案
大家好,欢迎来到金榜探云手! WebStorm公司简介 JetBrains 是一家专注于开发工具的软件公司,总部位于捷克。他们以提供强大的集成开发环境(IDE)而闻名,如 IntelliJ IDEA、PyCharm、和 WebStorm等。这些工具…...
Sublime 彻底解决中文乱码
1. 按ctrl,打开Console,输入如下代码: import urllib.request,os; pf Package Control.sublime-package; ipp sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHand…...
复旦大学EMBA校友出席两会建言献策助力中国发展
阳春三月,备受瞩目的全国两会如期召开。期间,复旦大学EMBA多位校友作为第十四届全国人民代表大会代表、第十四届全国政协委员与全国各地代表共商国是。 无论是作为大型央企负责人,还是作为科创企业的中坚力量,复旦大学EM…...
virtualbox导入vdi
新建虚拟机 点击新建 输入新建属性 配置cpu和内存 虚拟硬盘 这里选择已有的vdi文件 摘要 这里点击完成 虚拟机添加成功 点击启动,启动虚拟机 注意 这个时候的ip,还是以前镜像的ip,如果两个镜像一起启动,则需要修 改ip地…...
【信号处理】基于DGGAN的单通道脑电信号增强和情绪检测(tensorflow)
关于 情绪检测,是脑科学研究中的一个常见和热门的方向。在进行情绪检测的分类中,真实数据不足,经常导致情绪检测模型的性能不佳。因此,对数据进行增强,成为了一个提升下游任务的重要的手段。本项目通过DCGAN模型实现脑…...
使用 Docker Compose 部署 Spring Boot 应用
使用 Docker Compose 部署 Spring Boot 应用 第一步:创建 Spring Boot 应用的 Dockerfile 在您的 Spring Boot 项目根目录中创建一个 Dockerfile。 编辑 Dockerfile,添加以下内容: # 基础镜像使用 OpenJDK FROM openjdk:11-jdk-slim# 维护者…...
nginx 正向代理 https
问题背景 因为网络环境受限,应用服务器无法直接访问外网,需要前置机上中转一下,这种情况可在应用服务器修改/etc/hosts文件指向前置机,在前置机上的nginx设置四层代理,从而出站。 方案 根据How to Use NGINX as an …...
vue3从其他页面跳转页面头部组件菜单el-menu菜单高亮
主要代码 import { ref, onMounted, watch } from vue; const activeIndex ref("/"); const route useRoute();onMounted(() > {updateActiveMenu(); });watch(() > route.path, updateActiveMenu);function updateActiveMenu() {// 根据路由更新activeMenu…...
python 条件循环语句
python 条件循环语句 一、条件控制语句1. Python3 条件控制2. if 语句3. if 嵌套4. match...case5. 注意: 二、循环控制语句1. Python3 循环语句2. while 循环3. 无限循环4. while 循环使用 else 语句5. 简单语句组6. for 语句7. for...else8. break 和 continue 语…...
CIM搭建实现发送消息的效果
目录 背景过程1、下载代码2、进行配置3、直接启动项目4、打开管理界面5、启动web客户端实例项目6、发送消息 项目使用总结 背景 公司项目有许多需要发送即时消息的场景,之前一直采用的是传统的websocket连接,它会存在掉线严重,不可重连&…...
C++第十三弹---内存管理(下)
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 目录 1、operator new与operator delete函数 1.1、operator new与operator delete函数 2、new和delete的实现原理 2.1、内置类型 2.2、自定义类型 …...
Python爬虫学习完整版
一、什么是爬虫 网络爬虫,是一种按照一定规则,自动抓取互联网信息的程序或者脚本。由于互联网数据的多样性和资源的有限性,根据用户需求定向抓取相关网页并分析也成为如今主流的爬取策略。 1 爬虫可以做什么 你可以爬取网络上的的图片&#…...
JavaScript中的继承方式详解
Question JavaScript实现继承的方式? 包含原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合式继承和ES6 类继承 JavaScript实现继承的方式 在JavaScript中,实现继承的方式多种多样,每种方式都有其优势和适用场景。以下…...
Git基础(23):Git分支合并实战保姆式流程
文章目录 前言准备正常分支合并1. 创建两个不冲突分支2. 将dev合并到test 冲突分支合并1. 制造分支冲突2. 冲突合并 前言 Git分支合并操作 准备 这里先在Gitee创建了一个空仓库,方便远程查看内容。 正常分支合并 1. 创建两个不冲突分支 (1…...
为什么有些前端一直用 div 当按钮,而不是用 button?
1. HTML 中的 <div> 和 <button> 在了解为什么有些前端开发者更喜欢使用 <div> 作为按钮之前,让我们先来了解一下 <div> 和 <button> 标签在 HTML 中的作用和区别。 <div>:是 HTML 中的一个通用容器元素࿰…...
python实战之基础篇(一)
1. 注释 # coding utf-8 # 该注释放到文件第一行, 这个注释告诉python解释器该文件的编码集是UTF-82. 导入语句有三种形式 import <模块名> from <模块名> import <代码元素> from <模块名> import <代码元素> as <代码元素别名>3. 获取…...
第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(补题)
文章目录 1 日期统计2 01串的熵3 冶炼金属4 飞机降落5 接龙数列6 岛屿个数7 子串简写8 整数删除9 景区导游10 砍树 前言:时隔一年,再次做这套题(去年参赛选手),差点道心不稳T_T,故作此补题! 1 日期统计 没写出来&…...
蓝桥杯刷题--python-32
4964. 子矩阵 - AcWing题库 from collections import deque n, m, a, b map(int, input().split()) mod 998244353 nums [] for _ in range(n): nums.append(list(map(int, input().split()))) rmin [[0 for i in range(m)] for i in range(n)] rmax [[0 for i in ran…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
leetcode73-矩阵置零
leetcode 73 思路 记录 0 元素的位置:遍历整个矩阵,找出所有值为 0 的元素,并将它们的坐标记录在数组zeroPosition中置零操作:遍历记录的所有 0 元素位置,将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...
【java】【服务器】线程上下文丢失 是指什么
目录 ■前言 ■正文开始 线程上下文的核心组成部分 为什么会出现上下文丢失? 直观示例说明 为什么上下文如此重要? 解决上下文丢失的关键 总结 ■如果我想在servlet中使用线程,代码应该如何实现 推荐方案:使用 ManagedE…...
