libcurl 笔记

来自https://curl.haxx.se/libcurl/c/libcurl-tutorial.html

初始化

参数指定要初始化的模块
curl_global_init(CURL_GLOBAL_ALL);

CURL_GLOBAL_WIN32
CURL_GLOBAL_SSL

当不再使用libcurl时调用:
curl_global_cleanup();

查询libcurl支持的特性

curl_version_info()

libcurl提供两种接口

1. easy interface – 函数以curl_easy为前缀,同步、阻塞调用
(let you do single transfers with a synchronous and blocking function call)
2. multi interface – allows multiple simultaneous transfers in a single thread

Easy libcurl

首先获得一个句柄,该句柄不能被多个线程共享
easyhandle = curl_easy_init();

设置选项,用于接下来的传输
设置的选项将一直保持,直到下一次修改
curl_easy_setopt()

重置选项
curl_easy_reset()
复制句柄,连同其选项
curl_easy_duphandle()

常用的选项比如URL
curl_easy_setopt(handle, CURLOPT_URL, “http://domain.com/”);

假设想要接收上面指定的链接处收到的数据,默认输出到stdout
可以设置自己的回调函数处理该数据
回调函数:
size_t write_data(void* buffer, size_t size, size_t nmemb, void* userp);
设置回调函数
curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data);
设置回调函数第四个参数接收的自定义数据
可以将文件句柄传入第四个参数,比如FILE*
curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &internal_struct);

执行任务
该函数连接到远程地址,传输数据,当接收到文件时,之前设置的回调函数会被调用
success = curl_easy_perform(easyhandle);

对于某些协议,比如FTP,下载一个文件需要登录、设置传输模式、改变当前目录然后传输文件数据等一系列步骤,libcurl会自动处理这些步骤,开发人员只需要提供这个需要下载的文件的URL。

多线程

libcurl是线程安全的 多线程专题https://curl.haxx.se/libcurl/c/threadsafe.html

调试

传输可能会因为某些原因失败
调试用选项
CURLOPT_VERBOSE
CURLOPT_HEADER
CURLOPT_DEBUGFUNCTION

如果了解某些传输协议,学习协议的RFC文档,用利于更好地理解和使用libcurl

待续…

《Python基础教程》 笔记

Python具有丰富和强大的库

** 幂运算符 2**3
pow(2, 3)
abs(-10) 绝对值
round(1.0 / 2.0) 四舍五入到整数
import math 导入math模块
math.floor(32.9) –> 32
from math import floor
floor(32.9)

变量
x = 3

print(“Hello World!”)
x = input(“prompt:”)

转换为字符串
str 类型
repr 函数
str(1000L) -> 1000
repr(1000L) -> 1000L

拼接字符串
“Hello ” + “World!”
temp = 100
s = “Hello” + str(temp)

raw_input 100 -> ‘100’
input 100 -> 100
input Hello -> 当做变量
raw_input Hello -> ‘Hello’ 字符串

长字符串
“”” string “”” 保留换行,和特殊字符比如’ ”
”’ string ”’
原始字符串 不会转义,最后一个字符不能是\
r’Hello,\nWorld!’ -> ‘Hello,\nWorld’

Unicode字符串
u’Hello World’

基本类型
str int long

序列
a1 = [‘Hello’, 100]
str = ‘Hello’
str[0] -> ‘H’
str[-1] -> ‘o’
分片 第一二个参数分别是元素索引[index1, index2)
a1 = [1, 2, 3, 4, 5]
a1[0:3] -> [1,2,3]
a1[0:] -> 0到结尾
a1[:] -> 所有元素
a2[0:3:1] ->第三个参数步长,默认为1
序列连接
[1,2,3] + [4,5,6]
‘Hello ‘ + ‘World’
[1,2,3] + ‘Hello’ # Error,相同类型的序列才能相加
序列乘以数字n : 序列重复n次
‘python’ * 4
pythonpythonpythonpython
空序列
[]
[None] * 10 None表示什么都没有 类似c++中的NULL
判断是否在序列中
permissions = ‘rw’
‘w’ in permissions -> True
内建函数 len min max
len 返回序列中元素个数
min(2,4,6)
列表、元组属于序列
列表 可变序列
元组 不可变序列

