新人求助,关于Qsettings写reg修改注册表键值值类型问题

28141人阅读
&&&&&&& 本文先从概念和用法上讲述下QSettings的简单用法,最后以一个简单而较全面的使用例子结束,一句话:实践出真知!
QSettings 类提供“持久性”,平台独立的应用程序设置。意思是,程序关闭后QSettings把窗体大小,位置,用户设置的Option 保存起来,下次
打开程序时再重新加载。
如果你需要的是“非持久性” 基于内存的数据结构,可以考虑使用QMap&QString,QVariant& 代替。
通常,对于Windows,配置信息保存在“注册表”中,Mac OS 是XML 文件,Unix 是INI 文件
// 构造函数
QSettings settings(&MySoft&, &Star Runner&);&//& 公司或组织名& // 应用程序名
QCoreApplication::setOrganizationName(&MySoft&);
QCoreApplication::setOrganizationDomain(&&);&// 专为Mac OS X 准备的
QCoreApplication::setApplicationName(&Star Runner&);
如果要在程序很多地方使用QSettings,用 QCoreApplication::setOrganizationName() 和QCoreApplication::setApplicationName() 然后用QSettings 的默认构造函数。
这样,公司或组织名,应用程序名只要指定一次,QSettings settings 到处扔就行。
QSettings 存储了一对键值( Key / value ) ,Key 是一个QString,Value是一个QVariant
settings.setValue(&editor/wrapMargin&, 68);& //添加一对键值
添加键值的时侯,如果Key 已存在,则Value 被重写。
出于效率的原因,setValue 不会立既写入(如注册表,INI, XML), 要立既写入可以用sync() 函数。
int margin = settings.value(&editor/wrapMargin&).toInt();
通过Key,取回Value。如果指定的Key 不存在,QSettings 返回空的QVariant(转成整型是 0)。
// 类型转换
QSettings settings(&MySoft&, &Star Runner&);
QColor color =settings.value(&DataPump/bgcolor&).value&QColor&();
// 通过&/& 分组
settings.setValue(&mainwindow/size&,win-&size());
settings.setValue(&mainwindow/fullScreen&,win-&isFullScreen());
settings.setValue(&outputpanel/visible&,panel-&isVisible());
settings.beginGroup(&mainwindow&);
settings.setValue(&size&, win-&size());
settings.setValue(&fullScreen&,win-&isFullScreen());
settings.endGroup();
settings.beginGroup(&outputpanel&);
settings.endGroup();
添加分组,并链表化,读写分组
void QSettings::beginWriteArray(
constQString
& prefix,int
size =-<span style="color:#)
Adds prefix to the current group and starts writing an array of size size.
If size is -<span style="color:# (the default), it is automatically determined based on the indexes of the entries written.
If you have many occurrences of a certain set of keys,
you can use arrays to make your life easier.
For example, let's suppose that you want to save a variable-length list of user names and passwords.
You could then write:
struct Login{
QString userName;
QString password;
QList&Login& logins;
QSettings settings;
settings.beginWriteArray(&logins&);
for (int i = <span style="color:#; i & logins.size(); &#43;&#43;i) {
settings.setArrayIndex(i);
settings.setValue(&userName&, list.at(i).userName);
settings.setValue(&password&, list.at(i).password);
settings.endArray();
int QSettings::beginReadArray(
constQString
Adds prefix to the current group and starts reading from an array. Returns the size of the array.
struct Login {
QString userName;
QString password;
QList&Login& logins;
QSettings settings;
int size = settings.beginReadArray(&logins&);
for (int i = <span style="color:#; i & size; &#43;&#43;i) {
settings.setArrayIndex(i);
Login login;
login.userName = settings.value(&userName&).toString();
login.password = settings.value(&password&).toString();
logins.append(login);
settings.endArray();
QStringList QSettings::childGroups()
Returns a list of all key top-level groups that contain keys that can be read using the QSettings object.
QSettings settings;
settings.setValue(&fridge/color&, Qt::white);
settings.setValue(&fridge/size&, QSize(<span style="color:#, <span style="color:#));
settings.setValue(&sofa&, true);
settings.setValue(&tv&, false);
QStringList groups = settings.childGroups();
// groups: [&fridge&]
If a groupis
beginGroup(),the
first-levelkeys
group are returned,without
settings.beginGroup(&fridge&);
groups = settings.childGroups();
// groups: []
You can navigate through the entire setting hierarchy using childKeys() and childGroups() recursively.
See also childKeys() and allKeys().
readSettings()
/writeSettings()
void MainWindow::writeSettings()
QSettings settings(&Moose Soft&, &Clipper&);
settings.beginGroup(&MainWindow&);
settings.setValue(&size&, size());
settings.setValue(&pos&, pos());
settings.endGroup();
void MainWindow::readSettings()
QSettings settings(&Moose Soft&, &Clipper&);
settings.beginGroup(&MainWindow&);
resize(settings.value(&size&, QSize(<span style="color:#0, <span style="color:#0)).toSize());
move(settings.value(&pos&, QPoint(<span style="color:#0, <span style="color:#0)).toPoint());
settings.endGroup();
// readSettings() and writeSettings() 必须分别位于主窗体的构造函数和closeEvent函数里面。
MainWindow::MainWindow()
readSettings();
void MainWindow::closeEvent(QCloseEvent*event)
if (userReallyWantsToQuit()) {
writeSettings();
event-&accept();
event-&ignore();
&QtGui/QApplication&
#include &mainwindow.h&
int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
return a.exec();
mainwindow.h
MAINWINDOW_H
#define MAINWINDOW_H
#include &QMainWindow&
namespace Ui {
class MainWindow;
class MainWindow : public QMainWindow
explicit MainWindow(QWidget *parent = <span style="color:#);
~MainWindow();
Ui::MainWindow *ui;
#endif // MAINWINDOW_H
mainwindow.cpp
#include &mainwindow.h&
#include &ui_mainwindow.h&
#include&QList&
#include&QSettings&
#include&QFile&
#include&QStringList&
#include&QDebug&
struct Login {
QString userName;
QString password;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
ui-&setupUi(this);
QList&Login& logins;
Login lg1[<span style="color:#];
for(int i=<span style="color:#;i&<span style="color:#;i&#43;&#43;){
lg1[i].userName=QString(&log%1&).arg(i);
lg1[i].password=&000&;
logins&&lg1[i];
QString myfile=&test.ini&;
QSettings *settings=new QSettings(myfile,QSettings::IniFormat);
settings-&beginWriteArray(&logins1&);//写数组logins1
for (int i = <span style="color:#; i & logins.size(); &#43;&#43;i) {
settings-&setArrayIndex(i);
settings-&setValue(&userName&, logins.at(i).userName);
settings-&setValue(&password&, logins.at(i).password);
QList&Login& logins2;
Login lg2[<span style="color:#];
for(int i=<span style="color:#;i&<span style="color:#;i&#43;&#43;){
lg2[i].userName=QString(&log%1&).arg(i&#43;<span style="color:#);
lg2[i].password=&000&;
logins2&&lg2[i];
settings-&endArray();
//QString myfile=&test.txt&;
//QSettings *settings=new QSettings(myfile,QSettings::IniFormat);
settings-&beginWriteArray(&logins2&);//写数组logins2
for (int i = <span style="color:#; i & logins2.size()&#43;<span style="color:#; &#43;&#43;i) {
settings-&setArrayIndex(i);
settings-&setValue(&userName&, logins2.at(i-<span style="color:#).userName);
settings-&setValue(&password&, logins2.at(i-<span style="color:#).password);
settings-&endArray();
QStringList groups = settings-&childGroups();
foreach(QString str,groups)//列出所有子组
qDebug()&&str;
//QSettings
int size = settings-&beginReadArray(&logins1&);
for (int i = <span style="color:#; i & size; &#43;&#43;i) {
settings-&setArrayIndex(i);
Login login;
login.userName = settings-&value(&userName&).toString();
login.password = settings-&value(&password&).toString();
logins.append(login);
settings-&endArray();
qDebug()&&logins.size();
for(int i=<span style="color:#;i&logins.size();i&#43;&#43;)
qDebug()&&i&&logins[i].userName;
size = settings-&beginReadArray(&logins2&);
for (int i = <span style="color:#; i & size; &#43;&#43;i) {
settings-&setArrayIndex(i);
Login login;
login.userName = settings-&value(&userName&).toString();
login.password = settings-&value(&password&).toString();
logins.append(login);
settings-&endArray();
qDebug()&&logins.size();
for(int i=<span style="color:#;i&logins.size();i&#43;&#43;)
qDebug()&&i&&logins[i].userName;
settings-&beginWriteArray(&maingroup&);
//for (int i = <span style="color:#; i & logins2.size()&#43;5; &#43;&#43;i) {
settings-&setValue(&userName&, &root&);
settings-&setValue(&password&, &000&);
settings-&endArray();
qDebug()&&settings-&value(&maingroup/userName&).toString();//列出maingroup下userName的&#20540;
MainWindow::~MainWindow()
delete ui;
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:477360次
积分:4295
积分:4295
排名:第7026名
原创:45篇
转载:43篇
评论:87条
(1)(3)(5)(6)(1)(4)(2)(1)(1)(2)(2)(3)(1)(3)(5)(5)(8)(25)(1)(1)(1)(2)(2)(1)(2)一般情况下,我们在开发软件过程中,都会缓存一些信息到本地,可以使用轻量级数据库sqlite,也可以操作注册表、读写配置文件。
关于QSettings的使用前面已经介绍过了,比较详细,见“更多参考”,下面介绍下QSettings常用功能-读写注册表、配置文件。
一般情况下,我们在开发软件过程中,都会缓存一些信息到本地,可以使用轻量级数据库sqlite,也可以操作注册表、读写配置文件。
关于QSettings的使用前面已经介绍过了,比较详细,见“更多参考”,下面介绍下QSettings常用功能-读写注册表、配置文件。
无需指定注册表路径
一般情况下,我们需要定义一个宏,或者常量字符串来指定保存的注册表位置。
#define HKEY_CURRENT_USER_QT "HKEY_CURRENT_USER\\SoftWare\\Digia\\Qt"
const QString HKEY_CURRENT_USER_QT = "HKEY_CURRENT_USER\\SoftWare\\Digia\\Qt";
无需指定配置文件路径
一般情况下,我们需要定义一个宏,或者常量字符串来指定保存的配置文件位置及名称。
#define INI_QT "C:\Users\WangLiang\AppData\Roaming\Digia"
const QString INI_QT = "C:\Users\WangLiang\AppData\Roaming\Digia";
采用下面方式,我们不需要做太多工作,Qt已经很好的替你实现了!
读写注册表
下面我们以Qt为例,众所周知现在Qt已经属于Digia,也就是说:组织名为Digia,产品名为Qt。
在main()函数中,首先设置组织名、产品名。
QCoreApplication::setOrganizationName(QString("Digia"));
QCoreApplication::setApplicationName(QString("Qt"));
然后使用QSettings对注册表进行操作:
QSettings settings(QSettings, QSettings, QCoreApplication(), QCoreApplication());
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", 5);
这时,我们打开注册表regedit,数据就生成了。
存储完数据之后,默认的程序启动时需要加载对应的数据。
QString strName = settings.value("Name").toString();
int nVersion = settings.value("Version").toInt();
这时,我们可以通过查看应用程序输出窗口得到输出结果。
分目录存储
如果我们需要在同一路径下建立多个子目录该怎么办,下面介绍两种方式。
替换applicationName
如上,我们可以看出,organizationName对应的注册表路径为HKEY_CURRENT_USER\\SoftWare\\Digia,applicationName对应的为其下一级的目录,那么分目录就需要更改其对应的applicationName。
QSettings settings(QSettings::NativeFormat, QSettings::UserScope, QString("%1\\%2").arg(QCoreApplication::organizationName()).arg(QCoreApplication::applicationName()), "Qt5.5")
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", "5.5")
QSettings settings2(QString("%1\\%2").arg(QCoreApplication::organizationName()).arg(QCoreApplication::applicationName()), "Qt5.6")
settings2.setValue("Name", "Qt Creator")
settings2.setValue("Version", "5.6")
替换applicationName的方式看起来有些繁琐,相比之下,使用group分组则会更简单!
QSettings settings
settings.beginGroup("Qt5.5")
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", "5.5")
settings.endGroup()
settings.beginGroup("Qt5.6")
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", "5.6")
settings.endGroup()
这时,我们再次查看注册表数据。
新建目录,则需要重新打开注册表,如果新添加设置,则不需要重新打开注册表,只需要来回切换对应的选项即可。
读写配置文件
如上,我们只需要将格式从NativeFormat变为IniFormat即可:
QSettings settings(QSettings, QSettings, QCoreApplication(), QCoreApplication());
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", 5);
这时,我们打开对应的存储目录,数据就生成了。
我们可以进入文件夹:C:\Users\WangLiang\AppData\Roaming(AppData默认为隐藏文件,需要设置显示才可查看),可以看到生成了文件夹”Digia”以及配置文件”Qt.ini”。
存储完数据之后,默认的程序启动时需要加载对应的数据。
QString strName = settings.value("Name").toString();
int nVersion = settings.value("Version").toInt();
这时,我们可以通过查看应用程序输出窗口得到输出结果。
我们可以看到配置文件中包含默认的分组为:General。通常情况下,我们需要对配置进行归类,例如:用户名、密码等信息属于用户组,产品名称、版本号属于设置组。
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName())
settings.beginGroup("Setting")
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", 5)
settings.endGroup()
settings.beginGroup("User")
settings.setValue("UserName", "WangL")
settings.setValue("Password", "123456")
settings.endGroup()
这时我们再次查看配置文件,里面已经生成了另外两个分组。
settings.beginGroup("Setting")
QString strName = settings.value("Name").toString()
int nVersion = settings.value("Version").toInt()
settings.endGroup()
//Name:Qt Creator
settings.beginGroup("User")
QString strUserName = settings.value("UserName").toString()
QString strPassword = settings.value("Password").toString()
settings.endGroup()
//UserName:WangL
Password:123456
分目录存储
什么时候需要分目录存储呢?QQ大家都用过吧,是不是每一个用户都有一个对应QQ号的目录呢,里面保存各个用户对应的信息。
如上,我们可以看出,organizationName对应的本地路径为C:\Users\WangLiang\AppData\Roaming\Digia,applicationName对应的为其下的配置文件,那么如果我们需要在同一路径下建立多个目录就需要更改对应的organizationName,配置文件名称则需要更改其对应的applicationName了。
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QString("%1\\%2\\%3").arg(QCoreApplication::organizationName()).arg(QCoreApplication::applicationName()).arg("Qt5.5"), "User")
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", "5.5")
QSettings settings2(QSettings::IniFormat, QSettings::UserScope, QString("%1\\%2\\%3").arg(QCoreApplication::organizationName()).arg(QCoreApplication::applicationName()).arg("Qt5.5"), "User")
settings2.setValue("Name", "Qt Creator")
settings2.setValue("Version", "5.6")
这时,我们再次查看本地文件,则会发现C:\Users\WangLiang\AppData\Roaming\Digia\Qt所在目录下会生成两个文件夹”Qt5.5”和”Qt5.6”,并且每一个目录底下会生成对应的配置文件User.ini。
删除一个指定的键
QSettings settings
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", 5)
settings.remove("Name")
QStringList keys = settings.allKeys()
// keys: ["Version"]
清空所有键
settings.clear();
QStringList keys = settings.allKeys();
// keys: []
删除设置键以及子设置键
QSettings settings
settings.setValue("Qt5.6", "5.6")
settings.beginGroup("Qt5.5")
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", "5.5")
settings.endGroup()
settings.beginGroup("Qt5.6")
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", "5.6")
settings.endGroup()
settings.remove("Qt5.6")
QStringList strList = settings.allKeys()
// keys: ["Qt5.5/Name", "Qt5.5/Version"]
如果key为空字符串,在当前group()的所有键将被删除。
QSettings settings
settings.setValue("Qt5.6", "5.6")
settings.beginGroup("Qt5.5")
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", "5.5")
settings.endGroup()
settings.beginGroup("Qt5.6")
settings.setValue("Name", "Qt Creator")
settings.setValue("Version", "5.6")
settings.endGroup()
settings.beginGroup("Qt5.6")
settings.remove("")
settings.endGroup()
QStringList keys = settings.allKeys()
// keys: ["Qt5.5/Name", "Qt5.5/Version"]
如上文代码,我们可以知道未删除之前keys: ["Qt5.6", "Qt5.5/Name", "Qt5.5/Version", "Qt5.6/Name", "Qt5.6/Version"],其中Qt5.6所在分组为默认的General。
那么调用下面代码:
settings.beginGroup("Qt5.6")
settings.remove("")
settings.endGroup()
应该只删除对应组中的所有键才对,也就是说剩余的keys应该为 ["Qt5.6", "Qt5.5/Name", "Qt5.5/Version"],General下的键为什么会被删除呢?好,这里先跳过,继续。
General下的键既然可以被删除,那么在Qt5.5分组下建立对应的Qt5.6键值,应该也会被删除。
什么鬼,为嘛Qt5.5分组下的Qt5.6对应的键还在呢?
我们继续分析:
删除前:keys: ["Qt5.6", "Qt5.5/Qt5.6", "Qt5.5/Name", "Qt5.5/Version", "Qt5.6/Name", "Qt5.6/Version"]。
助手中关于remove()的说明为:Removes the setting key and any sub-settings of key.
也就是说:Qt5.5/Qt5.6键中即使存在Qt5.6,但是所属的setting key为Qt5.5而非Qt5.6,所以不会被删掉。
既然这样,那么我们的疑问也就不复存在了。
版权声明:本文内容由互联网用户自发贡献,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至: 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
用云栖社区APP,舒服~
【云栖快讯】数据库技术天团集体亮相,分享一线生产实践经验,告诉你踩过的坑、走过的路,都是老司机,靠谱!干货分享,不可错过!&&
面向阿里云ECS实例、HPC和Docker的文件存储服务。
超过10,000,000域名在这里注册
是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有...
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本...
2017杭州云栖大会火热抢票
Loading...1430人阅读
经常使用QT的QSettings了,感觉已经很熟练了,但是突然发现在64位系统上不能写注册表了,最开始我以为是管理员权限的问题,后来编译管理员权限之后发现没有问题,问题出在win7 64位的重定向上了。这是我找的资料,可以参考一下
//试验证明这样调试时没有错误了,但是根本写不了注册表 ( 网上提到)
使用的是64位系统,64位系统有文件重定向的问题。你可以试试取消文件重定向,再修改注册表。
& & PVOID OldValue = NULL;
& &if( Wow64DisableWow64FsRedirection(&OldValue) ) //取消文件重定向
& & & & & //添加修改注册表代码
& & & & & //……
& & & & & if ( FALSE == Wow64RevertWow64FsRedirection(OldValue) ) //恢复文件重定向
& & & & & & &{
& & & & & & & & & &return 0;
& & & & & & & }
下面是在64位系统中正确的做法:(实验证明了的)
////系统右键菜单写注册表
//QString strValue = m_FileTransMainWnd-&m_strAppPath&#43;&/FYSystemRightButtonUploadU.exe %1&;//系统右键菜单响应程序转发给主程序
//strValue.replace('/', '\\');
//m_FileTransMainWnd-&RegSettings = new QSettings(&HKEY_CLASSES_ROOT\\*\\shell\\RYFileTranClient&, QSettings::NativeFormat);
//m_FileTransMainWnd-&RegSettings-&setValue(NULL,m_FileTransMainWnd-&m_strRighttext);
//m_FileTransMainWnd-&RegSettings = new QSettings(&HKEY_CLASSES_ROOT\\*\\shell\\RYFileTranClient\\command&,
QSettings::NativeFormat);
//m_FileTransMainWnd-&RegSettings-&setValue(NULL,strValue);
////文件夹
//m_FileTransMainWnd-&RegSettings = new QSettings(&HKEY_CLASSES_ROOT\\Folder\\shell\\RYFileTranClient&,
QSettings::NativeFormat);
//m_FileTransMainWnd-&RegSettings-&setValue(NULL,m_FileTransMainWnd-&m_strRighttext);
//m_FileTransMainWnd-&RegSettings = new QSettings(&HKEY_CLASSES_ROOT\\Folder\\shell\\RYFileTranClient\\command&,
QSettings::NativeFormat);
//m_FileTransMainWnd-&RegSettings-&setValue(NULL,strValue);
上面的这些在调试时会提示:ASSERT failure in QSettings:&empty key&,file io\qsettings.cpp line322
将null换成&.&后就可以了,而且可以写注册表
//系统右键菜单写注册表&
QString strValue = m_FileTransMainWnd-&m_strAppPath&#43;&/FYSystemRightButtonUploadU.exe %1&;//系统右键菜单响应程序转发给主程序
strValue.replace('/', '\\');
m_FileTransMainWnd-&RegSettings = new QSettings(&HKEY_CLASSES_ROOT\\*\\shell\\RYFileTranClient&, QSettings::NativeFormat);
m_FileTransMainWnd-&RegSettings-&setValue(&.&,m_FileTransMainWnd-&m_strRighttext);
m_FileTransMainWnd-&RegSettings = new QSettings(&HKEY_CLASSES_ROOT\\*\\shell\\RYFileTranClient\\command&,
QSettings::NativeFormat);
m_FileTransMainWnd-&RegSettings-&setValue(&.&,strValue);
m_FileTransMainWnd-&RegSettings = new QSettings(&HKEY_CLASSES_ROOT\\Folder\\shell\\RYFileTranClient&,
QSettings::NativeFormat);
m_FileTransMainWnd-&RegSettings-&setValue(&.&,m_FileTransMainWnd-&m_strRighttext);
m_FileTransMainWnd-&RegSettings = new QSettings(&HKEY_CLASSES_ROOT\\Folder\\shell\\RYFileTranClient\\command&,
QSettings::NativeFormat);
m_FileTransMainWnd-&RegSettings-&setValue(&.&,strValue);
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在打开注册表时,32位程序往往在64为系统上不能直接访问64的路径,都是自动跳到WoW6432Node下面,
在打开注册表时添加“KEY_WOW64_64KEY”标志,就能直接访问64为注册表路径。
LONG lReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L&Software\\***&, 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &hKey);
对应的,访问32位注册表示可以加上KEY_WOW64_32KEY“”标志。
LONG lReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L&Software\\***&, 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, &hKey);
一般情况下32为程序打开注册表示默认“KEY_WOW64_32KEY”标志,访问64位支持注册表时,传个“KEY_WOW64_64KEY”位标志即可,但是经过测试,Window2000的系统是不支持这个标志的,所以32为程序运行在2000的系统或者以下系统时,把这个标志改成“0”即可;
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:401511次
积分:7795
积分:7795
排名:第2667名
原创:344篇
转载:179篇
评论:31条
基于python开发的跨平台的网络库,可以说只要是服务器涉及到的,都可以用。包含http、ftp、mail、ssh、xmpp、irc也包含了底层的通信库,包括twisted.basic中的基于字节或则基于行的通信。twisted最大的闪光点在于全面,而且基本上每个例子,包含服务器和客户端的实现。所以还是相当强大的。基于twisted的产品也很多,包括爬虫scrapy,以及很多其他的web服务器

我要回帖

更多关于 注册表键值 的文章

 

随机推荐