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…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...
WEB3全栈开发——面试专业技能点P4数据库
一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库,基于 mysql 库改进而来,具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点: 支持 Promise / async-await…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...