元素赋值
x = [1, 1, 1]
x[1] = 2 -> [1, 2, 1]

删除元素
names = [‘Alice’, ‘Beth’, ‘Cecil’]
del names[2]

分片赋值
names[1:] = [‘a’, ‘b’]

list(‘Hello’) 转换为可变序列
names.append(‘Hello’)
names.count(‘Alice’) 元素出现的次数

list tuple str 类型
a.extend(b) 拼接,修改a
a.index(‘who’) 查找元素 返回索引,找不到将引发异常
a.insert(index, value)
a.pop(index) 移除,如果不指定index,删除最后一个
a.remove(value)
a.reverse()
a.sort()
sorted(a) 返回排序副本
内建比较函数 cmp()
cmp(100, 200) -> -1

元组
不能修改
1,2,3 -> (1,2,3)
(1,2,3) -> (1,2,3)
() 空元组
(42,) 包含一个值的元组
tuple 类型非函数 以一个序列作为参数并把它转换为元组
tuple([1,2,3]) -> (1,2,3)
tuple(‘abc’) -> (‘a’,’b’,’c’)
tuple((1,2,3)) -> (1,2,3)

字符串方法
find 没有找到返回-1
“With a moo-moo here, and a moo-moo there.”.find(‘moo’)
title = “Monty python”
title.find(‘Monty’)
table = maketrans(‘ABC’, ‘abc’)
word = ‘ABC’
word.translate(table)

字典
phonebook = {‘Alice’:’2341′, ‘Beth’:’9120}
空字典 {}

dict 类型 通过对其他映射或者(键值)这样的序列对建立字典
items = [(‘name’,’Gumby’), (‘age’,42)]
d = dict(items)
d = dict(name=’Gumby’, age=42)

基本字典操作
len(d)
d[k]
d[k] = v
del d[k]
k in d

import module
— module.function()
from module import function
— function()
import math as foobar
— foobar.sqrt(100)
from math import sqrt as foobar

同一行输出
print ‘Hello’,
print ‘world!’

比较运算符可以连接
0<age<100

== 值相等 可以比较序列的值
is 引用相等 (避免用于比较类似数值和字符串这类不可变值)

逻辑运算符
and or not

三元运算符 c中的 ? :
a = b and c or d
c if b else d

range(0, 10) 结果是一个序列

zip 函数
names = [‘anne’, ‘beth’, ‘george’, ‘damon’]
ages = [12, 45, 32, 102]
zip(names, ages)
[(‘anne’, 12), (‘beth’, 45), (‘george’, 32), (‘damon’, 102)]

函数 reversed sorted

循环的else子句 没有调用break时执行

