正则表达式是一个描述字符模式的对象。
JavaScript的RegExp对象和String对象定义了使用正则表达式来执行强大的模式匹配和文本检索与替换函数的方法.
在JavaScript中,正则表达式是由一个RegExp对象表示的.当然,可以使用一个RegExp()构造函数来创建RegExp对象,也可以用JavaScript
正则表达式直接量也被定义为包含在一对斜杠(/)之间的字符.所以,JavaScript可能会包含如下的代码:
var pattern = /s$/;这行代码创建一个新的RegExp对象,并将它赋给变量parttern.这个特殊的RegExp对象和所有以字母"s"结尾的字符串都匹配.用RegExp()也可以定义 一个等价的正则表达式,代码如下:
var pattern = new RegExp("s$");无论是用正则表达式直接量还是用构造函数RegExp(),创建一个RegExp对象都是比较容易的.较为困难的任务是用正则表达式语法来描述字符的模式.
JavaScript采用的是Perl语言正则表达式语法的一个相当完整的子集.
正则表达式的模式规范是由一系列字符构成的.大多数字符(包括所有字母数字字符)描述的都是按照字面意思进行匹配的字符.这样说来,正则表达式/java/就和所有包含子串 "java" 的字符串相匹配.虽然正则表达式中的其它字符不是按照字面意思进行匹配的,但它们都具有特殊的意义.正则表达式 /s$/ 包含两个字符.第一个特殊字符 "s" 是按照字面意思与自身相匹配.第二个字符 "$" 是一个特殊字符,它所匹配的是字符串的结尾.所以正则表达式 /s$/ 匹配的就是以字母 "s" 结尾 的字符串.
下面详细讲解.
我们已经发现了,在正则表达式中所有的字母字符和数字都是按照字面意思与自身相匹配的.JavaScript的正则表达式还通过以反斜杠(\)开头的转义序列支持某些非字母字符.例如,序列 "\n" , 在字符串中匹配的是一个直接量换行符.在正则表达式中,许多标点符号都有特殊的含义.下面是这些字符和它们的含义:
正则表达式的直接量字符
字符 匹配
________________________________
字母数字字符 含义
\ f 换页符
\ n 换行符
\ r 回车
\ t 制表符
\ v 垂直制表符
\ / 一个 / 直接量
\ \ 一个 \ 直接量
\ . 一个 . 直接量
\ * 一个 * 直接量
\ + 一个 + 直接量
\ ? 一个 ? 直接量
\ | 一个 ( 直接量
\ ) 一个 ) 直接量
\ [ 一个 [ 直接量
\ ] 一个 ] 直接量
\ { 一个 { 直接量
\ } 一个 } 直接量
\ XXX 由十进制数 XXX 指定的ASCII码字符
\ Xnn 由十六进制数 nn 指定的ASCII码字符
\ cX 控制字符^X. 例如, \cI等价于
\t, \cJ等价于 \n
___________________________________________________
如果想在正则表达式中使用特殊的标点符号,必须在它们之前加上一个 "\" .
2.字符类
将单独的直接符放进中括号内就可以组合成字符类.一个字符类和它所包含的任何一个字符都匹配,所以正则表达式 / [abc] / 和字母 "a" , "b" , "c" 中的任何一个都匹配.另外还可以定义否定字符类,这些类匹配的是除那些包含在中括号之内的字符外的所有字符.定义否定字符尖时,要将一个 ^ 符号作为从左中括号算起的第 一个字符.正则表达式的集合是 / [a-zA-z0-9] / .由于某些字符类非常常用,所以JavaScript的正则表达式语法包含一些特殊字符和转义序列来表示这些常用的类.例如, \s 匹配的是空格符,制表符和其它空白符, \s匹配的则是空白符之外的任何字符.
正则表达式的字符类
字符 匹配
____________________________________________________
[...] 位于括号之内的任意字符
[^...] 不在括号之中的任意字符
.
除了换行符之外的任意字符,等价于[^\n]
\w 任何单字字符,
等价于[a-zA-Z0-9]
\W
任何非单字字符,等价于[^a-zA-Z0-9]
\s 任何空白符,等价于[\ t
\ n \ r \ f \ v]
\S 任何非空白符,等价于[^\
t \ n \ r \ f \ v]
\d 任何数字,等价于[0-9]
\D
除了数字之外的任何字符,等价于[^0-9]
[\b] 一个退格直接量(特例)
________________________________________________________________
3.复制
用以上的正则表式的语法,可以把两位数描述成 / \ d \ d /,把四位数描述成 / \d \ d \ d \ d /.但我们还没有一种方法可以用来描述具有任意多数位的数字或者是一个字符串.这个串由三个字符以及跟随在字母之后的一位数字构成.这些复杂的模式使用的正则表达式语法指定了该表达式中每个元素要重复出现的次数.指定复制的字符总是出现在它们所作用的模式后面.由于某种复制类型相当常用.所以有一些特殊的字符专门用于表示它们.例如:
+号匹配的就是复制前一模式一次
或多次的模式.下面的表列出了复制语法.先看一个例子:
/\d{2, 4}/ //匹配2到4间的数字.
/\w{3} \d?/ //匹配三个单字字符和一个任意的数字.
/\s+java\s+/ //匹配字符串"java"
,并且该串前后可以有一个或多个空格.
/[^"] * / //匹配零个或多个非引号字符.
正则表达式的复制字符
字符 含义
__________________________________________________________________
{n, m} 匹配前一项至少n次,但是不能超过m次
{n, } 匹配前一项n次,或者多次
{n} 匹配前一项恰好n次
? 匹配前一项0次或1次,也就是说前一项是可选的. 等价于 {0, 1}
+ 匹配前一项1次或多次,等价于{1,}
* 匹配前一项0次或多次.等价于{0,}
___________________________________________________________________
4.选择,分组和引用
正则表达式的语法还包括指定选择项,对子表达式分组和引用前一子表达式的特殊字符.字符| 用于分隔供选择的字符.例如:
/ab|cd|ef/ 匹配的是字符串 "ab",或者是
字符串 "cd",又或者 "ef". /\d{3}|[a-z]{4}/
匹配的是要么是一个三位数,要么是四个小写字母.在正则表达式中括号具有几种作用.它的主要作用是把单独的项目分组
成子表达式,以便可以像处理一个独立的单元那种用 *、+或? 来处理那些项目.例如: /java(script) ?/
匹配的是字符串 "java",其后既可以有 "script",也可以没有. /
(ab|cd) + |ef) / 匹配的既可以是字符串 "ef",也可以是字符串"ab" 或者 "cd" 的一次或多次重复.
在正则表达式中,括号的第二个用途是在完整的模式中定义子模式。当一个正则表达式成功地和目标字符串相匹配时,可以从目标串中抽出和括号中的子模式相匹配
的部分.例如,假定我们正在检索的模式是一个或多个字母后面跟随一位或多位数字,那么我们可以使用模式 / [a-z] + \
d+/.但是由于假定我们真正关心的是每个匹配
尾部的数字,那么如果我们将模式的数字部分放在括号中 (/ [a-z] + (\d+)/)
,我们就可以从所检索到的任何匹配中抽取数字了,之后我们会对此进行解析的.
代括号的子表达式的另一个用途是,允许我们在同一正则表达式的后面引用前面的子表达式.这是通过在字符串 \
后加一位或多位数字来实现的.数字指的是代括号的
子表达式在正则表达式中的位置.例如: \1 引用的是第一个代括号的子表达式. \3
引用的是第三个代括号的子表达式.注意,由于子表达式可以嵌套在其它子表达式中,
所以它的位置是被计数的左括号的位置.
例如:在下面的正则表达式被指定为 \2:
/([Jj]ava([Ss]cript)) \sis \s (fun\w*) /
对正则表达式中前一子表达式的引用所指定的并不是那个子表达式的模式,而是与那个模式相匹配的文本.这样,引用就不只是帮助你输入正则表达式的重复部分的快
捷方式了,它还实施了一条规约,那就是一个字符串各个分离的部分包含的是完全相同的字符.例如:下面的正则表达式匹配的就是位于单引号或双引号之内的所有字
符.但是,它要求开始和结束的引号匹配(例如两个都是双引号或者都是单引号):
/[' "] [^ ' "]*[' "]/
如果要求开始和结束的引号匹配,我们可以使用如下的引用:
/( [' "] ) [^ ' "]
* \1/
\1匹配的是第一个代括号的子表达式所匹配的模式.在这个例子中,它实施了一种规约,那就是开始的引号必须和结束的引号相匹配.注意,如果反斜杠后跟随的数字比
代括号的子表达式数多,那么它就会被解析为一个十进制的转义序列,而不是一个引用.你可以坚持使用完整的三个字符来表示转义序列,这们就可以避免混淆了.例如,
使用 \044,而不是\44.下面是正则表达式的选择、分组和引用字符:
字符 含义
____________________________________________________________________
|
选择.匹配的要么是该符号左边的子表达式,要么它右边的子表达式
(...) 分组.将几个项目分为一个单元.这个单元可由
*、+、?和|等符号使用,而且还可以记住和这个组匹配的字符以供此后引
用使用
\n
和第n个分组所匹配的字符相匹配.分组是括号中的子表达式(可能是嵌套的).分组号是从左到右计数的左括号数
____________________________________________________________________
5.指定匹配的位置
我们已经看到了,一个正则表达式中的许多元素才能够匹配字符串的一个字符.例如: \s
匹配的只是一个空白符.还有一些正则表达式的元素匹配的是字符之间宽度为
0的空间,而不是实际的字符例如: \b 匹配的是一个词语的边界,也就是处于一个/w字字符和一个\w非字字符之间的边界.像\b
这样的字符并不指定任何一个匹配了的
字符串中的字符,它们指定的是匹配所发生的合法位置.有时我们称这些元素为正则表达式的锚.因为它们将模式定位在检索字符串中的一个特定位置.最常用的锚元
素是 ^, 它使模式依赖于字符串的开头,而锚元素$则使模式定位在字符串的末尾.
例如:要匹配词 "javascript" ,我们可以使用正则表达式 /^ javascript $/. 如果我们想检索
"java" 这个词自身 (不像在 "javascript" 中那样作为前缀),那么我们可以使
用模式 /\s java \s /, 它要求在词语java之前和之后都有空格.但是这样作有两个问题.第一: 如果
"java" 出现在一个字符的开头或者是结尾.该模式就不会与之匹配,除
非在开头和结尾处有一个空格. 第二:
当这个模式找到一个与之匹配的字符时,它返回的匹配的字符串前端和后端都有空格,这并不是我们想要的.因此,我们使用词语
的边界 \b 来代替真正的空格符 \s 进行匹配. 结果表达式是 /\b java \b/.
下面是正则表达式的锚字符:
字符 含义
____________________________________________________________________
^
匹配的是字符的开头,在多行检索中,匹配的是一行的开头
$ 匹配的是字符的结尾,在多行检索中,匹配的是一行的结尾
\b
匹配的是一个词语的边界.简而言之就是位于字符\w 和 \w之间的位置(注意:[\b]匹配的是退格符)
\B
匹配的是非词语的边界的字符
_____________________________________________________________________
6.属性
有关正则表达式的语法还有最后一个元素,那就是正则表达式的属性,它说明的是高级模式匹配的规则.和其它正则表达式语法不同,属性是在
/ 符号之外说明的.即它
们不出现在两个斜杠之间,而是位于第二个斜杠之后.javascript 1.2支持两个属性.属性 i
说明模式匹配应该是大小写不敏感的.属性 g 说明模式匹配应该是全局的.也
就是说,应该找出被检索的字符串中所有的匹配.这两种属性联合起来就可以执行一个全局的,大小写不敏感的匹配.
例如: 要执行一个大小不敏感的检索以找到词语 "java" (或者是 "java" 、"JAVA"等)
的第一个具体值,我们可以使用大小不敏感的正则表达式 /\b java\b/i .如果要在
一个字符串中找到 "java" 所有的具体值,我们还可以添加属性 g, 即 /\b java \b/gi .
以下是正则表达式的属性:
字符 含义
_________________________________________
i
执行大小写不敏感的匹配
g
执行一个全局的匹配,简而言之,就是找到所有的匹配,而不是在找到第一个之后就停止了
_________________________________________
除属性 g 和 i 之外,正则表达式就没有其它像属性一样的特性了.如果将构造函数 RegExp 的静态属性
multiline 设置为 true ,那么模式匹配将以多行的模式进行.在这
种模式下,锚字符 ^ 和 $ 匹配的不只是检索字符串的开头和结尾,还匹配检索字符串内部的一行的开头和结尾.例如: 模式
/Java$/ 匹配的是 "Java",但是并不匹配
"Java\nis fun" .如果我们设置了 multiline 属性,那么后者也将被匹配:
RegExp.multiline = true;
// 字符验证
jQuery.validator.addMethod("stringCheck", function(value, element) {
return this.optional(element) || /^[\u0391-\uFFE5\w]+$/.test(value);
}, "只能包括中文字、英文字母、数字和下划线");
// 中文字两个字节
jQuery.validator.addMethod("byteRangeLength", function(value, element, param) {
var length = value.length;
for(var i = 0; i < value.length; i++){
if(value.charCodeAt(i) > 127){
length++;
}
}
return this.optional(element) || ( length >= param[0] && length <= param[1] );
}, "请确保输入的值在3-15个字节之间(一个中文字算2个字节)");
// 身份证号码验证
jQuery.validator.addMethod("isIdCardNo", function(value, element) {
return this.optional(element) || isIdCardNo(value);
}, "请正确输入您的身份证号码");
// 手机号码验证
jQuery.validator.addMethod("isMobile", function(value, element) {
var length = value.length;
var mobile = /^(((13[0-9]{1})|(15[0-9]{1}))+\d{8})$/;
return this.optional(element) || (length == 11 && mobile.test(value));
}, "请正确填写您的手机号码");
// 电话号码验证
jQuery.validator.addMethod("isTel", function(value, element) {
var tel = /^\d{3,4}-?\d{7,9}$/; //电话号码格式010-12345678
return this.optional(element) || (tel.test(value));
}, "请正确填写您的电话号码");
// 联系电话(手机/电话皆可)验证
jQuery.validator.addMethod("isPhone", function(value,element) {
var length = value.length;
var mobile = /^(((13[0-9]{1})|(15[0-9]{1}))+\d{8})$/;
var tel = /^\d{3,4}-?\d{7,9}$/;
return this.optional(element) || (tel.test(value) || mobile.test(value));
}, "请正确填写您的联系电话");
// 邮政编码验证
jQuery.validator.addMethod("isZipCode", function(value, element) {
var tel = /^[0-9]{6}$/;
return this.optional(element) || (tel.test(value));
}, "请正确填写您的邮政编码");
//添加自定义校验函数
$.validator.addMethod("charNo",function(value,element) {
var length = value.length;
var your_tel =/[\W]/g;
return this.optional(element) || (length<=8&&!your_tel.test(value));
},"请输入英文字符或数字!");
//添加验证操作名称的校验函数
$.validator.addMethod("charString",function(value,element) {
var length = value.length;
var your_tel =/[^\a-zA-Z\u4E00-\u9FA5]/g;
var your_tel2=/^[A-Za-z]*$/;
return this.optional(element) || (length<=20&&!your_tel.test(value));
},"请输入中文或英文名称");
//验证手机号码(仅仅13和15开头)
$.validator.addMethod("isPhone", function(value,element) {
var length = value.length;
var mobile = /^(((13[0-9]{1})|(15[0-9]{1}))+\d{8})$/;
var tel = /^\d{3,4}-?\d{7,9}$/;
return this.optional(element) || (tel.test(value) || mobile.test(value));
}, "请正确填写您的联系电话或者手机");
匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
评注:表单验证时很实用
匹配网址URL的正则表达式:[a-zA-z]+://[^s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用
匹配国内电话号码:d{3}-d{8}|d{4}-d{7}
评注:匹配形式如 0511-4405222 或 021-87888822
匹配腾讯QQ号:[1-9][0-9]{4,}
评注:腾讯QQ号从10000开始
匹配中国邮政编码:[1-9]d{5}(?!d)
评注:中国邮政编码为6位数字
匹配身份证:d{15}|d{18}
评注:中国的身份证为15位或18位
匹配ip地址:d+.d+.d+.d+
评注:提取ip地址时有用
匹配特定数字:
^[1-9]d*$ //匹配正整数
^-[1-9]d*$ //匹配负整数
^-?[1-9]d*$ //匹配整数
^[1-9]d*|0$ //匹配非负整数(正整数 + 0)
^-[1-9]d*|0$ //匹配非正整数(负整数 + 0)
^[1-9]d*.d*|0.d*[1-9]d*$ //匹配正浮点数
^-([1-9]d*.d*|0.d*[1-9]d*)$ //匹配负浮点数
^-?([1-9]d*.d*|0.d*[1-9]d*|0?.0+|0)$ //匹配浮点数
^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$ //匹配非负浮点数(正浮点数 + 0)
^(-([1-9]d*.d*|0.d*[1-9]d*))|0?.0+|0$ //匹配非正浮点数(负浮点数 + 0)
评注:处理大量数据时有用,具体应用时注意修正
匹配特定字符串:
^[A-Za-z]+$ //匹配由26个英文字母组成的字符串
^[A-Z]+$ //匹配由26个英文字母的大写组成的字符串
^[a-z]+$ //匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$ //匹配由数字和26个英文字母组成的字符串
^w+$ //匹配由数字、26个英文字母或者下划线组成的字符串
在使用RegularExpressionValidator验证控件时的验证功能及其验证表达式介绍如下:
只能输入数字:“^[0-9]*$”
只能输入n位的数字:“^d{n}$”
只能输入至少n位数字:“^d{n,}$”
只能输入m-n位的数字:“^d{m,n}$”
只能输入零和非零开头的数字:“^(0|[1-9][0-9]*)$”
只能输入有两位小数的正实数:“^[0-9]+(.[0-9]{2})?$”
只能输入有1-3位小数的正实数:“^[0-9]+(.[0-9]{1,3})?$”
只能输入非零的正整数:“^+?[1-9][0-9]*$”
只能输入非零的负整数:“^-[1-9][0-9]*$”
只能输入长度为3的字符:“^.{3}$”
只能输入由26个英文字母组成的字符串:“^[A-Za-z]+$”
只能输入由26个大写英文字母组成的字符串:“^[A-Z]+$”
只能输入由26个小写英文字母组成的字符串:“^[a-z]+$”
只能输入由数字和26个英文字母组成的字符串:“^[A-Za-z0-9]+$”
只能输入由数字、26个英文字母或者下划线组成的字符串:“^w+$”
验证用户密码:“^[a-zA-Z]w{5,17}$”正确格式为:以字母开头,长度在6-18之间,
只能包含字符、数字和下划线。
验证是否含有^%&',;=?$"等字符:“[^%&',;=?$x22]+”
只能输入汉字:“^[u4e00-u9fa5],{0,}$”
验证Email地址:“^w+[-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$”
验证InternetURL:“^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$”
验证电话号码:“^((d{3,4})|d{3,4}-)?d{7,8}$”
正确格式为:“XXXX-XXXXXXX”,“XXXX-XXXXXXXX”,“XXX-XXXXXXX”,
“XXX-XXXXXXXX”,“XXXXXXX”,“XXXXXXXX”。
验证身份证号(15位或18位数字):“^d{15}|d{}18$”
验证一年的12个月:“^(0?[1-9]|1[0-2])$”正确格式为:“01”-“09”和“1”“12”
验证一个月的31天:“^((0?[1-9])|((1|2)[0-9])|30|31)$”
正确格式为:“01”“09”和“1”“31”。
匹配中文字符的正则表达式: [u4e00-u9fa5]
匹配双字节字符(包括汉字在内):[^x00-xff]
匹配空行的正则表达式:n[s| ]*r
匹配HTML标记的正则表达式:/< (.*)>.*|< (.*) />/
匹配首尾空格的正则表达式:(^s*)|(s*$)
匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
匹配网址URL的正则表达式:http://([w-]+.)+[w-]+(/[w- ./?%&=]*)?
(1)应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
String.prototype.len=function(){return this.replace([^x00-xff]/g,"aa").length;}
(2)应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现
String.prototype.trim = function()
{
return this.replace(/(^s*)|(s*$)/g, "");
}
(3)应用:利用正则表达式分解和转换IP地址
function IP2V(ip) //IP地址转换成对应数值
{
re=/(d+).(d+).(d+).(d+)/g //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}
(4)应用:从URL地址中提取文件名的javascript程序
s="http://www.9499.net/page1.htm";
s=s.replace(/(.*/){0,}([^.]+).*/ig,"$2") ; //Page1.htm
(5)应用:利用正则表达式限制网页表单里的文本框输入内容
用正则表达式限制只能输入中文:onkeyup="value="/blog/value.replace(/["^u4E00-u9FA5]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^u4E00-u9FA5]/g,''))"
用正则表达式限制只能输入全角字符: onkeyup="value="/blog/value.replace(/["^uFF00-uFFFF]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^uFF00-uFFFF]/g,''))"
用正则表达式限制只能输入数字:onkeyup="value="/blog/value.replace(/["^d]/g,'') "onbeforepaste= "clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))"
用正则表达式限制只能输入数字和英文:onkeyup="value="/blog/value.replace(/[W]/g,"'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,'))'
//对于datagridview使用CellMouseDown事件
private void dataGridView_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
if (e.RowIndex >= 0)
{
dataGridView.ClearSelection();
dataGridView.Rows[e.RowIndex].Selected = true;
dataGridView.CurrentCell = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex];
contextMenuStrip_ListViewItemRightClick.Show(MousePosition.X, MousePosition.Y);
}
}
}
//对于treeview可以使用mousedown事件
方法一:
private void treeView1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
TreeNode node = this.treeView1.GetNodeAt(e.Location);
if (node != null)
{
this.treeView1.SelectedNode = node;
}
}
}
方法二:
void jcsTreeView1_MouseDown(object sender, MouseEventArgs e)
{
System.Windows.Forms.TreeViewHitTestInfo hittestinfo = this.jcsTreeView1.HitTest(e.X ,e.Y);
if (hittestinfo.Node != null)
{
TreeViewHitTestLocations loc = hittestinfo.Location;
if(loc == TreeViewHitTestLocations.Label )
MessageBox.Show(hittestinfo.Node.Text);
}
}
//1.给不带密码的数据库添加密码
string strconn = @"Data
Source=E:\test.db3;Pooling=true;FailIfMissing=false";
SQLiteConnection conn =
new
SQLiteConnection(strconn);
conn.Open();
//首次设置密码
conn.ChangePassword("password");
conn.Close();
//2.读取带密码的数据
string strconn = @"Data
Source=E:\test.db3;Pooling=true;FailIfMissing=false";
SQLiteConnection conn =
new
SQLiteConnection(strconn);
//输入密码
conn.SetPassword("password");
string
sql = "select * from tb";
SQLiteDataAdapter adapter = new
SQLiteDataAdapter(sql, conn);
DataSet ds = new
DataSet();
adapter.Fill(ds);
this.dataGridView1.DataSource =
ds.Tables[0];
//3.修改数据库密码
string strconn = @"Data
Source=E:\test.db3;Pooling=true;FailIfMissing=false";
SQLiteConnection conn =
new
SQLiteConnection(strconn);
//数据原来密码
conn.SetPassword("old_password");
conn.Open();
//设置新密码
conn.ChangePassword("new_password");
conn.Close();
打个比方,如果你在等一个人,
同步的时候,你会一直等到她来了之后才做其他事情,这个过程除了等待你啥都不会做,
异步的时候,你一边在等,可能一边玩游戏或者是看报纸什么的,一直到她到来,你的等待状态才会结束
在实现上,同步的过程会阻塞进程的所有其他操作,将同步转换为异步的最常见方法则是
将会阻塞进程的等待操作放入到一个新的进程中,同时为该等待操作添加一个监视器,在检测到等待操作完成的时候结束等待的进程
Attributes(特性)讨论的是主题的天性。而 Properties(属性)则讨论的是主题的所有物中的财产、内容,状态或者所有权。
打个比方说我是人类,在这个前提下人类就是以我为主题时的一个 Attribute(特性)。而象在我的公寓中既有人也有狗一样,在这里的人就是以公寓为主题时的 Properties(属性)。
相同的事物出现在 .NET 的世界中。例如:Serializable 就是一个实例对象的 Attribute(特性),并且那个对象可能拥有一个使用所期望的 true 或 false 布尔值的属性来表示其能够被序列化。这会告诉 .NET 运行时:这个类是能够通过 Attribute(特性)来表示序列化能力的,并且又无需使用通过它所暴露的 Property(属性)就能够完全表示这个类是可序列化能力。
因此 Attribute(特性)为主题定义了特有的性质或天性,而 Property(属性)则是属于这个主题的。在面向对象范例的术语中,与主题相关的 Attribute(特性)的含意应该是:“是什么”,而 Property(属性)的含意则应该是:“有什么”。
范例
·
人是人类。这里的人类就是一个 Attribute(特性)。
·
人有翅膀。这里的翅膀就是 Properties(属性)。
那么 Field(字段) 和 Property(属性)呢?多数时候我们都会听说:Fields(字段)和 Properties(属性)在有时候听起来是相似的,而在有时候它们听起来又是不同的。而实际上,Fields(字段)定义了在存储值或者主题的状态时所必需的区域,而 Properties(属性)则除了对状态或值的呈现之外,其他的什么也没有
线程挂起:
1.一般是被动的;
2.保存现场(寄存器,页面等等),部分内存交换出去,不访问,被动开启,好象中断一样.
线程等待:
1.一般是主动的
2.不保存现场信息,内存不变,等待-访问,等待开启(有可能是某个信号量),此时的线程处于Sleep状态(起码Windows是这样的).
[STAThread]
STAThread:Single Thread Apartment Thread.(单一线程单元线程)
[]是用来表示Attributes;
[STAThread]
是一种线程模型,用在程序的入口方法上(在C#和VB.NET里是Main()方法),来指定当前线程的ApartmentState 是STA。用在其他方法上不产生影响。在aspx页面上可以使用AspCompat = "true" 来达到同样的效果。这个属性只在 Com Interop 有用,如果全部是 managed code 则无用。简单的说法:[STAThread]指示应用程序的默认线程模型是单线程单元 (STA)。启动线程模型可设置为单线程单元或多线程单元。如果未对其进行设置,则该线程不被初始化。也就是说如果你用的.NET Framework,并且没有使用COM Interop,一般不需要这个Attribute。其它的还有MTA(多线程套间)、Free Thread(自由线程)。
[STAThread] attribute指示应用程序的 COM 线程模型是单线程单元。
而于此对应的多线程单元则是 [MTAThread] (多线程单元线程)
COM 线程模型只适用于使用 COM interop 的应用程序。如果将此属性应用到不使用 COM interop 的应用程序,将没有任何效果。
COM 线程模型可设置为单线程单元或多线程单元。如果应用程序线程实际调用了 COM 组件,则仅为 COM interop 初始化该线程。如果没有使用 COM interop,则不初始化该线程。
以下是找到的一个资料介绍:
Q. When I create a c# project from scratch in VS.NET, the generated code always have a [STAThread] attribute above the main routine. What does the STAThread attribute really do? Can I change it to MTAThread instead? I have searched website and books, no one seems to explain this well.
Asked by anon. Answered by the Wonk on February 17, 2003
A.
The STAThreadAttribute marks a thread to use the Single-Threaded COM Apartment if COM is needed. By default, .NET won't initialize COM at all. It's only when COM is needed, like when a COM object or COM Control is created or when drag 'n' drop is needed, that COM is initialized. When that happens, .NET calls the underlying CoInitializeEx function, which takes a flag indicating whether to join the thread to a multi-threaded or single-threaded apartment.
A multi-threaded apartment (MTA) in COM is more efficient, since any of a number of RPC threads from a pool can be used to handle a request. However, an object on the MTA thread needs to protect itself from multiple threads accessing it at the same time, so that efficiency comes at a cost.
The single-thread apartment (STA) in COM is inherently single-threaded and therefore no additional thread synchronization is needed. The STA is implemented using the thread's Windows message queue, which is how requests to objects on an STA are serialized. Because of how the STA thread is implemented, calls to objects on that thread are serialized with Windows message handling on that thread, making sure that everything, both the COM objects and the underlying windowing objects, e.g. HWNDs, are all synchronized. This is necessary for UI-oriented COM objects, like controls and drag 'n' drop, which must also be synchronized together with the UI.
When COM is needed .NET will call CoInitializeEx, picking the MTA by default because it's more efficient. However, to get the synchronization needed for controls, windows and drag 'n' drop, you need to mark a thread's entry point with the STAThreadAttribute to let .NET know to initialize the UI thread on the STA. All of the VS.NET project templates put that attribute in to make sure you don't forget:
大致意思是:由于很多COM在.NET环境下如果使用多线程的话,会导致引用的COM不能正常运行,而如果不声明程序为STAThread的话,.NET就会自动使用多线程来提高效率,这样就会导致不可预知的后果。
以下引用另一同辈的发言:http://blog.csdn.net/qilang/archive/2006/06/06/775605.aspx
STA不是单线程的意思.英文为single threaded apartment.是一种套间(或译为公寓)线程模式.
sta thread并不表明应用程式的类型,和应用程序不搭界,恰相反,一个应用程序可以有多个线程.每个线程也可以有多个组件或对象.以前win16位系统的组件线程模式才真正是单线程.这是一种被淘汰了的模式.
线程模式用于处理组件在多线程的环境里并行与并互的方式.比如套间线程(STAThread)模式中接口跨线程传递必须被调度(Marshal),不调度直传肯定会失败!而MTA或FreeThread模式中的接口可以不经调度直接传递.
这种调度在特定的环境中非常影响性能(可有几百倍之差).如VB里只支持STAThread模式.FreeThread模式的组件会在里面表现成和跨进程一样慢!
线程模式是微软的COM基础中的极其重要的概念.一定要吃透!
我对.net真是一窍不通(没空去弄,对不起微软去年的奖赏).但我可以肯定,C#中的[STAThread]属性是应用程序的套间初始化代码.可以直接理解成SDK里的
CoInitialize(NULL);
初始一个STA套间实际上是相当于开了一个消息窗口,所有调用经此窗口过程调度到组件内.
同理[MTAThread](不知有没有这个属性,自已去查)
可以理解成
CoInitializeEx(NULL,COINIT_MULTITHREADED )
这经常是一个对初入com大门的人来说,有一定难度但必须过的一道关.