列表推导式
[x*x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

#注释

字典 引用
a = None

什么都不做的语句 pass

删除名称
x = [“Hello”, “World]
del x

执行字符串中的Python代码
exec “print ‘Hello, world!'”
exec(“print ‘Hello, world!'”) #Python3.0

命名空间
from math import sqrt
scope = {}
exec ‘sqrt = 1’ in scope
sqrt(4) # ->2.0
scope[‘sqrt’] # ->1

eval 计算表达式值

函数是否可调用
callable(x)
Python3.0 hasattr(func, __call__)

定义函数
def hello(name):
return ‘Hello. ‘ + name + ‘!’

#注释

文档字符串 def语句后面、模块或者类的开头

help函数
help(square)

非位置参数(与位置无关)
调用函数时,指明参数名

参数默认值

*收集参数到元组

**收集关键字参数到字典

在调用函数时使用 * ** 将元组或字典解包成参数

vars() 返回当前作用域字典
globals() 返回全局作用域字典
locals()

给全局变量赋值
x = 1

闭包概念 类似lua

lambda表达式
lambda 数学中表示匿名函数
一切用递归实现的功能都可以用循环实现,但有时递归更易读。
递归的一个局限,有耗尽栈空间的风险。

map(func, seq) 对序列中的每个元素应用函数
filter(func, seq) 返回其函数为真的元素的列表

isinstance(object, tuple)
isinstance(object, dict)

#为变量随机赋值
from random import choice
x = choice([‘Hello, world!’, [1,2,’e’,’e’,4]])

repr函数 输出变量文本表示
x = ‘Fnord’
print repr(x)

type
isinstance
issubclass

创建类

类中的变量和self.变量不是同一个,前者所有实例共享,后者是实例的私有变量。

foo = Person() #创建实例
foo.setName(‘Hello’)
foo.greet()
Person.setName(foo, ‘Hello’)

私有实现方式
前面加__
但仍然可以访问
s._类名__函数名()

指定超类
class Filter:

class SPAMFilter(Filter):

issubclass(SPAMFilter, Filter) ->True

获取基类
SPAMFilter.__bases__
一个对象属于哪个类
s.__class__
type(s) # 使用__metaclass__=type 或从object继承

tc是否包含talk特性
hasattr(tc, ‘talk’)
是否可调用
callable(getattr(tc, ‘talk’, None))
Python3.0 hasattr(x, ‘__call__’)

术语
特性 成员变量
方法 成员函数

异常处理
异常类 从Exception继承
引发异常 raise Exception # 会自动创建实例
raise Exception(‘hyperdrive overload’)
内建异常 exceptions模块

dir函数 列出模块的内容
import exceptions
dir(exceptions)

最重要的内建异常类:146页

捕获异常

重新抛出捕获的异常
raise # 无参数

获得异常实例

Python3.0
except (ZeroDivisionError, TypeError) as e:
捕获所有异常

__future__
两边带下划线的被称为魔法或特殊方法
实现这些方法,这些方法会在特殊情况下被Python调用

构造函数

析构函数
__del__
因为有垃圾回收机制,所以避免使用__del__

调用父类的构造函数
方法1

方法2

静态方法 类成员方法

一个实现了__iter__方法的对象是可迭代的,一个实现了next方法的对象则是迭代器。

内建函数iter可以从可迭代的对象中获得迭代器
it = iter([1,2,3])
it.next() ->1
it.next() ->2

将迭代器或迭代对象转换为序列
ti = TestIterator()
list(ti) -> […]

任何包含yield语句的函数称为生成器

生成器是逐渐产生结果的复杂递归算法的理想实现工具。

–第10章–
充电时刻
import sys
sys.path.append(‘c:/python’)
告诉解释器除了从默认的目录中寻找之外,还需要从目录c:/python中寻找模块
.py .pyw (windows系统)
.pyc 平台无关的 经过处理(编译)的,已经转换成Python能够更加有效地处理的文件。
导入模块的时候,其中的代码被执行。重复导入,不会重复执行。
强制重新导入 reload(hello) # hello – 模块名 Python3.0已经去掉

.py 文件 导入后文件名就是模块名作用域

主程序 __name__ -> ‘__main__’
import __name__ -> ‘__模块名__’
模块中的测试代码可以使用__name__判断是否执行测试代码。

pprint模块中pprint函数 提供更加智能的打印输出,比如列表分行输出。
sys.path
PYTHONPATH 环境变量

包 – 目录
目录中包含__init__.py文件

查看模块包含的内容可以使用dir函数,他会将对象(以及模块的所有函数、类、变量等)的所有特性列出
dir(sys) -> 列表[‘a’, ‘b’, …]
from copy import *
copy.__all__ 过滤
如果没有设定__all__ 用import *语句默认导出所有不以下划线开头的全局名称。
help(copy.copy) copy模块中的copy函数
print copy.copy.__doc__

模块的源代码
print copy.__file__

标准库
-sys
argv
exit([arg])
modules
path
platform
stdin
stdout
stderr
-os
environ
system(command)
sep
pathsep
linesep
urandom(n)

webbrowser模块

-fileinput
input
filename()
lineno()
filelineno()
isfirstline()
isstdin()
nextfile()
close()
-collections
-heapq #堆
-time
-random
-shelve #序列化 保存到文件
-re #正则表达式

open 默认读模式
+ 参数可以用到其他任何模式中,指明读和写都是允许的。比如r+能在打开一个文件用来读写时使用。
r 读模式
w 写模式
a 追加模式
b 二进制模式 (可添加到其他模式中使用)
rb 读取二进制文件

f = open(r’c:\file.txt’, ‘w’)
f.write(‘0112345’)
f.seek(5)
f.close()
f.read()

file.readline() 读取一行 (包含换行符)
file.readlines()

# Open your file here
try:
# Write data to your file
finally:
file.close()

# Python2.5 from __future__ import with_statement
# 自动close
with open(“somefile.txt”) as somefile:

with 上下文管理 __enter__ __exit__ contextlib模块
do_something(somefile)

当到达文件末尾时,read方法返回一个空的字符串。

数据库
Python DB API的模块特性
apilevel 所使用的Python DB API版本
threadsafety 模块的线程安全等级
paramstyle 在SQL查询中使用的参数风格

socket模块

urllib urllib2模块
能让通过网络访问文件,就像那些文件存在于你的电脑上一样。通过一个简单的函数调用,几乎可以把任何URL所指向的东西用作程序的输入。

如果需要使用HTTP验证或cookie或者要为自己的协议写扩展程序的话,urllib2是个好的选择。

标准库中一些与网络相关的模块

服务器框架
SocketServer
BaseHTTPServer
SimpleHTTPServer
CGIHTTPServer
SimpleXMLRPCServer
DocXMLRPCServer

基于SocketServer的服务器

Twisted 一个非常强大的异步网络编程框架

文件是一个可迭代对象

使用默认浏览器打开某个网址
import webbrowser
webbrowser.open(‘www.baidu.com’)

集合 set
set([0, 1, 2, 3])
set会剔除重复元素
set的元素顺序是随意的
a = set([1, 2, 3])
b = set([2, 3, 4])
并集 a.union(b) a | b
交集 a.intersection(b) b & b
a.issuperset(b)
a.issubset()
a.difference(b) a – b
a.symmetric_difference(b) a ^ b
a.copy()

reduce(func, [a, b, c])
reduce执行以下步骤
tmp = func(a, b)
tmp = func(tmp, c)

time 模块
time() 当前时间 – 1970至今的秒数
localtime() 将秒数转换为日期元组,本地时间
asctime() 将日期元组转换为字符串
mktime() 将日期元组转换为本地时间(秒数) 与localtime()功能相反
sleep()

datetime 模块
支持日期和时间的算法

timeit 模块
帮助开发人员对代码段的执行时间进行计时

random 模块
random() 0<= n < 1
randrange([start], stop, [step]) [start, stop) 随机整数
uniform(a, b) [a, b] 随机实数
choice() 从给定序列中选择随机元素
shuffle() 将给定(可变)序列的元素进行随机移位
sample() 从给定序列中 选择给定数目的元素,同时确保元素互不相同

re 正则表达式模块
compile(pattern, [flags]) 根据包含正则表达式的字符串创建模式对象
search(pattern, string, [flags]) 在字符串中寻找模式,返回第一个匹配的MatchObject
match(pattern, string, [flags]) 在字符串的开始处匹配模式,返回MatchObject
split(pattern, string, [maxsplit=0]) 根据模式的匹配项来分割字符串,返回列表
findall(pattern, string) 列出字符串中模式的所有匹配项,返回列表
sub(pat, repl, string, [count=0])将字符串中所有pat匹配项用repl替换
escape(string) 将字符串中所有特殊正则表达式字符转义

pattern =
re.sub(pattern, r'<em>\1</em>’, ‘Hello, *world*!’)
\1 引用模式匹配中的组

模式匹配默认是贪婪模式
所有的重复运算符都可以通过在其后面加上一个问号变成非贪婪版本

string模块中的模板系统 template类

functools 通过部分参数来使用某个函数,稍后再为剩下的参数提供数值
difflib 这个库让你可以计算两个序列的相似程度,
还能让你在一些序列中找出和提供的原始序列最像的那个。
可以用于创建简单的搜索程序
hashlib 如果为两个不同的字符串计算出了签名。几乎可以确保这两个签名完全不同。
加密和安全性 见 md5 sha 模块
csv 读写csv文件
timeit profile trace
itertools
logging
getopt optparse
cmd

项目3 万能的XML
from xml.sax.handler import ContentHandler
from xml.sax import parse

class MyHandler(ContentHandler):
parse(‘website.xml’, MyHandler)

str.capitalize()
getattr()
callable()
os.makedirs(‘foo/bar/baz’)
os.path.isdir()
a = [‘hello’]
*a + [‘boys’] -> * (a + [‘boys’])

项目4 新闻聚合
nntplib
NNTP(Network News Transfer Protocal,网络新闻组传输协议)
urllib
strftime(‘%y%m%d’) # 年月日
strftime(‘%H%M%S’) # 时分秒

body = server.body(id)[3] # 返回一个字符串列表
打印完所有文章后 调用server.quit()

list.extend(list)
list.append(object)

BBC新闻网页的HTML页面布局可能会变,如果这样的话就需要重写正则表达式。
在使用其他页面的时候也要注意这样的情况。要查看HTML源代码然后试着去找到适用的匹配模式。

file
str
unicode
zlib
gzip
bz2
zipfile
tarfile
shutil

《C++ GUI Qt 4 编程》 笔记(七)

第21章 创建插件

动态链接库
LIBS += -ldb_cxx
INCLUDEPATH += /usr/local/BerkeleyDb.4.2/include

QLibrary 动态加载dll

插件
常见的插件类型:
数据库驱动程序、图像格式、风格、文本编码解码器

实现一个插件
需要实现两种类:
插件类 提供访问插件功能(处理器类)的接口
处理器基类 插件提供的功能

.pro
TEMPLATE = lib
CONFIG += plugin // 指明是插件库而不是通用库

Qt应用程序在plugins目录中寻找插件比如 plugins/styles
如果需要将Qt插件配置到其他目录中
需要在代码中扩展搜索路径
QCoreApplication::addLibraryPath()
或设置QT_PLUGIN_PATH环境变量

自定义插件
1.定义接口

2. 定义插件

感知插件,加载插件

第22章 应用程序脚本

QtScript模块 ECMAScript (JavaScript标准)

1.把脚本读入QString
2.创建一个QScriptEngine对象,并设置应用程序相关的功能
3.执行脚本

QFileSystemWatcher

脚本:
pi.js
return 3.14;
cube.js
return x * x * x;

QSyntaxHighlighter

QUiLoader

扩展QVariant处理的类型
Q_DECLARE_METATYPE(QScriptValue)

第23章 平台相关特性

平台相关的编程接口
Windows Win32
Mac OS X Carbon
X11 Xlib

QWidget::winId() 返回平台相关的窗口句柄

QWidget::find() 返回指定窗口ID对应的QWidget

平台相关宏定义
Q_WS_MAC
Q_WS_X11
Q_WS_WIN
Q_WS_QWS (Qtopia)

系统版本
QSysInfo::WindowsVersion()
QSysInfo::MacintoshVersion()

编译器宏
Q_CC_MSVC

Qt/Windows桌面版 提供了ActiveQt框架,用以为ActiveX和Qt提供完美结合。
ActiveQt由两个模块组成:
QAxContainer 允许我们使用COM对象并且可以在Qt应用程序中嵌入ActiveX控件
QAxServer 允许我们导出使用Qt编写的自定义的COM对象和ActiveX控件

.pro
CONFIG += qaxcontainer
CONFIG += qaxserver

Q_ENUMS()宏
用来告诉moc在槽中使用的该类型为一个枚举类型

QAxObject封装一个COM对象
QAxWidget封装一个ActiveX控件
QAxBase为QAxObject和QAxWidget实现了COM的核心功能

编写服务器

当包括一个源于QObject类的多重继承的时候,必须总是把这个起源于QObject的类放在第一位,以便moc可以快速识别它。

Q_PROPERTY()宏 使用该宏声明的属性可以用setProperty()设置值

第24章 嵌入式编程

Qt/Embedded Linux (Qtopia Core)是为嵌入式Linux优化过的Qt版本

《C++ GUI Qt 4 编程》 笔记(六)

第17章 提供在线帮助

工具提示

状态提示 显示在状态栏上

What’s This? 文本帮助

当处于what’s this模式下时(windows 标题栏问号按钮 或shift + f1)
单击窗体,将显示设置的帮助文本

QWhatsThis::createAction();

当用户按下F1键或单击Help菜单项时,应用程序主窗口会调用help()槽

QTextBrowser

QWidget::setAttribute(Qt::WA_DeleteOnClose)
// 通常模式对话框不允许和这个应用程序中的其他任何窗口进行交互
// 以下代码允许这种交互
QWidget::setAttribute(Qt::WA_GroupLeader)

textBrowser->documentTitle();

Qt Assitant库
.pro
CONFIG += assistant

第三部分 Qt高级

第19章 Unicode

QTextCodec::codecForLocale() 获得本地字符集

让应用程序感知翻译
1. tr()
2. 程序启动时,载入一个翻译文件.qm

另一种方式:

lupdate工具

不要含有变量

应该这样

QT_TRANSLATE_NOOP(“上下文”, “xxx”);

禁止const char* 到QString的隐含转换
在包含任意Qt头文件之前预先定义:
QT_NO_CAST_FROM_ASCII
或在.pro中
DEFINES += QT_NO_CAST_FROM_ASCII

QLocale 提供本地化的数字和日期以及时间格式

动态改变语言
只需重新加载翻译文件,然后重新设置需要翻译的文本

翻译应用程序:
1. 运行lupdate,从应用程序的源代码中提取所有用户可见的字符串
2. 使用Qt Linguist翻译应用程序
3. 运行lrelease,生成二进制的.qm文件,应用程序可以使用QTranslator加载这个文件

在.pro中加入需要支持的语言
当第一次运行lupdate时会创建这两个文件xml格式
ts – translate source
qm – Qt Message
TRANSLATIONS = spreadsheet_de.ts spreadSheet_fr.ts

lupdate -verbose spreadsheet.pro

CODECFORTR = …
QTextCodec::setCodecForTr()

lrelease -verbose spreadsheet.pro

第19章 自定义外观

三种方法重新定义Qt内置窗口部件的外观
1. 子类化窗口部件类
2. 子类化QStyle或者一个预定义的风格比如QWindowStyle,Qt通过这种方法为不同平台提供基于平台的外观
3. Qt样式表 受CSS启发

样式表作用于上层的当前激活的QStyle上,因为创建样式表不引入任何子类,所以它们适合对现有窗口部件做微小的定制。

例如:
想在应用程序中的所有QLineEdit中使用黄色作为背景色

QObject::setProperty()

QStyle
内置样式类:
QStyle
|- QCommonStyle
|  |-QWindowStyle
|  |-QCleanlookStyle
|  |-QMacStyle
|  |-QPlastiqueStyle
|  |-QWindowsXPStyle
|  |-QWindowsVistaStyle
|
|- QMotifStyle
|- QCDEStyle

class MyPushButton : public QWidget

QApplication::setStyle() // 设置整个应用程序的样式
QWidget::setStyle() // 为个别窗口部件设置样式

drawControl()函数被各种QStyle的子类重新实现,用于绘制窗口部件
第20章 三维绘图 OpenGL

1. 子类化QGLWidget
2. 实现几个虚函数
3. 连接QtOpenGL OpenGL库

.pro
QT += opengl

OpenGL QPainter结合
在paintEvent()函数绘制
1. 创建一个QPainter
2. 使用QPainter绘制背景
3. 保存OpenGL状态
4. 使用OpenGL操作绘制场景
5. 恢复OpenGL状态
6. 使用QPainter绘制前景
7. 销毁QPainter

QGLWidget::renderText()

使用帧缓存对象生成叠加
基本思路:
1. opengl渲染到纹理
2. 将纹理绘制到窗口
3. 将选择框绘制到窗口
假如只有窗口大小改变时才重新opengl渲染
这时,假如选择框的大小改变,而窗口大小没有改变时,则只需要绘制一张纹理和一个选择框,模型并不需要频繁渲染。

《C++ GUI Qt 4 编程》 笔记(五)

第15章 网络

QFtp
QHttp

QTcpSocket QSslSocket
QUdpSocket

使用QCoreApplication而不是QApplication以避免连接到QtGui库

QUrl类提供了一个高级接口,用来提取URL的不同部分,如文件名称、路径、协议和端口

当所有请求都已处理完时,QFtp就发射done(bool)信号,bool表明是否有错误发生

FTP指令在Qt的事件循环中排队并等待执行。

QFtp提供的FTP指令函数
connectToHost()
login() close() list() cd() get() put() remove()
mkdir() rmdir() rename()

使用rawCommand() 可以执行任意FTP指令
ftp.rawCommand(“SITE CHMOD 755 fortune”)

QFtp信号
commandStarted(int) // int 指令ID号
commandFinished(int, bool)
stateChanged() // 只要连接进入了一个新状态就会发射该信号
done(bool) // 一旦指令队列变空,就会发射这个信号
listInfo(const QUrlInfo&) // 对list()处理的每一个文件调用该信号
如果发生错误,QFtp会自动清空指令队列,错误指令后面的指令将不会执行

.pro
QT += network

QUrlInfo urlInfo;
urlInfo.isSymLink()

QHttp
get() post() 是异步工作的,调用时立即返回,当控制权回到Qt事件循环时才会开始传输数据

QHttp貌似在Qt5中已经不存在了

QTcpSocket

连接成功后会发送connected()信号
连接失败会发送error(QAbstracSocket::SocketError)信号
readyRead()信号 只要QTcpSocket已经从服务器收到新数据,就会发射该信号

QTcpServer 信号
incomingConnection(int socketId)

QTcpServer
.listen(QHostAddress::Any, 6178); // any 表示 本地主机上的任意IP地址 0.0.0.0

基于行

发送数据使用QTextStream

QHostInfo::fromName()
QHostInfo::lookupHost()

UTP客户端

第16章 XML

QtXml模块的三个不同编程接口
QXmlStreamReader 一个用于读取格式良好的XML文档的快速解析器
DOM 将XML文档转换为应用程序可以遍历的树形结构
SAX 通过虚拟函数直接向应用程序报告解析事件

XML文件写入,三种方法:
1. 使用QXmlStreamWriter
2. 在内存中以DOM树的结构表示数据,并要求树结构将自己写到文件中
3. 手动生成XML

QXmlStreamReader
.readNext()
.isStartElement()
.isCharacters()

.pro
QT += xml

Qt的SAX类时对基于SAX2的java实现的模拟

QXmlSimpleReader
QXmlContentHandler
QXmlErrorHandler

继承自QXmlDefaultHandler
重写事件处理函数
startDocument()
startElement()
characters()
endElement()
endDocument()
fatalError()

XML保存

QXmlStreamWriter自动处理转义字符