python kivy ‘NoneType‘ object has no attribute ‘xxx‘ 问题解决方案

有很多中情况都是我遇到的,现在写出来:

一、未实例化而使用

# py文件
class A(BoxLayout)
	a = ObjectProperty(None)

	def __init__(self)
		a.text = 'textname'
#kv文件
<A>:
	a:alabel
	Label:
		id:alabel
		text:"x"

此文件报错

AttributeError:
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
jQuery1.2 API 中文版折叠展开折叠全部展开全部 英文说明 核心jQuery 核心函数 jQuery(expression,[context]) jQuery(expression,[context]) 这个函数接收一个包含 CSS 选择器的字符串,然后用这个字符串去匹配一组元素。 jQuery 的核心功能都是通过这个函数实现的。 jQuery中的一切都构建于这个函数之上,或者说都是在以某种方式使用这个函数。这个函数最基本的用法就是向它传递一个表达式(通常由 CSS 选择器组成),然后根据这个表达式来查找所有匹配的元素。 默认情况下, 如果没有指定context参数,$()将在当前的 HTML 文档中查找 DOM 元素;如果指定了 context 参数,如一个 DOM 元素集或 jQuery 对象,那就会在这个 context 中查找。 参考 Selectors 获取更多用于 expression 参数的 CSS 语法的信息。 -------------------------------------------------------------------------------- This function accepts a string containing a CSS selector which is then used to match a set of elements. The core functionality of jQuery centers around this function. Everything in jQuery is based upon this, or uses this in some way. The most basic use of this function is to pass in an expression (usually consisting of CSS), which then finds all matching elements. By default, if no context is specified, $() looks for DOM elements within the context of the current HTML document. If you do specify a context, such as a DOM element or jQuery object, the expression will be matched against the contents of that context. See Selectors for the allowed CSS syntax for expressions. 返回值 jQuery 参数 expression (String) : 用来查找的字符串 context (Element, jQuery) : (可选) 作为待查找的 DOM 元素集、文档或 jQuery 对象。 示例 找到所有 p 元素,并且这些元素都必须是 div 元素的子元素。 HTML 代码: <p>one</p> <div><p>two</p></div> <p>three</p> jQuery 代码: $("div > p"); 结果: [ <p>two</p> ] -------------------------------------------------------------------------------- 在文档的第一个表单中,查找所有的单选按钮(即: type 值为 radio 的 input 元素)。 jQuery 代码: $("input:radio", document.forms[0]); -------------------------------------------------------------------------------- 在一个由 AJAX 返回的 XML 文档中,查找所有的 div 元素。 jQuery 代码: $("div", xml.responseXML); jQuery(html)jQuery(html) 根据提供的原始 HTML 标记字符串,动态创建由 jQuery 对象包装的 DOM 元素。 你可以传递一个手写的 HTML 字符串,或者由某些模板引擎或插件创建的字符串,也可以是通过 AJAX 加载过来的字符串。但是在你创建 input 元素的时会有限制,可以参考第二个示例。当然这个字符串可以包含斜杠 (比如一个图像地址),还有反斜杠。当你创建单个元素时,请使用闭合标签或 XHTML 格式。例如,创建一个 span ,可以用 $("<span/>") 或 $("<span></span>") ,但不推荐 $("<span>") -------------------------------------------------------------------------------- Create DOM elements on-the-fly from the provided String of raw HTML. You can pass in plain HTML Strings written by hand, create them using some template engine or plugin, or load them via AJAX. There are limitations when creating input elements, see the second example. Also when passing strings that may include slashes (such as an image path), escape the slashes. When creating single elements use the closing tag or XHTML format. For example, to create a span use $("<span/>") or $("<span></span>") instead of without the closing slash/tag. 返回值 jQuery 参数 html (String) : 用于动态创建DOM元素的HTML标记字符串 示例 动态创建一个 div 元素(以及其中的所有内容),并将它追加到 body 元素中。在这个函数的内部,是通过临时创建一个元素,并将这个元素的 innerHTML 属性设置为给定的标记字符串,来实现标记到 DOM 元素转换的。所以,这个函数既有灵活性,也有局限性。 jQuery 代码: $("<div><p>Hello</p></div>").appendTo("body"); -------------------------------------------------------------------------------- 创建一个 <input> 元素必须同时设定 type 属性。因为微软规定 <input> 元素的 type 只能写一次。 jQuery 代码: // 在 IE 中无效: $("<input>").attr("type", "checkbox"); // 在 IE 中有效: $("<input type='checkbox'>"); jQuery(elements)jQuery(elements) 将一个或多个DOM元素转化为jQuery对象。 这个函数也可以接收XML文档和Window对象(虽然它们不是DOM元素)作为有效的参数。 -------------------------------------------------------------------------------- Wrap jQuery functionality around a single or multiple DOM Element(s). This function also accepts XML Documents and Window objects as valid arguments (even though they are not DOM Elements). 返回值 jQuery 参数 elements (Element, Array<Element>) : 用于封装成jQuery对象的DOM元素 示例 设置页面背景色。 jQuery 代码: $(document.body).css( "background", "black" ); -------------------------------------------------------------------------------- 隐藏一个表单中所有元素。 jQuery 代码: $(myForm.elements).hide() jQuery(callback)jQuery(callback) $(document).ready()的简写。 允许你绑定一个在DOM文档载入完成后执行的函数。这个函数的作用如同$(document).ready()一样,只不过用这个函数时,需要把页面中所有需要在 DOM 加载完成时执行的$()操作符都包装到其中来。从技术上来说,这个函数是可链接的--但真正以这种方式链接的情况并不多。 你可以在一个页面中使用任意多个$(document).ready事件。 参考 ready(Function) 获取更多 ready 事件的信息。 -------------------------------------------------------------------------------- A shorthand for $(document).ready(). Allows you to bind a function to be executed when the DOM document has finished loading. This function behaves just like $(document).ready(), in that it should be used to wrap other $() operations on your page that depend on the DOM being ready to be operated on. While this function is, technically, chainable - there really isn't much use for chaining against it. You can have as many $(document).ready events on your page as you like. See ready(Function) for details about the ready event. 返回值 jQuery 参数 callback (Function) : 当DOM加载完成后要执行的函数 示例 当DOM加载完成后,执行其中的函数。 jQuery 代码: $(function(){ // Document is ready }); -------------------------------------------------------------------------------- Uses both the shortcut for $(document).ready() and the argument to write failsafe jQuery code using the $ alias, without relying on the global alias. jQuery 代码: jQuery(function($) { // Your code using failsafe $ alias here... }); jQuery 对象访问 each(callback)each(callback) 以每一个匹配的元素作为上下文来执行一个函数。 意味着,每次执行传递进来的函数时,函数中的this关键字都指向一个不同的DOM元素(每次都是一个不同的匹配元素)。 而且,在每次执行函数时,都会给函数传递一个表示作为执行环境的元素在匹配的元素集合中所处位置的数字值作为参数(从零开始的整形)。 返回 'false' 将停止循环 (就像在普通的循环中使用 'break')。返回 'true' 跳至下一个循环(就像在普通的循环中使用'continue')。 -------------------------------------------------------------------------------- Execute a function within the context of every matched element. This means that every time the passed-in function is executed (which is once for every element matched) the 'this' keyword points to the specific DOM element. Additionally, the function, when executed, is passed a single argument representing the position of the element in the matched set (integer, zero-index). Returning 'false' from within the each function completely stops the loop through all of the elements (this is like using a 'break' with a normal loop). Returning 'true' from within the loop skips to the next iteration (this is like using a 'continue' with a normal loop). 返回值 jQuery 参数 callback (Function) : 对于每个匹配的元素所要执行的函数 示例 迭代两个图像,并设置它们的 src 属性。注意:此处 this 指代的是 DOM 对象而非 jQuery 对象。 HTML 代码: <img/><img/> jQuery 代码: $("img").each(function(i){ this.src = "test" + i + ".jpg"; }); 结果: [ <img src="test0.jpg" />, <img src="test1.jpg" /> ] -------------------------------------------------------------------------------- 如果你想得到 jQuery对象,可以使用 $(this) 函数。 jQuery 代码: $("img").each(function(){ $(this).toggleClass("example"); }); -------------------------------------------------------------------------------- 你可以使用 'return' 来提前跳出 each() 循环。 HTML 代码: <button>Change colors</button> <span></span> <div></div> <div></div> <div></div> <div></div> <div id="stop">Stop here</div> <div></div> <div></div> <div></div> jQuery 代码: $("button").click(function () { $("div").each(function (index, domEle) { // domEle == this $(domEle).css("backgroundColor", "yellow"); if ($(this).is("#stop")) { $("span").text("Stopped at div index #" + index); return false; } }); });size()size() jQuery 对象中元素的个数。 这个函数的返回值与 jQuery 对象的'length' 属性一致。 -------------------------------------------------------------------------------- The number of elements in the jQuery object. This returns the same number as the 'length' property of the jQuery object. 返回值 Number 示例 计算文档中所有图片数量 HTML 代码: <img src="test1.jpg"/> <img src="test2.jpg"/> jQuery 代码: $("img").size(); 结果: 2 lengthlength jQuery 对象中元素的个数。 当前匹配的元素个数。 size 将返回相同的值。 -------------------------------------------------------------------------------- The number of elements in the jQuery object. The number of elements currently matched. The size function will return the same value. 返回值 Number 示例 计算文档中所有图片数量 HTML 代码: <img src="test1.jpg"/> <img src="test2.jpg"/> jQuery 代码: $("img").length; 结果: 2 get()get() 取得所有匹配的 DOM 元素集合。 这是取得所有匹配元素的一种向后兼容的方式(不同于jQuery对象,而实际上是元素数组)。 如果你想要直接操作 DOM 对象而不是 jQuery 对象,这个函数非常有用。 -------------------------------------------------------------------------------- Access all matched DOM elements. This serves as a backwards-compatible way of accessing all matched elements (other than the jQuery object itself, which is, in fact, an array of elements). It is useful if you need to operate on the DOM elements themselves instead of using built-in jQuery functions. 返回值 Array<Element> 示例 选择文档中所有图像作为元素数组,并用数组内建的 reverse 方法将数组反向。 HTML 代码: <img src="test1.jpg"/> <img src="test2.jpg"/> jQuery 代码: $("img").get().reverse(); 结果: [ <img src="test2.jpg"/> <img src="test1.jpg"/> ] get(index)get(index) 取得其中一个匹配的元素。 num表示取得第几个匹配的元素。 这能够让你选择一个实际的DOM 元素并且对他直接操作,而不是通过 jQuery 函数。$(this).get(0)与$(this)[0]等价。 -------------------------------------------------------------------------------- Access a single matched DOM element at a specified index in the matched set. This allows you to extract the actual DOM element and operate on it directly without necessarily using jQuery functionality on it. This function called as $(this).get(0) is the equivalent of using square bracket notation on the jQuery object itself like $(this)[0]. 返回值 Element 参数 index (Number) :取得第 index 个位置上的元素 示例 HTML 代码: <img src="test1.jpg"/> <img src="test2.jpg"/> jQuery 代码: $("img").get(0); 结果: [ <img src="test1.jpg"/> ] index(subject)index(subject) 搜索与参数表示的对象匹配的元素,并返回相应元素的索引值值。 如果找到了匹配的元素,从0开始返回;如果没有找到匹配的元素,返回-1。 -------------------------------------------------------------------------------- Searches every matched element for the object and returns the index of the element, if found, starting with zero. Returns -1 if the object wasn't found. 返回值 Number 参数 subject (Element) : 要搜索的对象 示例 返回ID值为foobar的元素的索引值值。 HTML 代码: <div id="foobar"><b></b><span id="foo"></span></div> jQuery 代码: $("*").index($('#foobar')[0]) 结果: 5 插件机制 jQuery.fn.extend(object)jQuery.fn.extend(object) 扩展 jQuery 元素集来提供新的方法(通常用来制作插件)。 查看这里Plugins/Authoring可以获取更多信息。 -------------------------------------------------------------------------------- Extends the jQuery element set to provide new methods (used to make a typical jQuery plugin). Can be used to add functions into the to add plugin methods (plugins). 返回值 jQuery 参数 object (Object) :用来扩充 jQuery 对象。 示例 增加两个插件方法。 jQuery 代码: jQuery.fn.extend({ check: function() { return this.each(function() { this.checked = true; }); }, uncheck: function() { return this.each(function() { this.checked = false; }); } }); 结果: $("input[@type=checkbox]").check(); $("input[@type=radio]").uncheck(); jQuery.extend(object)jQuery.extend(object) 扩展jQuery对象本身。 用来在jQuery命名空间上增加新函数。 查看 'jQuery.fn.extend' 获取更多添加插件的信息。 -------------------------------------------------------------------------------- Extends the jQuery object itself. Can be used to add functions into the jQuery namespace. See 'jQuery.fn.extend' for more information on using this method to add Plugins. 返回值 jQuery 参数 object (Object) : 用以扩展 jQuery 对象 示例 在jQuery命名空间上增加两个函数。 jQuery 代码: jQuery.extend({ min: function(a, b) { return a < b ? a : b; }, max: function(a, b) { return a > b ? a : b; } }); 结果: jQuery.min(2,3); // => 2 jQuery.max(4,5); // => 5 多库共存 jQuery.noConflict()jQuery.noConflict() 运行这个函数将变量$的控制权让渡给第一个实现它的那个库。 这有助于确保jQuery不会与其他库的$对象发生冲突。在运行这个函数后,就只能使用jQuery变量访问jQuery对象。例如,在要用到$("div p")的地方,就必须换成jQuery("div p")。 -------------------------------------------------------------------------------- Run this function to give control of the $ variable back to whichever library first implemented it. This helps to make sure that jQuery doesn't conflict with the $ object of other libraries. By using this function, you will only be able to access jQuery using the 'jQuery' variable. For example, where you used to do $("div p"), you now must do jQuery("div p"). 返回值 jQuery 示例 将$引用的对象映射回原始的对象。 jQuery 代码: jQuery.noConflict(); // 使用 jQuery jQuery("div p").hide(); // 使用其他库的 $() $("content").style.display = 'none'; -------------------------------------------------------------------------------- 恢复使用别名$,然后创建并执行一个函数,在这个函数的作用域中仍然将$作为jQuery的别名来使用。在这个函数中,原来的$对象是无效的。这个函数对于大多数不依赖于其他库的插件都十分有效。 jQuery 代码: jQuery.noConflict(); (function($) { $(function() { // 使用 $ 作为 jQuery 别名的代码 }); })(jQuery); // 其他用 $ 作为别名的库的代码 -------------------------------------------------------------------------------- 创建一个新的别名用以在接下来的库中使用jQuery对象。 jQuery 代码: var j = jQuery.noConflict(); // 基于 jQuery 的代码 j("div p").hide(); // 基于其他库的 $() 代码 $("content").style.display = 'none'; jQuery.noConflict(extreme)jQuery.noConflict(extreme) 将$和jQuery的控制权都交还给原来的库。用之前请考虑清楚! 这是相对于简单的 noConflict 方法更极端的版本,因为这将完全重新定义jQuery。这通常用于一种极端的情况,比如你想要将jQuery嵌入一个高度冲突的环境。注意:调用此方法后极有可能导致插件失效。 -------------------------------------------------------------------------------- Revert control of both the $ and jQuery variables to their original owners. Use with discretion. This is a more-extreme version of the simple noConflict method, as this one will completely undo what jQuery has introduced. This is to be used in an extreme case where you'd like to embed jQuery into a high-conflict environment. NOTE: It's very likely that plugins won't work after this particular method has been called. 返回值 jQuery 参数 extreme (Boolean) : 传入 true 来允许彻底将jQuery变量还原 示例 完全将 jQuery 移到一个新的命名空间。 jQuery 代码: var dom = {}; dom.query = jQuery.noConflict(true); 结果: // 新 jQuery 的代码 dom.query("div p").hide(); // 另一个库 $() 的代码 $("content").style.display = 'none'; // 另一个版本 jQuery 的代码 jQuery("div > p").hide(); 选择器基本 #id#id 根据给定的ID匹配一个元素。 -------------------------------------------------------------------------------- Matches a single element with the given id attribute. 返回值 Element 参数 id (String) : 用于搜索的,通过元素的 id 属性中给定的值 示例 查找 ID 为"myDiv"的元素。 HTML 代码: <div id="notMe"><p>id="notMe"</p></div> <div id="myDiv">id="myDiv"</div> jQuery 代码: $("#myDiv"); 结果: [ <div id="myDiv">id="myDiv"</div> ] elementelement 根据给定的元素名匹配所有元素 -------------------------------------------------------------------------------- Matches all elements with the given name. 返回值 Array<Element> 参数 element (String) : 一个用于搜索的元素。指向 DOM 节点的标签名。 示例 查找一个 DIV 元素。 HTML 代码: <div>DIV1</div> <div>DIV2</div> <span>SPAN</span> jQuery 代码: $("div"); 结果: [ <div>DIV1</div>, <div>DIV2</div> ] .class.class 根据给定的类匹配元素。 -------------------------------------------------------------------------------- Matches all elements with the given class. 返回值 Array<Element> 参数 class (String) : 一个用以搜索的类。一个元素可以有多个类,只要有一个符合就能被匹配到。 示例 查找所有类是 "myClass" 的元素. HTML 代码: <div class="notMe">div class="notMe"</div> <div class="myClass">div class="myClass"</div> <span class="myClass">span class="myClass"</span> jQuery 代码: $(".myClass"); 结果: [ <div class="myClass">div class="myClass"</div>, <span class="myClass">span class="myClass"</span> ] ** 匹配所有元素 多用于结合上下文来搜索。 -------------------------------------------------------------------------------- Matches all elements. Most useful when combined with a context to search in. 返回值 Array<Element> 示例 找到每一个元素 HTML 代码: <div>DIV</div> <span>SPAN</span> <p>P</p> jQuery 代码: $("*") 结果: [ <div>DIV</div>, <span>SPAN</span>, <p>P</p> ] selector1,selector2,selectorNselector1,selector2,selectorN 将每一个选择器匹配到的元素合并后一起返回。 你可以指定任意多个选择器,并将匹配到的元素合并到一个结果内。 -------------------------------------------------------------------------------- Matches the combined results of all the specified selectors. You can specify any number of selectors to combine into a single result. 返回值 Array<Element> 参数 selector1 (Selector) : 一个有效的选择器 selector2 (Selector) : 另一个有效的选择器 selectorN (Selector) : (可选) 任意多个有效选择器 示例 找到匹配任意一个类的元素。 HTML 代码: <div>div</div> <p class="myClass">p class="myClass"</p> <span>span</span> <p class="notMyClass">p class="notMyClass"</p> jQuery 代码: $("div,span,p.myClass") 结果: [ <div>div</div>, <p class="myClass">p class="myClass"</p>, <span>span</span> ] 层级 ancestor descendantancestor descendant 在给定的祖先元素下匹配所有的后代元素 -------------------------------------------------------------------------------- Matches all descendant elements specified by descendant of elements specified by ancestor. 返回值 Array<Element> 参数 ancestor (Selector) : 任何有效选择器 descendant (Selector) : 用以匹配元素的选择器,并且它是第一个选择器的后代元素 示例 找到表单中所有的 input 元素 HTML 代码: <form> <label>Name:</label> <input name="name" /> <fieldset> <label>Newsletter:</label> <input name="newsletter" /> </fieldset> </form> <input name="none" /> jQuery 代码: $("form input") 结果: [ <input name="name" />, <input name="newsletter" /> ] parent > childparent > child 在给定的父元素下匹配所有的子元素 -------------------------------------------------------------------------------- Matches all child elements specified by child of elements specified by parent. 返回值 Array<Element> 参数 parent (Selector) : 任何有效选择器 child (Selector) : 用以匹配元素的选择器,并且它是第一个选择器的子元素 示例 匹配表单中所有的子级input元素。 HTML 代码: <form> <label>Name:</label> <input name="name" /> <fieldset> <label>Newsletter:</label> <input name="newsletter" /> </fieldset> </form> <input name="none" /> jQuery 代码: $("form > input") 结果: [ <input name="name" /> ] prev + nextprev + next 匹配所有紧接在 prev 元素后的 next 元素 -------------------------------------------------------------------------------- Matches all next elements specified by next that are next to elements specified by prev. 返回值 Array<Element> 参数 prev (Selector) : 任何有效选择器 next (Selector) :一个有效选择器并且紧接着第一个选择器 示例 匹配所有跟在 label 后面的 input 元素 HTML 代码: <form> <label>Name:</label> <input name="name" /> <fieldset> <label>Newsletter:</label> <input name="newsletter" /> </fieldset> </form> <input name="none" /> jQuery 代码: $("label + input") 结果: [ <input name="name" />, <input name="newsletter" /> ] prev ~ siblingsprev ~ siblings 匹配 prev 元素之后的所有 siblings 元素 -------------------------------------------------------------------------------- Matches all sibling elements after the "prev" element that match the filtering "siblings" selector. 返回值 Array<Element> 参数 prev (Selector) : 任何有效选择器 siblings (Selector) : 一个选择器,并且它作为第一个选择器的同辈 示例 找到所有与表单同辈的 input 元素 HTML 代码: <form> <label>Name:</label> <input name="name" /> <fieldset> <label>Newsletter:</label> <input name="newsletter" /> </fieldset> </form> <input name="none" /> jQuery 代码: $("form ~ input") 结果: [ <input name="none" /> ] 简单 :first:first 匹配找到的第一个元素 -------------------------------------------------------------------------------- Matches the first selected element. 返回值 Element 示例 查找表格的第一行 HTML 代码: <table> <tr><td>Header 1</td></tr> <tr><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:first") 结果: [ <tr><td>Header 1</td></tr> ] :last:last 匹配找到的最后一个元素 -------------------------------------------------------------------------------- Matches the last selected element. 返回值 Element 示例 查找表格的最后一行 HTML 代码: <table> <tr><td>Header 1</td></tr> <tr><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:last") 结果: [ <tr><td>Value 2</td></tr> ] :not(selector):not(selector) 去除所有与给定选择器匹配的元素 -------------------------------------------------------------------------------- Removes all elements matching the given selector. 返回值 Array<Element> 参数 selector (Selector) : 用于筛选的选择器 示例 查找所有未选中的 input 元素 HTML 代码: <input name="apple" /> <input name="flower" checked="checked" /> jQuery 代码: $("input:not(:checked)") 结果: [ <input name="apple" /> ] :even:even 匹配所有索引值为偶数的元素,从 0 开始计数 -------------------------------------------------------------------------------- Matches even elements, zero-indexed. 返回值 Array<Element> 示例 查找表格的1、3、5...行(即索引值0、2、4...) HTML 代码: <table> <tr><td>Header 1</td></tr> <tr><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:even") 结果: [ <tr><td>Header 1</td></tr>, <tr><td>Value 2</td></tr> ] :odd:odd 匹配所有索引值为奇数的元素,从 0 开始计数 -------------------------------------------------------------------------------- Matches odd elements, zero-indexed. 返回值 Array<Element> 示例 查找表格的2、4、6行(即索引值1、3、5...) HTML 代码: <table> <tr><td>Header 1</td></tr> <tr><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:odd") 结果: [ <tr><td>Value 1</td></tr> ] :eq(index):eq(index) 匹配一个给定索引值的元素 -------------------------------------------------------------------------------- Matches a single element by its index. 返回值 Element 参数 index (Number) : 从 0 开始计数 示例 查找第二行 HTML 代码: <table> <tr><td>Header 1</td></tr> <tr><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:eq(1)") 结果: [ <tr><td>Value 1</td></tr> ] :gt(index):gt(index) 匹配所有大于给定索引值的元素 -------------------------------------------------------------------------------- Matches all elements with an index above the given one. 返回值 Array<Element> 参数 index (Number) : 从 0 开始计数 示例 查找第二第三行,即索引值是1和2,也就是比0大 HTML 代码: <table> <tr><td>Header 1</td></tr> <tr><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:gt(0)") 结果: [ <tr><td>Value 1</td></tr>, <tr><td>Value 2</td></tr> ] :lt(index):lt(index) 匹配所有小于给定索引值的元素 -------------------------------------------------------------------------------- Matches all elements with an index below the given one. 返回值 Array<Element> 参数 index (Number) : 从 0 开始计数 示例 查找第一第二行,即索引值是0和1,也就是比2小 HTML 代码: <table> <tr><td>Header 1</td></tr> <tr><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:lt(2)") 结果: [ <tr><td>Header 1</td></tr>, <tr><td>Value 1</td></tr> ] :header:header 匹配如 h1, h2, h3之类的标题元素 -------------------------------------------------------------------------------- Matches all elements that are headers, like h1, h2, h3 and so on. 返回值 Array<Element> 示例 给页面内所有标题加上背景色 HTML 代码: <h1>Header 1</h1> <p>Contents 1</p> <h2>Header 2</h2> <p>Contents 2</p> jQuery 代码: $(":header").css("background", "#EEE"); 结果: [ <h1 style="background:#EEE;">Header 1</h1>, <h2 style="background:#EEE;">Header 2</h2> ] :animated:animated 匹配所有没有在执行动画效果中的元素 -------------------------------------------------------------------------------- Matches all elements that are currently being animated. 返回值 Array<Element> 示例 只有对不在执行动画效果的元素执行一个动画特效 HTML 代码: <button id="run">Run</button><div></div> jQuery 代码: $("#run").click(function(){ $("div:not(:animated)").animate({ left: "+20" }, 1000); }); 内容 :contains(text):contains(text) 匹配包含给定文本的元素 -------------------------------------------------------------------------------- Matches elements which contain the given text. 返回值 Array<Element> 参数 text (String) : 一个用以查找的字符串 示例 查找所有包含 "John" 的 div 元素 HTML 代码: <div>John Resig</div> <div>George Martin</div> <div>Malcom John Sinclair</div> <div>J. Ohn jQuery 代码: $("div:contains('John')") 结果: [ <div>John Resig</div>, <div>Malcom John Sinclair</div> ] :empty:empty 匹配所有不包含子元素或者文本的空元素 -------------------------------------------------------------------------------- Matches all elements that are empty, be it elements or text. 返回值 Array<Element> 示例 查找所有不包含子元素或者文本的空元素 HTML 代码: <table> <tr><td>Value 1</td><td></td></tr> <tr><td>Value 2</td><td></td></tr> </table> jQuery 代码: $("td:empty") 结果: [ <td></td>, <td></td> ] :has(selector):has(selector) 匹配含有选择器所匹配的元素的元素 -------------------------------------------------------------------------------- Matches elements which contain at least one element that matches the specified selector. 返回值 Array<Element> 参数 selector (Selector) : 一个用于筛选的选择器 示例 给所有包含 p 元素的 div 元素添加一个 text 类 HTML 代码: <div><p>Hello</p></div> <div>Hello again!</div> jQuery 代码: $("div:has(p)").addClass("test"); 结果: [ <div class="test"><p>Hello</p></div> ] :parent:parent 匹配含有子元素或者文本的元素 -------------------------------------------------------------------------------- Matches all elements that are parents - they have child elements, including text. 返回值 Array<Element> 示例 查找所有含有子元素或者文本的 td 元素 HTML 代码: <table> <tr><td>Value 1</td><td></td></tr> <tr><td>Value 2</td><td></td></tr> </table> jQuery 代码: $("td:parent") 结果: [ <td>Value 1</td>, <td>Value 1</td> ] 可见性 :hidden:hidden 匹配所有的不可见元素,input 元素的 type 属性为 "hidden" 的话也会被匹配到 -------------------------------------------------------------------------------- Matches all elements that are hidden, or input elements of type "hidden". 返回值 Array<Element> 示例 查找所有不可见的 tr 元素 HTML 代码: <table> <tr style="display:none"><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:hidden") 结果: [ <tr style="display:none"><td>Value 1</td></tr> ] :visible:visible 匹配所有的可见元素 -------------------------------------------------------------------------------- Matches all elements that are visible. 返回值 Array<Element> 示例 查找所有可见的 tr 元素 HTML 代码: <table> <tr style="display:none"><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:visible") 结果: [ <tr><td>Value 2</td></tr> ] 属性 [attribute][attribute] 匹配包含给定属性的元素 -------------------------------------------------------------------------------- Matches elements that have the specified attribute. 返回值 Array<Element> 参数 attribute (String) : 属性名 示例 查找所有含有 id 属性的 div 元素 HTML 代码: <div> <p>Hello!</p> </div> <div id="test2"></div> jQuery 代码: $("div[id]") 结果: [ <div id="test2"></div> ] [attribute=value][attribute=value] 匹配给定的属性是某个特定值的元素 -------------------------------------------------------------------------------- Matches elements that have the specified attribute with a certain value. 返回值 Array<Element> 参数 attribute (String) : 属性名 value (String) : 属性值。引号在大多数情况下是可选的。但在遇到诸如属性值包含"]"时,用以避免冲突。 示例 查找所有 name 属性是 newsletter 的 input 元素 HTML 代码: '<input type="checkbox" name="newsletter" value="Hot Fuzz" /> <input type="checkbox" name="newsletter" value="Cold Fusion" /> <input type="checkbox" name="accept" value="Evil Plans" /> jQuery 代码: $("input[name='newsletter']").attr("checked", true); 结果: [ <input type="checkbox" name="newsletter" value="Hot Fuzz" checked="true" />, <input type="checkbox" name="newsletter" value="Cold Fusion" checked="true" /> ] [attribute!=value][attribute!=value] 匹配给定的属性是不包含某个特定值的元素 -------------------------------------------------------------------------------- Matches elements that don't have the specified attribute with a certain value. 返回值 Array<Element> 参数 attribute (String) : 属性名 value (String) : 属性值。引号在大多数情况下是可选的。但在遇到诸如属性值包含"]"时,用以避免冲突。 示例 查找所有 name 属性不是 newsletter 的 input 元素 HTML 代码: '<input type="checkbox" name="newsletter" value="Hot Fuzz" /> <input type="checkbox" name="newsletter" value="Cold Fusion" /> <input type="checkbox" name="accept" value="Evil Plans" /> jQuery 代码: $("input[name!='newsletter']").attr("checked", true); 结果: [ <input type="checkbox" name="accept" value="Evil Plans" checked="true" /> ] [attribute^=value][attribute^=value] 匹配给定的属性是以某些值开始的元素 -------------------------------------------------------------------------------- Matches elements that have the specified attribute and it starts with a certain value. 返回值 Array<Element> 参数 attribute (String) : 属性名 value ( String) : 属性值。引号在大多数情况下是可选的。但在遇到诸如属性值包含"]"时,用以避免冲突。 示例 查找所有 name 以 'news' 开始的 input 元素 HTML 代码: <input name="newsletter" /> <input name="milkman" /> <input name="newsboy" /> jQuery 代码: $("input[name^='news']") 结果: [ <input name="newsletter" />, <input name="newsboy" /> ] [attribute$=value][attribute$=value] 匹配给定的属性是以某些值结尾的元素 -------------------------------------------------------------------------------- Matches elements that have the specified attribute and it ends with a certain value. 返回值 Array<Element> 参数 attribute (String) : 属性名 value (String) : 属性值。引号在大多数情况下是可选的。但在遇到诸如属性值包含"]"时,用以避免冲突。 示例 查找所有 name 以 'letter' 结尾的 input 元素 HTML 代码: <input name="newsletter" /> <input name="milkman" /> <input name="jobletter" /> jQuery 代码: $("input[name$='letter']") 结果: [ <input name="newsletter" />, <input name="jobletter" /> ] [attribute*=value][attribute*=value] 匹配给定的属性是以包含某些值的元素 -------------------------------------------------------------------------------- Matches elements that have the specified attribute and it contains a certain value. 返回值 Array<Element> 参数 attribute (String) : 属性名 value (String) : 属性值。引号在大多数情况下是可选的。但在遇到诸如属性值包含"]"时,用以避免冲突。 示例 查找所有 name 包含 'man' 的 input 元素 HTML 代码: <input name="man-news" /> <input name="milkman" /> <input name="letterman2" /> <input name="newmilk" /> jQuery 代码: $("input[name*='man']") 结果: [ <input name="man-news" />, <input name="milkman" />, <input name="letterman2" /> ] [selector1][selector2][selectorN][selector1][selector2][selectorN] 复合属性选择器,需要同时满足多个条件时使用。 -------------------------------------------------------------------------------- Matches elements that have the specified attribute and it contains a certain value. 返回值 Array<Element> 参数 selector1 (Selector) : 属性选择器 selector2 (Selector) : 另一个属性选择器,用以进一步缩小范围 selectorN (Selector) : 任意多个属性选择器 示例 找到所有含有 id 属性,并且它的 name 属性是以 man 结尾的 HTML 代码: <input id="man-news" name="man-news" /> <input name="milkman" /> <input id="letterman" name="new-letterman" /> <input name="newmilk" /> jQuery 代码: $("input[id][name$='man']") 结果: [ <input id="letterman" name="new-letterman" /> ] 子元素 :nth-child(index/even/odd/equation):nth-child(index/even/odd/equation) 匹配其父元素下的第N个子或奇偶元素 ':eq(index)' 只匹配一个元素,而这个将为每一个父元素匹配子元素。:nth-child从1开始的,而:eq()是从0算起的! 可以使用: nth-child(even) :nth-child(odd) :nth-child(3n) :nth-child(2) :nth-child(3n+1) :nth-child(3n+2) -------------------------------------------------------------------------------- Matches the nth-child of its parent. While ':eq(index)' matches only a single element, this matches more then one: One for each parent. The specified index is one-indexed, in contrast to :eq() which starst at zero. 返回值 Array<Element> 参数 index (Number) : 要匹配元素的序号,从1开始 示例 在每个 ul 查找第 2 个li HTML 代码: <ul> <li>John</li> <li>Karl</li> <li>Brandon</li> </ul> <ul> <li>Glen</li> <li>Tane</li> <li>Ralph</li> </ul> jQuery 代码: $("ul li:nth-child(2)") 结果: [ <li>Karl</li>, <li>Tane</li> ] :first-child:first-child 匹配第一个子元素 ':first' 只匹配一个元素,而此选择符将为每个父元素匹配一个子元素 -------------------------------------------------------------------------------- Matches the first child of its parent. While ':first' matches only a single element, this matches more then one: One for each parent. 返回值 Array<Element> 示例 在每个 ul 中查找第一个 li HTML 代码: <ul> <li>John</li> <li>Karl</li> <li>Brandon</li> </ul> <ul> <li>Glen</li> <li>Tane</li> <li>Ralph</li> </ul> jQuery 代码: $("ul li:first-child") 结果: [ <li>John</li>, <li>Glen</li> ] :last-child:last-child 匹配最后一个子元素 ':last'只匹配一个元素,而此选择符将为每个父元素匹配一个子元素 -------------------------------------------------------------------------------- Matches the last child of its parent. While ':last' matches only a single element, this matches more then one: One for each parent. 返回值 Array<Element> 示例 在每个 ul 中查找最后一个 li HTML 代码: <ul> <li>John</li> <li>Karl</li> <li>Brandon</li> </ul> <ul> <li>Glen</li> <li>Tane</li> <li>Ralph</li> </ul> jQuery 代码: $("ul li:last-child") 结果: [ <li>Brandon</li>, <li>Ralph</li> ] :only-child:only-child 如果某个元素是父元素中唯一的子元素,那将会被匹配 如果父元素中含有其他元素,那将不会被匹配。 -------------------------------------------------------------------------------- Matches the only child of its parent. If the parent has other child elements, nothing is matched. 返回值 Array<Element> 示例 在 ul 中查找是唯一子元素的 li HTML 代码: <ul> <li>John</li> <li>Karl</li> <li>Brandon</li> </ul> <ul> <li>Glen</li> jQuery 代码: $("ul li:only-child") 结果: [ <li>Glen</li> ] 表单 :input:input 匹配所有 input, textarea, select 和 button 元素 -------------------------------------------------------------------------------- Matches all input, textarea, select and button elements. 返回值 Array<Element> 示例 查找所有的input元素 HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":input") 结果: [ <input type="text" />, <input type="checkbox" />, <input type="radio" />, <input type="image" />, <input type="file" />, <input type="submit" />, <input type="reset" />, <input type="password" />, <input type="button" /> ] :text:text 匹配所有的单行文本框 -------------------------------------------------------------------------------- Matches all input elements of type text. 返回值 Array<Element> 示例 查找所有文本框 HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":text") 结果: [ <input type="text" /> ] :password:password 匹配所有密码框 -------------------------------------------------------------------------------- Matches all input elements of type password. 返回值 Array<Element> 示例 查找所有密码框 HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":password") 结果: [ <input type="password" /> ] :radio:radio 匹配所有单选按钮 -------------------------------------------------------------------------------- Matches all input elements of type radio. 返回值 Array<Element> 示例 查找所有单选按钮 HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":radio") 结果: [ <input type="radio" /> ] :checkbox:checkbox 匹配所有复选框 -------------------------------------------------------------------------------- Matches all input elements of type checkbox. 返回值 Array<Element> 示例 查找所有复选框 HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":checkbox") 结果: [ <input type="checkbox" /> ] :submit:submit 匹配所有提交按钮 -------------------------------------------------------------------------------- Matches all input elements of type submit. 返回值 Array<Element> 示例 查找所有提交按钮 HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":submit") 结果: [ <input type="submit" /> ] :image:image 匹配所有图像域 -------------------------------------------------------------------------------- Matches all input elements of type image. 返回值 Array<Element> 示例 匹配所有图像域 HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":image") 结果: [ <input type="image" /> ] :reset:reset 匹配所有重置按钮 -------------------------------------------------------------------------------- Matches all input elements of type reset. 返回值 Array<Element> 示例 查找所有重置按钮 HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":reset") 结果: [ <input type="reset" /> ] :button:button 匹配所有按钮 -------------------------------------------------------------------------------- Matches all input elements of type button. 返回值 Array<Element> 示例 查找所有按钮. HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":button") 结果: [ <input type="button" />,<button></button> ] :file:file 匹配所有文件域 -------------------------------------------------------------------------------- Matches all input elements of type file. 返回值 Array<Element> 示例 查找所有文件域 HTML 代码: <form> <input type="text" /> <input type="checkbox" /> <input type="radio" /> <input type="image" /> <input type="file" /> <input type="submit" /> <input type="reset" /> <input type="password" /> <input type="button" /> <select><option/></select> <textarea></textarea> <button></button> </form> jQuery 代码: $(":file") 结果: [ <input type="file" /> ] :hidden:hidden 匹配所有不可见元素,或者type为hidden的元素 -------------------------------------------------------------------------------- Matches all elements that are hidden, or input elements of type "hidden". 返回值 Array<Element> 示例 查找隐藏的 tr HTML 代码: <table> <tr style="display:none"><td>Value 1</td></tr> <tr><td>Value 2</td></tr> </table> jQuery 代码: $("tr:hidden") 结果: [ <tr style="display:none"><td>Value 1</td></tr> ] -------------------------------------------------------------------------------- 匹配type为hidden的元素 HTML 代码: <form> <input type="text" name="email" /> <input type="hidden" name="id" /> </form> jQuery 代码: $("input:hidden") 结果: [ <input type="hidden" name="id" /> ] 表单对象属性 :enabled:enabled 匹配所有可用元素 -------------------------------------------------------------------------------- Matches all elements that are enabled. 返回值 Array<Element> 示例 查找所有可用的input元素 HTML 代码: <form> <input name="email" disabled="disabled" /> <input name="id" /> </form> jQuery 代码: $("input:enabled") 结果: [ <input name="id" /> ] :disabled:disabled 匹配所有不可用元素 -------------------------------------------------------------------------------- Matches all elements that are disabled. 返回值 Array<Element> 示例 查找所有不可用的input元素 HTML 代码: <form> <input name="email" disabled="disabled" /> <input name="id" /> </form> jQuery 代码: $("input:disabled") 结果: [ <input name="email" disabled="disabled" /> ] :checked:checked 匹配所有选中的复选框元素 -------------------------------------------------------------------------------- Matches all elements that are checked. 返回值 Array<Element> 示例 查找所有选中的复选框元素 HTML 代码: <form> <input type="checkbox" name="newsletter" checked="checked" value="Daily" /> <input type="checkbox" name="newsletter" value="Weekly" /> <input type="checkbox" name="newsletter" checked="checked" value="Monthly" /> </form> jQuery 代码: $("input:checked") 结果: [ <input type="checkbox" name="newsletter" checked="checked" value="Daily" />, <input type="checkbox" name="newsletter" checked="checked" value="Monthly" /> ] :selected:selected 匹配所有选中的选项元素 -------------------------------------------------------------------------------- Matches all elements that are selected. 返回值 Array<Element> 示例 查找所有选中的选项元素 HTML 代码: <select> <option value="1">Flowers</option> <option value="2" selected="selected">Gardens</option> <option value="3">Trees</option> </select> jQuery 代码: $("select option:selected") 结果: [ <option value="2" selected="selected">Gardens</option> ] -------------------------------------------------------------------------------- Finds all option elements that are selected. HTML 代码: <select multiple="multiple"> <option value="1">Flowers</option> <option value="2" selected="selected">Gardens</option> <option value="3" selected="selected">Trees</option> </select> jQuery 代码: $("select option:selected") 结果: [ <option value="2" selected="selected">Gardens</option>, <option value="3" selected="selected">Trees</option> ] 属性属性 attr(name)attr(name) 取得第一个匹配元素的属性值。通过这个方法可以方便地从第一个匹配元素中获取一个属性的值。如果元素没有相应属性,则返回 undefined 。 -------------------------------------------------------------------------------- Access a property on the first matched element. This method makes it easy to retrieve a property value from the first matched element. If the element does not have an attribute with such a name, undefined is returned. 返回值 Object 参数 name (String) : 属性名称 示例 返回文档中第一个图像的src属性值。 HTML 代码: <img src="test.jpg"/> jQuery 代码: $("img").attr("src"); 结果: test.jpg attr(properties)attr(properties) 将一个“名/值”形式的对象设置为所有匹配元素的属性。 这是一种在所有匹配元素中批量设置很多属性的最佳方式。 注意,如果你要设置对象的class属性,你必须使用'className' 作为属性名。或者你可以直接使用.addClass( class ) 和 .removeClass( class ). -------------------------------------------------------------------------------- Set a key/value object as properties to all matched elements. This serves as the best way to set a large number of properties on all matched elements. Note that you must use 'className' as key if you want to set the class-Attribute. Or use .addClass( class ) or .removeClass( class ). 返回值 jQuery 参数 properties (Map) : 作为属性的“名/值对”对象 示例 为所有图像设置src和alt属性。 HTML 代码: <img/> jQuery 代码: $("img").attr({ src: "test.jpg", alt: "Test Image" }); 结果: [ <img src= "test.jpg" alt:="Test Image" /> ] -------------------------------------------------------------------------------- attr(key,value)attr(key,value) 为所有匹配的元素设置一个属性值。 -------------------------------------------------------------------------------- Set a single property to a value, on all matched elements. 返回值 jQuery 参数 key (String) : 属性名称 value (Object) : 属性值 示例 为所有图像设置src属性。 HTML 代码: <img/> <img/> jQuery 代码: $("img").attr("src","test.jpg"); 结果: [ <img src= "test.jpg" /> , <img src= "test.jpg" /> ] attr(key,fn)attr(key,fn) 为所有匹配的元素设置一个计算的属性值。 不提供值,而是提供一个函数,由这个函数计算的值作为属性值。 -------------------------------------------------------------------------------- Set a single property to a computed value, on all matched elements. Instead of supplying a string value as described 'above', a function is provided that computes the value. 返回值 jQuery 参数 key (String) : 属性名称 fn (Function) : 返回值的函数 范围:当前元素, 参数: 当前元素的索引值 示例 把src属性的值设置为title属性的值。 HTML 代码: <img src="test.jpg"/> jQuery 代码: $("img").attr("title", function() { return this.src }); 结果: <img src="test.jpg" title="test.jpg" /> removeAttr(name)removeAttr(name) 从每一个匹配的元素中删除一个属性 -------------------------------------------------------------------------------- Remove an attribute from each of the matched elements. 返回值 jQuery 参数 name (String) : 要删除的属性名 示例 将文档中图像的src属性删除 HTML 代码: <img src="test.jpg"/> jQuery 代码: $("img").removeAttr("src"); 结果: [ <img /> ] 类 addClass(class)addClass(class) 为每个匹配的元素添加指定的类名。 -------------------------------------------------------------------------------- Adds the specified class(es) to each of the set of matched elements. 返回值 jQuery 参数 class (String) : 一个或多个要添加到元素中的CSS类名,请用空格分开 示例 为匹配的元素加上 'selected' 类 HTML 代码: <p>Hello</p> jQuery 代码: $("p").addClass("selected"); 结果: [ <p class="selected">Hello</p> ] -------------------------------------------------------------------------------- 为匹配的元素加上 selected highlight 类 HTML 代码: <p>Hello</p> jQuery 代码: $("p").addClass("selected highlight"); 结果: [ <p class="selected highlight">Hello</p> ] removeClass(class)removeClass(class) 从所有匹配的元素中删除全部或者指定的类。 -------------------------------------------------------------------------------- Removes all or the specified class(es) from the set of matched elements. 返回值 jQuery 参数 class (String) : (可选) 一个或多个要删除的CSS类名,请用空格分开 示例 从匹配的元素中删除 'selected' 类 HTML 代码: <p class="selected first">Hello</p> jQuery 代码: $("p").removeClass("selected"); 结果: [ <p>Hello</p> ] -------------------------------------------------------------------------------- 删除匹配元素的所有类 HTML 代码: <p class="selected first">Hello</p> jQuery 代码: $("p").removeClass(); 结果: [ <p>Hello</p> ] toggleClass(class)toggleClass(class) 如果存在(不存在)就删除(添加)一个类。 -------------------------------------------------------------------------------- Adds the specified class if it is not present, removes the specified class if it is present. 返回值 jQuery 参数 class (String) :CSS类名 示例 为匹配的元素切换 'selected' 类 HTML 代码: <p>Hello</p><p class="selected">Hello Again</p> jQuery 代码: $("p").toggleClass("selected"); 结果: [ <p class="selected">Hello</p>, <p>Hello Again</p> ] Html代码 html()html() 取得第一个匹配元素的html内容。这个函数不能用于XML文档。但可以用于XHTML文档。 -------------------------------------------------------------------------------- Get the html contents of the first matched element. This property is not available on XML documents (although it will work for XHTML documents). 返回值 String 示例 HTML 代码: <div><p>Hello</p></div> jQuery 代码: $("div").html(); 结果: Hello html(val)html(val) 设置每一个匹配元素的html内容。这个函数不能用于XML文档。但可以用于XHTML文档。 -------------------------------------------------------------------------------- Set the html contents of every matched element. This property is not available on XML documents (although it will work for XHTML documents). 返回值 jQuery 参数 val (String) : 用于设定HTML内容的值 示例 HTML 代码: <div></div> jQuery 代码: $("div").html("<p>Hello Again</p>"); 结果: [ <div><p>Hello Again</p></div> ] 文本 text()text() 取得所有匹配元素的内容。 结果是由所有匹配元素包含的文本内容组合起来的文本。这个方法对HTML和XML文档都有效。 -------------------------------------------------------------------------------- Get the text contents of all matched elements. The result is a string that contains the combined text contents of all matched elements. This method works on both HTML and XML documents. 返回值 String 示例 HTML 代码: <p><b>Test</b> Paragraph.</p><p>Paraparagraph</p> jQuery 代码: $("p").text(); 结果: Test Paragraph.Paraparagraph text(val)text(val) 设置所有匹配元素的文本内容 与 html() 类似, 但将编码 HTML (将 "<" 和 ">" 替换成相应的HTML实体). -------------------------------------------------------------------------------- Set the text contents of all matched elements. Similar to html(), but escapes HTML (replace "<" and ">" with their HTML entities). 返回值 jQuery 参数 val (String) : 用于设置元素内容的文本 示例 HTML 代码: <p>Test Paragraph.</p> jQuery 代码: $("p").text("<b>Some</b> new text."); 结果: [ <p><b>Some</b> new text.</p> ] 值 val()val() 获得第一个匹配元素的当前值。 在 jQuery 1.2 中,可以返回任意元素的值了。包括select。如果多选,将返回一个数组,其包含所选的值。 -------------------------------------------------------------------------------- Get the content of the value attribute of the first matched element. In jQuery 1.2, a value is now returned for all elements, including selects. For multiple selects an array of values is returned. 返回值 String,Array 示例 获得单个select的值和多选select的值。 HTML 代码: <p></p><br/> <select id="single"> <option>Single</option> <option>Single2</option> </select> <select id="multiple" multiple="multiple"> <option selected="selected">Multiple</option> <option>Multiple2</option> <option selected="selected">Multiple3</option> </select> jQuery 代码: $("p").append( "<b>Single:</b> " + $("#single").val() + " <b>Multiple:</b> " + $("#multiple").val().join(", ") ); 结果: [ <p><b>Single:</b>Single<b>Multiple:</b>Multiple, Multiple3</p>] -------------------------------------------------------------------------------- 获取文本框中的值 HTML 代码: <input type="text" value="some text"/> jQuery 代码: $("input").val(); 结果: some text val(val)val(val) 设置每一个匹配元素的值。 在 jQuery 1.2, 这也可以为select元件赋值 -------------------------------------------------------------------------------- Set the value attribute of every matched element. In jQuery 1.2, this is also able to set the value of select elements, but selecting the appropriate options. 返回值 jQuery 参数 val (String) : 要设置的值。 示例 设定文本框的值 HTML 代码: <input type="text"/> jQuery 代码: $("input").val("hello world!"); val(val)val(val) check,select,radio等都能使用为之赋值 返回值 jQuery 参数 val (Array<String>) : 用于 check/select 的值 示例 设定一个select和一个多选的select的值 HTML 代码: <select id="single"> <option>Single</option> <option>Single2</option> </select> <select id="multiple" multiple="multiple"> <option selected="selected">Multiple</option> <option>Multiple2</option> <option selected="selected">Multiple3</option> </select><br/> <input type="checkbox" value="check1"/> check1 <input type="checkbox" value="check2"/> check2 <input type="radio" value="radio1"/> radio1 <input type="radio" value="radio2"/> radio2 jQuery 代码: $("#single").val("Single2"); $("#multiple").val(["Multiple2", "Multiple3"]); $("input").val(["check2", "radio1"]); 筛选过滤 eq(index)eq(index) 获取第N个元素 这个元素的位置是从0算起。 -------------------------------------------------------------------------------- Reduce the set of matched elements to a single element. The position of the element in the set of matched elements starts at 0 and goes to length - 1. 返回值 jQuery 参数 index (Integer) :元素在jQuery对象中的索引 示例 获取匹配的第二个元素 HTML 代码: <p> This is just a test.</p> <p> So is this</p> jQuery 代码: $("p").eq(1) 结果: [ <p> So is this</p> ] hasClass(class)hasClass(class) 检查当前的元素是否含有某个特定的类,如果有,则返回true。 这其实就是 is("." + class)。 -------------------------------------------------------------------------------- Checks the current selection against a class and returns true, if at least one element of the selection has the given class. This is an alternative to is("." + class). 返回值 Boolean 参数 class (String) : 用于匹配的类名 示例 给包含有某个类的元素进行一个动画。 HTML 代码: <div class="protected"></div><div></div> jQuery 代码: $("div").click(function(){ if ( $(this).hasClass("protected") ) $(this) .animate({ left: -10 }) .animate({ left: 10 }) .animate({ left: -10 }) .animate({ left: 10 }) .animate({ left: 0 }); }); filter(expr)filter(expr) 筛选出与指定表达式匹配的元素集合。 这个方法用于缩小匹配的范围。用逗号分隔多个表达式 -------------------------------------------------------------------------------- Removes all elements from the set of matched elements that do not match the specified expression(s). This method is used to narrow down the results of a search. Provide a comma-separated list of expressions to apply multiple filters at once. 返回值 jQuery 参数 expr (Expression) : 表达式 示例 保留带有select类的元素 HTML 代码: <p>Hello</p><p>Hello Again</p><p class="selected">And Again</p> jQuery 代码: $("p").filter(".selected") 结果: [ <p class="selected">And Again</p> ] -------------------------------------------------------------------------------- 保留第一个以及带有select类的元素 HTML 代码: <p>Hello</p><p>Hello Again</p><p class="selected">And Again</p> jQuery 代码: $("p").filter(".selected, :first") 结果: [ <p>Hello</p>, <p class="selected">And Again</p> ] filter(fn)filter(fn) 筛选出与指定函数返回值匹配的元素集合 这个函数内部将对每个对象计算一次 (正如 '$.each'). 如果调用的函数返回false则这个元素被删除,否则就会保留。 -------------------------------------------------------------------------------- Removes all elements from the set of matched elements that does not match the specified function. The function is called with a context equal to the current element (just like '$.each'). If the function returns false, then the element is removed - anything else and the element is kept. 返回值 jQuery 参数 fn (Function) : 传递进filter的函数 示例 保留子元素中不含有ol的元素。 HTML 代码: <p><ol><li>Hello</li></ol></p><p>How are you?</p> jQuery 代码: $("p").filter(function(index) { return $("ol", this).length == 0; }); 结果: [ <p>How are you?</p> ] is(expr)is(expr) 用一个表达式来检查当前选择的元素集合,如果其中至少有一个元素符合这个给定的表达式就返回true。 如果没有元素符合,或者表达式无效,都返回'false'. 'filter' 内部实际也是在调用这个函数,所以,filter()函数原有的规则在这里也适用。 -------------------------------------------------------------------------------- Checks the current selection against an expression and returns true, if at least one element of the selection fits the given expression. If no element fits, or the expression is not valid, then the response will be 'false'. 'filter' is used internally, therefore all rules that apply there apply here, as well. 返回值 Boolean 参数 expr (String) :用于筛选的表达式 示例 由于input元素的父元素是一个表单元素,所以返回true。 HTML 代码: <form><input type="checkbox" /></form> jQuery 代码: $("input[type='checkbox']").parent().is("form") 结果: true map(callback)map(callback) 将一组元素转换成其他数组(不论是否是元素数组) 你可以用这个函数来建立一个列表,不论是值、属性还是CSS样式,或者其他特别形式。这都可以用'$.map()'来方便的建立。 -------------------------------------------------------------------------------- Translate a set of elements into another set of values (which may, or may not, be elements). You could use this to build lists of values, attributes, css values - or even perform special, custom, selector transformations. This is provided as a convenience method for using '$.map()'. 返回值 jQuery 参数 callback (Function) : 给每个元素执行的函数 示例 把form中的每
 数据的加密与解密  文件的加密与解密 第 章 加密与解密技术 第19章 加密与解密技术 829 19.1 数据的加密与解密 实例571 异或算法对数字进行加密与解密 光盘位置:光盘\MR\19\571 中级 趣味指数: 实 例说明 在实现本实例之前先来简要了解一下加密的概念,加密是指通过 某种特殊的方法,更改已有信息的内容,使得未授权的用户即使得到 了加密信息,如果没有正确解密的方法,也无法得到信息的内容。谈 到加密的话题,一些读者一定非常感兴趣,而且会联想到复杂的加密 算法,本实例主要使用异或“^”运算符简单地实现了对数字加密的 功能。实例运行效果如图19.1 所示。 关 键技术 本实例实现时主要使用了“异或”运算符对数字进行“异或”运 算,以达到简单加密数字的目的,下面对其进行详细讲解。 “异或”运算符“^”用于比较两个二进制数的相应位。在执行按位“异或”运算时,如果两个二进制数的 相应位都为1 或两个二进制数的相应位都为0,则返回0;如果两个二进制数的相应位其中一个为1 一个为0, 则返回1。 现在来了解一下使用“异或”加密或解密的执行过程,数值23 转换为二进制为10111,加密数字的数值15 转换为二进制为1111。对比两个二进制的值,从右向左按位对比,如果两个二进制数的相应位都为1 或两个二 进制数的相应位都为0,则返回0;如果两个二进制数的相应位中一个为1 一个为0,则返回1,最后得到的结 果为二进制值11000,该值转换为十进制为24,所以得到的加密结果为24。而解密过程也很简单,只是将加密 结果24与加密数字15 进行“异或”运算,将24 转换为二进制值11000,将15 转换为二进制值1111,进行“异 或”运算后,得到结果为23,这样又还原了加密的数据。  说明:本实例只是简单地使用了“异或”运算符计算两个整型数值以达到加密的目的,所以本实例只可以 对整型数值进行加密运算,并不适合其他数据的加密。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为Encrypt。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个GroupBox 容器控件,其中, 在第一个GroupBox 中放入3 个TextBox 控件和一个Button 按钮,分别用于输入数字、输入加密数字、显示加 密后的数字和计算加密信息;在第二个GroupBox 中放入一个TextBox 控件和一个Button 按钮,分别用于显示 解密后的信息和计算解密信息。 (3)程序主要代码如下: private void btn_Encrypt_Click(object sender, EventArgs e) { int P_int_Num, P_int_Key; //定义两个值类型变量 if (int.TryParse(txt_Num.Text, out P_int_Num) //判断输入是否是数值 && int.TryParse(txt_Key.Text, out P_int_Key)) { txt_Encrypt.Text = (P_int_Num ^ P_int_Key).ToString(); //加密数值 } else 图19.1 异或算法对数字进行加密与解密 C#开发实战1200 例(第II卷) 830 { MessageBox.Show("请输入数值", "出现错误!"); //提示输入信息不正确 } } private void btn_Revert_Click(object sender, EventArgs e) { int P_int_Key, P_int_Encrypt; //定义两个值类型变量 if (int.TryParse(txt_Encrypt.Text, out P_int_Key) //判断输入是否是数值 && int.TryParse(txt_Key.Text, out P_int_Encrypt)) { txt_Revert.Text = (P_int_Encrypt ^ P_int_Key).ToString(); //解密数值 } else { MessageBox.Show("请输入数值", "出现错误!"); //提示输入信息不正确 } } 秘 笈心法 心法领悟571:简述“异或”运算符。 本实例使用了“异或”运算符,但是在使用“异或”运算符之前,有必要了解“异或”运算符所做的“异 或”运算的机制,“异或”运算符“^”用于比较两个二进制数的相应位。在执行按位“异或”运算时,如果两 个二进制数的相应位都为1 或两个二进制数的相应位都为0,则返回0;如果两个二进制数的相应位中一个为1 一个为0,则返回1。 实例572 使用MD5算法加密数据 光盘位置:光盘\MR\19\572 中级 趣味指数: 实 例说明 MD5(Message-Digest Algorithm 5)是一种被广泛使用的“消息-摘要 算法”。“消息-摘要算法”实际上就是一个单项散列函数,数据块通过单 向散列函数得到一个固定长度的散列值,数据块的签名就是计算数据块的散 列值,MD5 算法的散列值为128 位。本实例演示如何使用MD5 算法对用户 输入的密码进行加密,实例运行效果如图19.2 所示。 关 键技术 本实例在实现时主要用到了MD5类的ComputeHash 方法,下面对其进行详细讲解。 MD5 类表示MD5 哈希算法的所有实现均从中继承的抽象类,该类位于System.Security.Cryptography 命名 空间下,其ComputeHash 方法有3种重载形式,分别介绍如下。  计算指定字节数组的哈希值,语法格式如下: public byte[] ComputeHash(byte[] buffer) 参数说明  buffer:要计算其哈希代码的输入。  返回值:计算所得的哈希代码。  计算指定Stream 对象的哈希值,语法格式如下: public byte[] ComputeHash(Stream inputStream) 参数说明  inputStream:要计算其哈希代码的输入。  返回值:计算所得的哈希代码。 图19.2 使用MD5 算法加密数据 第19章 加密与解密技术 831  计算指定字节数组的指定区域的哈希值,语法格式如下: public byte[] ComputeHash(byte[] buffer,int offset,int count) ComputeHash 方法中的参数及说明如表19.1 所示。 表19.1 ComputeHash方法中的参数及说明 参 数 说 明 buffer 要计算其哈希代码的输入 offset 字节数组中的偏移量,从该位置开始使用数据 count 数组中用作数据的字节数 返回值 计算所得的哈希代码  说明:本实例用到了ComputeHash 方法的第一种重载形式。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为MD5Arithmetic。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个TextBox 控件,分别用来输入 要加密的数据和显示加密后的字符串;添加一个Button 控件,用来使用MD5算法对输入的数据进行加密。 (3)程序主要代码如下: public string Encrypt(string strPwd) { MD5 md5 = new MD5CryptoServiceProvider(); //创建MD5 对象 byte[] data = System.Text.Encoding.Default.GetBytes(strPwd); //将字符编码为一个字节序列 byte[] md5data = md5.ComputeHash(data); //计算data字节数组的哈希值 md5.Clear(); //清空MD5 对象 string str = ""; //定义一个变量,用来记录加密后的密码 for (int i = 0; i < md5data.Length - 1; i++) //遍历字节数组 { str += md5data[i].ToString("x").PadLeft(2, '0'); //对遍历到的字节进行加密 } return str; //返回得到的加密字符串 } private void button1_Click(object sender, EventArgs e) { string P_str_Code = textBox1.Text; //记录要加密的密码 textBox2.Text = Encrypt(P_str_Code); //显示加密后的字符串 } 秘 笈心法 心法领悟572:如何判断是否为数字? 开发程序时,经常需要判断输入的字符串是否为数字,如判断输入的电话号码、货币金额和邮编等。在程 序中判断是否为数字的方法有很多种,可以使用正则表达式、int.Parse 方法和double.Parse 方法等。下面的代码 通过double.Parse 方法判断textBox1 文本框中的输入是否为数字。 double.Parse(textBox1.Text); 实例573 使用ROT13算法加密解密数据 光盘位置:光盘\MR\19\573 中级 趣味指数: 实 例说明 文件加密可以避免造成重要信息的泄漏,复杂的加密算法可以将信息加密得非常繁杂,但是对于一般的应 用,没有必要作类似于PGP、RSA 或DES 等复杂的加密算法。本实例介绍如何使用ROT13 算法加密和解密数 C#开发实战1200 例(第II卷) 832 据。实例运行效果如图19.3 所示。 图19.3 使用ROT13算法加密解密数据 关 键技术 本实例实现时,主要是用Convert 类的ToChar 方法来获取单个字符的Unicode 编码,然后将字母的前13 个和后13 个对调,从而实现加密的功能。下面对Convert类的ToChar 方法进行详细讲解。 ToChar 方法返回指定的Unicode字符值,并且不执行任何实际的转换,其语法格式如下: public static char ToChar (char value) 参数说明 value:一个Unicode 字符。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为ROT13Encrypt。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个TextBox 控件,分别用来显示 原始数据和解密后的数据;添加两个Button 控件,分别用来实现利用ROT13算法加密和解密数据的功能。 (3)程序主要代码如下: public string ROT13Encode(string InputText) { char tem_Character; //存储临时字符 int UnicodeChar; //存储临时字符的字节值 string EncodedText = ""; //存储加密或解密后的字符串 for (int i = 0; i = 97 && UnicodeChar = 110 && UnicodeChar = 65 && UnicodeChar = 78 && UnicodeChar <= 90) //对字符进行解密 { UnicodeChar = UnicodeChar - 13; } EncodedText = EncodedText + (char)UnicodeChar; //得到加密或解密字符串 } return EncodedText; //返回加密或解密后的字符串 } 秘 笈心法 心法领悟573:如何在字符串中查找指定字符? 在字符串中查找指定字符时,可以先将字符串显示在richTextBox 控件中,然后利用richTextBox 类的Find 方法在该控件中查找指定字符。在字符串中查找指定字符的代码如下: 第19章 加密与解密技术 833 M_int_index = richTextBox1.Find(textBox1.Text.Trim(), M_int_index, RichTextBoxFinds.MatchCase); if (M_int_index == -1) { MessageBox.Show("没有要查找的字符串", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); M_int_index = 0; } else M_int_index = M_int_index + textBox1.Text.Trim().Length; richTextBox1.Focus(); 实例574 使用恺撒密码算法加密密码 光盘位置:光盘\MR\19\574 中级 趣味指数: 实 例说明 恺撒密码据传是古罗马恺撒大帝用来保护重要军情的加密系统,它 是一种置换密码,通过将字母顺序推后起到加密作用。例如,将字母顺 序推后3 位,字母A 将被推作为字母D,字母B 将被推作字母E。本实 例使用C#实现了恺撒加密的算法,实例运行效果如图19.4 所示。 关 键技术 本实例实现时主要用到了string 类的ToCharArray 方法和Convert 类的ToChar 方法,下面分别对它们进行 详细介绍。 (1)string类的ToCharArray 方法 string类的ToCharArray 方法用来将字符串中的字符复制到Unicode 字符数组,该方法有两种重载形式,本 实例中用到的它的重载形式如下: public char[] ToCharArray() 参数说明 返回值:元素为此字符串的各字符的Unicode 字符数组。如果此字符串是空字符串,则返回的数组为空且 长度为零。 (2)Convert 类的ToChar 方法 Convert 类的ToChar 方法用来将指定的值转换为Unicode 字符,该方法为可重载方法,本实例中用到的它 的重载形式如下: public static char ToChar(int value) 参数说明  value:32 位有符号整数。  返回值:等效于value 的值的Unicode 字符。 设 计过程 (1)打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为CaesarArithmetic。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个TextBox 控件,分别用来输入 要加密的数据和显示加密后的字符串;添加一个Button 控件,用来使用恺撒密码算法对输入的数据进行加密。 (3)程序主要代码如下: public int AscII(string str) //获取字符的ASCII 码 { byte[] array = new byte[1]; //创建字节数组 array = System.Text.Encoding.ASCII.GetBytes(str); //为字节数组赋值 int asciicode = (short)(array[0]); //获取字节数组的第一项 return asciicode; //返回字节数组的第一项 } 图19.4 使用恺撒密码算法加密密码 C#开发实战1200 例(第II卷) 834 public string Caesar(string str) //凯撒加密算法的实现 { char[] c = str.ToCharArray(); //创建字符数组 string strCaesar = ""; //定义一个变量,用来存储加密后的字符串 for (int i = 0; i < str.Length; i++) //遍历字符串中的每一个字符串 { string ins = c[i].ToString(); //记录遍历到的字符 string outs = ""; //定义一个变量,用来记录加密后的字符串 bool isChar = "0123456789abcdefghijklmnopqrstuvwxyz".Contains(ins.ToLower()); //判断指定的字符串中是否包含遍历到的字符 bool isToUpperChar = isChar && (ins.ToUpper() == ins); //判断遍历到的字符是否是大写 ins = ins.ToLower(); //将遍历到的字符转换为小写 if (isChar) //判断指定的字符串中是否包含遍历到的字符 { int offset = (AscII(ins) + 5 - AscII("a")) % (AscII("z") - AscII("a") + 1); //获取字符的ASCII 码 outs = Convert.ToChar(offset + AscII("a")).ToString(); //转换为字符并记录 if (isToUpperChar) //判断是否大写 { outs = outs.ToUpper(); //全部转换为大写 } } else { outs = ins; //记录遍历的字符 } strCaesar += outs; //添加到加密字符串中 } return strCaesar; //返回加密后的字符串 } 秘 笈心法 心法领悟574:如何将新字符串添加到已有字符串中? 将新字符串添加到已有字符串中时,可以先声明一个StringBuilder类对象,以指定已有字符串的长度可变, 然后利用该对象的Append方法在字符串中添加指定字符串。将新字符串添加到已有字符串的代码如下: StringBuilder strbuilder = new StringBuilder(textBox1.Text.Trim()); strbuilder.Append(textBox2.Text.Trim()); textBox3.Text = strbuilder.ToString(); 实例575 对数据报进行加密保障通信安全 光盘位置:光盘\MR\19\575 高级 趣味指数: 实 例说明 网络传输数据时,有时候传输信息容易被不法分子截获而 用作其他用途。这样,如果传输的数据中包含有重要秘密,将 会造成非常严重的后果。为了防止这种情况的发生,可以对网 络中传输的数据进行加密,用户接收到数据后再进行解密查看, 这样可以更好地保障网络通信安全。运行本实例,首先设置端 口号,然后在窗体左下方的文本框中输入聊天信息,单击“发 送”按钮,向局域网中发送聊天信息,同时在右侧的“数据传 输信息”栏中显示数据报的发送、接收及丢失情况。实例运行 效果如图19.5 所示。 关 键技术 本实例获取数据报信息时主要用到IPGlobalProperties和UdpStatistics类,而在对数据报加密时用到DESCrypto 图19.5 对数据报进行加密保障通信安全 第19章 加密与解密技术 835 ServiceProvider 和CryptoStream 类,其中DESCryptoServiceProvider 继承于DES 类。下面对本实例中用到的关 键技术进行详细讲解。 (1)IPGlobalProperties 类 IPGlobalProperties 类提供有关本地计算机的网络连接的信息,本实例中用到它的GetIPGlobalProperties 和 GetUdpIPv4Statistics 方法,下面分别进行介绍。 GetIPGlobalProperties 为静态方法,主要用来获取一个对象,该对象提供有关本地计算机的网络连接和通信 统计数据的信息,其语法格式如下: public static IPGlobalProperties GetIPGlobalProperties() 参数说明 返回值:IPGlobalProperties 对象,该对象包含有关本地计算机的信息。 GetUdpIPv4Statistics 方法主要用来提供本地计算机的用户数据报协议/Internet 协议版本4 (UDP/IPv4)统 计数据,其语法格式如下: public abstract UdpStatistics GetUdpIPv4Statistics() 参数说明 返回值:UdpStatistics 对象,提供本地计算机的UDP/IPv4通信统计数据。 例如,本实例中创建IPGlobalProperties 对象,及调用其GetUdpIPv4Statistics 方法创建UdpStatistics 对象的 代码如下: IPGlobalProperties NetInfo = IPGlobalProperties.GetIPGlobalProperties(); UdpStatistics myUdpStat = null; myUdpStat = NetInfo.GetUdpIPv4Statistics(); (2)UdpStatistics类 UdpStatistics 类提供用户数据报协议(UDP)统计数据,本实例中主要用到其DatagramsSent 属性、 DatagramsReceived属性和IncomingDatagramsDiscarded 属性,其中,DatagramsSent 属性用来获取已发送的用户 数据报协议(UDP)数据报的数量,DatagramsReceived 属性用来获取已接收的用户数据报协议(UDP)数据报 的数量,IncomingDatagramsDiscarded 属性用来获取已收到但因端口错误而丢弃的用户数据报协议(UDP)数据 报的数量。 例如,本实例中初始化已发送、已接收和丢失数据报的实现代码如下: SendNum1 = Int32.Parse(myUdpStat.DatagramsSent.ToString()); //记录发送的数据报 ReceiveNum1 = Int32.Parse(myUdpStat.DatagramsReceived.ToString()); //记录接收的数据报 DisNum1 = Int32.Parse(myUdpStat.IncomingDatagramsDiscarded.ToString()); //记录丢失的数据报  说明:IPGlobalProperties 类和UdpStatistics 类位于System.Net.NetworkInformation 命名空间下。 (3)DES 类 DES 类表示所有DES 实现都必须从中派生的数据加密标准(DES)算法的基类,其CreateEncryptor 方法和 CreateDecryptor 方法分别用来加密和解密。 CreateEncryptor 方法使用指定的Key属性和初始化向量(IV)创建对称加密器对象,其语法格式如下: public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey,byte[] rgbIV) 参数说明  rgbKey:用于对称算法的密钥。  rgbIV:用于对称算法的初始化向量。  返回值:对称加密器对象。 CreateDecryptor 方法使用指定的Key属性和初始化向量(IV)创建对称解密器对象,其语法格式如下: public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey,byte[] rgbIV) 参数说明  rgbKey:用于对称算法的密钥。  rgbIV:用于对称算法的初始化向量。  返回值:对称解密器对象。 C#开发实战1200 例(第II卷) 836 (4)CryptoStream 类 CryptoStream 类定义将数据流链接到加密转换的流,其构造函数的语法格式如下: public CryptoStream(Stream stream,ICryptoTransform transform,CryptoStreamMode mode) 参数说明  stream:对其执行加密转换的流。  transform:要对流执行的加密转换。  mode:CryptoStreamMode 枚举值之一,CryptoStreamMode 枚举值及说明如表19.2 所示。 表19.2 CryptoStreamMode枚举值及说明 枚 举 值 说 明 Read 对加密流的读访问 Write 对加密流的写访问 另外,在向加密或解密流中写入数据时用到CryptoStream 类的Write 方法,该方法将一个字节序列写入当 前CryptoStream,并将流中的当前位置提升写入的字节数,其语法格式如下: public override void Write(byte[] buffer,int offset,int count) 参数说明  buffer:字节数组,此方法将count 个字节从buffer 复制到当前流。  offset:buffer 中的字节偏移量,从此偏移量开始将字节复制到当前流。  count:要写入当前流的字节数。  说明:DES 类和CryptoStream 类位于System.Security.Cryptography 命名空间下。 设 计过程 (1)打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为EncryptDataReport。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个RichTextBox 控件,分别用来 输入聊天信息和显示聊天信息;添加4 个TextBox 控件,分别用来输入端口号和显示已发送数据报、已接收数 据报、丢失数据报;添加4 个Button 控件,分别用来执行设置端口号、发送聊天信息、清空聊天信息和关闭应 用程序操作。 (3)程序主要代码如下。 Frm_Main 窗体的后台代码中,首先创建程序所需要的.NET 对象及公共变量,代码如下: #region 定义全局对象及变量 private IPEndPoint Server; //服务器端 private IPEndPoint Client; //客户端 private Socket mySocket; //套接字 private EndPoint ClientIP; //IP地址 byte[] buffer, data; //接收缓存 bool blFlag = true; //标识是否第一次发送信息 bool ISPort = false; //判断端口打开 int SendNum1, ReceiveNum1, DisNum1; //记录窗体加载时的已发送\已接收\丢失的数据报 int SendNum2, ReceiveNum2, DisNum2; //记录当前已发送\已接收\丢失的数据报 int SendNum3, ReceiveNum3, DisNum3; //缓存已发送\已接收\丢失的数据报 int port; //端口号 #endregion Frm_Main 窗体加载时,初始化已发送、已接收和丢失的数据报,并使用全局变量记录,实现代码如下: //初始化已发送、已接收和丢失的数据报 private void Form1_Load(object sender, EventArgs e) { if (blFlag == true) { IPGlobalProperties NetInfo = IPGlobalProperties.GetIPGlobalProperties(); //创建一个IPGlobalProperties 对象 UdpStatistics myUdpStat = null; //声明UdpStatistics 对象 myUdpStat = NetInfo.GetUdpIPv4Statistics(); //创建UdpStatistics 对象 第19章 加密与解密技术 837 SendNum1 = Int32.Parse(myUdpStat.DatagramsSent.ToString()); //记录发送的数据报 ReceiveNum1 = Int32.Parse(myUdpStat.DatagramsReceived.ToString()); //记录接收的数据报 DisNum1 = Int32.Parse(myUdpStat.IncomingDatagramsDiscarded.ToString()); //记录丢失的数据报 } } 单击“设置”按钮,使用指定的端口号连接服务器端与客户端,并开始接收消息。“设置”按钮的Click 事件的代码如下: private void button4_Click(object sender, EventArgs e) //设置端口号 { try { port = Convert.ToInt32(textBox4.Text); //记录端口号 CheckForIllegalCrossThreadCalls = false; //指定线程中可以调用窗体的控件对象 buffer = new byte[1024]; data = new byte[1024]; Server = new IPEndPoint(IPAddress.Any, port); //创建服务器端 Client = new IPEndPoint(IPAddress.Broadcast, port); //创建客户端 ClientIP = (EndPoint)Server; //获取服务器端IP 地址 //创建Socket 对象 mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //设置Socket 网络操作 mySocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); mySocket.Bind(Server); //绑定服务器端 //开始接收消息 mySocket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref ClientIP, new AsyncCallback(StartLister), null); ISPort = true; //打开指定端口号 } catch { } } 单击“发送”按钮,首先判断是否有打开的端口,如果没有,弹出提示信息,否则根据发送和接收的消息 计算已发送、已接收和丢失的数据报,并显示在相应的文本框中,然后使用DES对要发送的消息进行加密发送。 “发送”按钮的Click事件的代码如下: //发送信息 private void button2_Click(object sender, EventArgs e) { if (ISPort == true) //判断是否有打开的端口号 { IPGlobalProperties NetInfo = IPGlobalProperties.GetIPGlobalProperties(); UdpStatistics myUdpStat = null; myUdpStat = NetInfo.GetUdpIPv4Statistics(); try { if (blFlag == false) //非第一次发送 { SendNum2 = Int32.Parse(myUdpStat.DatagramsSent.ToString()); ReceiveNum2 = Int32.Parse(myUdpStat.DatagramsReceived.ToString()); DisNum2 = Int32.Parse(myUdpStat.IncomingDatagramsDiscarded.ToString()); textBox1.Text = Convert.ToString(SendNum2 - SendNum3); textBox2.Text = Convert.ToString(ReceiveNum2 - ReceiveNum3); textBox3.Text = Convert.ToString(DisNum2 - DisNum3); } SendNum2 = Int32.Parse(myUdpStat.DatagramsSent.ToString()); ReceiveNum2 = Int32.Parse(myUdpStat.DatagramsReceived.ToString()); DisNum2 = Int32.Parse(myUdpStat.IncomingDatagramsDiscarded.ToString()); SendNum3 = SendNum2; //记录本次的发送数据报 ReceiveNum3 = ReceiveNum2; //记录本次的接收数据报 DisNum3 = DisNum2; //记录本次的丢失数据报 if (blFlag == true) //第一次发送 { textBox1.Text = Convert.ToString(SendNum2 - SendNum1); textBox2.Text = Convert.ToString(ReceiveNum2 - ReceiveNum1); textBox3.Text = Convert.ToString(DisNum2 - DisNum1); blFlag = false; C#开发实战1200 例(第II卷) 838 } } catch (Exception ex) { MessageBox.Show(ex.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information); } string str = EncryptDES(rtbSend.Text, "mrsoftxk"); //加密要发送的信息 data = Encoding.Unicode.GetBytes(str); mySocket.SendTo(data, data.Length, SocketFlags.None, Client); //发送消息 rtbSend.Text = ""; } else { MessageBox.Show("请首先打开端口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); button4.Focus(); } } 上面的代码中用到了EncryptDES 方法,该方法为自定义的、返回值类型为string 的方法,主要用来使用 DES 加密数据报,它有两个string 类型的参数,分别用来表示待加密的字符串和加密密钥,返回值为加密后的 字符串。EncryptDES 方法的实现代码如下: #region DES 加密字符串 /// ///DES 加密字符串 /// ///待加密的字符串 ///加密密钥,要求为8 位 ///加密成功返回加密后的字符串,失败返回源字符串 public string EncryptDES(string str, string key) { try { byte[] rgbKey = Encoding.UTF8.GetBytes(key.Substring(0, 8)); //将加密密钥转换为字节数组 byte[] rgbIV = Keys; //记录原始密钥数组 byte[] inputByteArray = Encoding.UTF8.GetBytes(str); //将加密字符串转换为字节数组 DESCryptoServiceProvider myDES = new DESCryptoServiceProvider(); //创建加密对象 MemoryStream MStream = new MemoryStream(); //创建内存数据流 //创建加密流对象 CryptoStream CStream = new CryptoStream(MStream, myDES.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write); CStream.Write(inputByteArray, 0, inputByteArray.Length); //向加密流中写入数据 CStream.FlushFinalBlock(); //释放加密流对象 return Convert.ToBase64String(MStream.ToArray()); //返回内存流中的数据 } catch { return str; } } #endregion 秘 笈心法 心法领悟575:如何根据标点符号分行? 根据标点符号分行时,首先要使用string 类的Split 方法分割字符串,然后再通过“\n”回车换行符将分割 的字符串换行显示。根据标点符号分行的代码如下: string oldstr = textBox1.Text.Trim(); string[] newstr = oldstr.Split('。'); for (int i = 0; i < newstr.Length; i++) { if (richTextBox1.Text == "") richTextBox1.Text = newstr[i].ToString(); else richTextBox1.Text += "\n" + newstr[i].ToString(); } 第19章 加密与解密技术 839 实例576 使用one-time pad算法加密数据 光盘位置:光盘\MR\19\576 高级 趣味指数: 实 例说明 在密码学里,有一种理想的加密方案,叫做一次一密乱码本,即 one-time pad 算法,该算法是最安全的加密算法,双方一旦安全交换 了密钥,之后交换信息的过程就可以保证绝对安全。本实例使用C# 实现了one-time pad 加密算法,实例运行效果如图19.6 所示。  注意:程序中使用one-time pad 算法时,一定要保证密钥和密文 的长度是一样的。 关 键技术 本实例在实现one-time pad 加密算法时,主要用到了Encoding 类的GetBytes 方法和GetString 方法,下面 分别对它们进行详细介绍。 (1)Encoding 类的GetBytes方法 Encoding 类表示字符编码,其GetBytes方法主要用来将一组字符编码为一个字节序列,该方法为可重载方 法,本实例中用到的它的重载形式如下: public virtual byte[] GetBytes(string s) 参数说明  s:字符串。  返回值:一个字节数组,包含对指定的字符集进行编码的结果。  说明:Encoding 类位于System.Text 命名空间下。 (2)Encoding 类的GetString方法 Encoding 类的GetString方法主要用来将一个字节序列解码为一个字符串,该方法为可重载方法,本实例中 用到的它的重载形式如下: public virtual string GetString(byte[] bytes) 参数说明  bytes:包含要解码的字节序列的字节数组。  返回值:包含指定字节序列解码结果的字符串。 设 计过程 (1) 打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为OneTimePadArithmetic。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加4 个TextBox 控件,分别用来输入 要加密的数据和密钥,以及显示加密后的数据和解密后的数据;添加两个Button控件,分别用来实现使用one-time pad 算法加密数据和解密数据的功能。 (3)程序主要代码如下。 在Frm_Main 窗体中输入要加密的数据和密钥后,单击“加密”按钮,使用one-time pad 算法对输入的数据 进行加密,实现代码如下: private void button1_Click(object sender, EventArgs e) { textBox2.Text = ""; //清空文本框 Encoding encoding = Encoding.Default; //获取字符编码 byte[] btData = encoding.GetBytes(textBox1.Text); //将要加密的数据转换为字节数组 byte[] btKey = encoding.GetBytes(textBox4.Text); //将密钥转换为字节数组 图19.6 使用one-time pad 算法加密数据 C#开发实战1200 例(第II卷) 840 if (btData.Length == btKey.Length) //判断长度是否相等 { byte[] btEncrypt = Encrypt(btData, btKey); //加密数据 for (int i = 0; i < btEncrypt.Length; i++) //遍历加密后的字节数组 { textBox2.Text += btEncrypt[i]; //显示在文本框中 } } } 上面的代码中用到了Encrypt 方法,该方法为自定义的、返回值类型为byte[]的方法,主要用来对指定的数 据使用one-time pad 算法进行加密。Encrypt方法的实现代码如下: public static byte[] Encrypt(byte[] btData, byte[] btKey) { if (btKey.Length != btData.Length) //判断长度是否相等 { MessageBox.Show("请确保要加密数据的长度与密钥的长度一致!"); } byte[] btResult = new byte[btData.Length]; //声明一个字节数组,用来存储加密数据 for (int i = 0; i < btResult.Length; ++i) //遍历字节数组 { btResult[i] = (byte)(btKey[i] ^ btData[i]); //为字节数组赋值 } return btResult; //返回得到的加密数据 } 单击“解密”按钮,调用Encrypt 方法对加密过的数据进行逆向加密,并返回一个byte[]数组,然后使用 Encoding 类的GetString方法从该数组中获取解密字符串。“解密”按钮的Click事件的代码如下: private void button2_Click(object sender, EventArgs e) { Encoding encoding = Encoding.Default; //获取字符编码 byte[] btData = encoding.GetBytes(textBox1.Text); //将要加密的数据转换为字节数组 byte[] btKey = encoding.GetBytes(textBox4.Text); //将密钥转换为字节数组 if (btData.Length == btKey.Length) //判断长度是否相等 { byte[] btDecrypt = Encrypt(Encrypt(btData, btKey), btKey); //解密数据 textBox3.Text = encoding.GetString(btDecrypt); //将解密后的字节数组转换为字符串并显示 } } 秘 笈心法 心法领悟576:如何在字符串中添加多个空格? 开发程序时,有时会根据需要在字符串中添加一些空格,这时可以使用string 类的Insert方法,该方法可以 在字符串中的指定位置插入一个新的字符串(包括空格)。在字符串中添加空格的代码如下: textBox3.Text = textBox1.Text.Insert(Convert.ToInt32(textBox2.Text.Trim()), " "); 实例577 使用伪随机数加密技术加密用户登录密码 光盘位置:光盘\MR\19\577 高级 趣味指数: 实 例说明 为了保障用户登录密码的安全,本实例使用伪随机数技术对用 户的登录密码进行加密,运行本实例,当用户在“登录密码”文本 框中输入登录密码时,程序会自动将使用过伪随机数加密技术加密 过的登录密码显示在下面的“加密密码”文本框中,单击“登录” 按钮,程序对“加密密码”文本框中的加密数据进行解密,然后再 与用户输入的登录密码相比较,如果相同,则登录成功;否则,登 录失败。实例运行效果如图19.7 所示。 图19.7 使用伪随机数加密技术 加密用户登录密码 第19章 加密与解密技术 841 关 键技术 本实例对用户登录密码加密时用到伪随机数加密技术,伪随机数加密技术实质上就是通过伪随机数序列使 登录密码字符串的字节值发生变化而产生密文,由于相同的初值能得到相同的随机数序列,因此,可以采用同 样的伪随机数序列来对密文进行解密。产生伪随机数时主要用到Random 类,该类表示伪随机数生成器,它是 一种能够产生满足某些随机性统计要求的数字序列的设备,其Next方法用来返回随机数,语法格式如下: public virtual int Next(int maxValue) 参数说明  maxValue:要生成的随机数的上界(随机数不能取该上界值),maxValue 必须大于等于零。  返回值:大于等于零且小于maxValue 的32 位带符号整数,即返回值的范围通常包括零但不包括 maxValue;不过,如果maxValue 等于零,则返回maxValue。 设 计过程 (1)打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为PRanDataEncrypt。 (2)更改默认窗体Form1 的Name属性为Frm_Main,在该窗体中添加3 个TextBox 控件,分别用来输入 登录用户、登录密码和显示加密密码;添加两个Button 控件,分别用来执行用户登录和清空文本框操作。 (3)程序主要代码如下。 Frm_Main 窗体的后台代码中,首先定义加密用户密码所用的伪随机数,代码如下: //定义加密用户密码所用的伪随机数 private string randStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; 当在“登录密码”文本框中输入登录密码时,实时将使用伪随机数加密过的登录密码显示在“加密密码” 文本框中,实现代码如下: private void textBox2_TextChanged(object sender, EventArgs e) { textBox3.Text = EncryptPwd(textBox2.Text); //显示加密后的用户登录密码 } 上面的代码中用到EncryptPwd 方法,该方法为自定义的、返回值类型为string 的方法,主要用来使用伪随 机数技术加密用户登录密码,它有一个参数,用来表示用户登录密码。EncryptPwd 方法的实现代码如下: /// /// 使用伪随机数加密用户登录密码 /// /// 用户登录密码 /// 加密后的用户登录密码 private string EncryptPwd(string str) { byte[] btData = Encoding.Default.GetBytes(str); //将登录密码转换为字节数组 int j, k, m; int len = randStr.Length; //记录伪随机数长度 StringBuilder sb = new StringBuilder(); //创建StringBuilder对象 Random rand = new Random(); //创建Random 对象 for (int i = 0; i < btData.Length; i++) { j = (byte)rand.Next(6); //产生伪随机数 btData[i] = (byte)((int)btData[i] ^ j); //使用伪随机数对密码字节数组进行移位 k = (int)btData[i] % len; m = (int)btData[i] / len; m = m * 8 + j; sb.Append(randStr.Substring(k, 1) + randStr.Substring(m, 1)); //组合加密字符串 } return sb.ToString(); //返回生成的加密字符串 } 单击“登录”按钮,判断“加密密码”文本框是否为空。如果不为空,调用DecryptPwd 方法解密“加密 密码”文本框中的字符串;然后使用解密后的字符串与“登录密码”文本框中的字符串相比较,如果相同,则 用户登录成功;否则,弹出提示信息。“登录”按钮的Click事件代码如下: C#开发实战1200 例(第II卷) 842 private void button1_Click(object sender, EventArgs e) { if (textBox3.Text != "") { if (DecryptPwd(textBox3.Text) == textBox2.Text) //对加密过的登录密码进行解密 MessageBox.Show("用户登录成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); else MessageBox.Show("用户密码错误!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } 上面的代码中用到了DecryptPwd 方法,该方法为自定义的、返回值类型为string 的方法,主要用来解密用 户登录密码,它有一个参数,主要用来表示经过加密的用户登录密码。DecryptPwd 方法的实现代码如下: /// /// 解密用户登录密码 /// /// 经过加密的用户登录密码 /// 解密后的用户登录密码 private string DecryptPwd(string str) { try { int j, k, m, n = 0; int len = randStr.Length; //获取伪随机数长度 byte[] btData = new byte[str.Length / 2]; //定义一个字节数组,并指定长度 for (int i = 0; i < str.Length; i += 2) //对登录密码进行解密 { k = randStr.IndexOf(str[i]); m = randStr.IndexOf(str[i + 1]); j = m / 8; m = m - j * 8; btData[n] = (byte)(j * len + k); btData[n] = (byte)((int)btData[n] ^ m); n++; } return Encoding.Default.GetString(btData); //返回解密后的登录密码 } catch { return ""; } } 秘 笈心法 心法领悟577:如何将字符串颠倒输出? 颠倒输出字符串时,可以先将要输出的字符串保存到一个char 类型的数组中,然后使用Array 类的Reverse 方法。将字符串颠倒输出的代码如下: string str1 = textBox1.Text.Trim(); char[] charstr = str1.ToCharArray(); Array.Reverse(charstr); string str2 = new string(charstr); textBox2.Text = str2; 实例578 以XML格式导入导出密钥 光盘位置:光盘\MR\19\578 高级 趣味指数: 实 例说明 本实例主要实现以XML 格式导入导出密钥,从而实现对数据进行加密和解密的功能。运行本实例,首先 在窗体中显示生成的公钥和私钥,然后输入明文数据,单击“加密”按钮,对输入的明文数据进行加密;单击 “解密”按钮,对加密后的数据进行解密。实例运行效果如图19.8 所示。 第19章 加密与解密技术 843 图19.8 以XML 格式导入导出密钥 关 键技术 本实例实现时主要用到了RSACryptoServiceProvider 类的ToXmlString方法、Encrypt 方法和Decrypt 方法, 下面对本实例中用到的关键技术进行详细讲解。 (1)RSACryptoServiceProvider 类的ToXmlString方法 RSACryptoServiceProvider 类用来使用加密服务提供程序(CSP)提供的RSA 算法的实现执行不对称加密和 解密,其ToXmlString 方法主要用来创建并返回包含当前RSA 对象的密钥的XML 字符串,该方法的语法格式 如下: public override string ToXmlString(bool includePrivateParameters) 参数说明  includePrivateParameters:true 表示同时包含RSA公钥和私钥,false 表示仅包含公钥。  返回值:包含当前RSA对象的密钥的XML字符串。  说明:RSACryptoServiceProvider 类位于System.Security.Cryptography 命名空间下。 (2)RSACryptoServiceProvider 类的Encrypt方法 该方法主要使用RSA算法对数据进行加密,其语法格式如下: public byte[] Encrypt(byte[] rgb,bool fOAEP) 参数说明  rgb:要加密的数据。  fOAEP:如果为true,则使用OAEP 填充(仅在运行Microsoft Windows XP 或更高版本的计算机上可用) 执行直接的RSA 加密;如果为false,则使用PKCS#1 1.5 版填充。  返回值:字节数组,表示已加密的数据。 (3)RSACryptoServiceProvider 类的Decrypt方法 该方法主要使用RSA算法对数据进行解密,其语法格式如下: public byte[] Decrypt(byte[] rgb,bool fOAEP) 参数说明  rgb:要解密的数据。  fOAEP:如果为true,则使用OAEP 填充(仅在运行Microsoft Windows XP 或更高版本的计算机上可用) 执行直接的RSA 解密;如果为false,则使用PKCS#1 1.5 版填充。  返回值:字节数组,表示已解密的数据,它是加密前的原始纯文本。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为KeyToXML。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加5 个TextBox 控件,分别用来显示 C#开发实战1200 例(第II卷) 844 公钥、显示私钥、输入明文数据、显示加密后的数据和显示解密后的数据;添加两个Button 控件,分别用来执 行数据加密和解密操作。 (3)程序主要代码如下。 在Frm_Main 窗体的后台代码中,首先创建RSACryptoServiceProvider 对象,并且定义一个字节数组,用来 存储临时数据,代码如下: RSACryptoServiceProvider RSACrypto = new RSACryptoServiceProvider(); //创建RSA 算法加密解密对象 byte[] M_bt_Data; //定义一个字节数组,用来存储临时数据 Frm_Main 窗体加载时,在文本框中显示程序自动生成的公钥和私钥数据,代码如下: private void Frm_Main_Load(object sender, EventArgs e) { this.textBox1.Text = RSACrypto.ToXmlString(true); //显示生成的公钥 this.textBox2.Text = RSACrypto.ToXmlString(false); //显示生成的私钥 } 当用户输入明文数据之后,单击“加密”按钮,调用RSACryptoServiceProvider 类的Encrypt方法对数据进 行加密,并且使用Encoding 类的UTF8 编码方式的GetString 方法得到加密后的数据,显示在文本框中。“加密” 按钮的Click事件代码如下: private void button1_Click(object sender, EventArgs e) { if (textBox3.Text != "") //判断是否输入了要加密的数据 { byte[] P_bt_Encrypt = Encoding.UTF8.GetBytes(textBox3.Text); //将要加密的数据转换为字节数组 M_bt_Data = RSACrypto.Encrypt(P_bt_Encrypt, false); //加密数据 textBox4.Text = Encoding.UTF8.GetString(M_bt_Data); //显示加密数据 } } 单击“解密”按钮,调用RSACryptoServiceProvider 类的Decrypt方法对加密过的数据进行解密,并且使用 Encoding 类的UTF8 编码方式的GetString 方法得到解密后的数据,显示在文本框中。“解密”按钮的Click 事 件代码如下: private void button2_Click(object sender, EventArgs e) { if (textBox4.Text != "") //判断是否有加密过的数据 { byte[] P_bt_Decrypt = RSACrypto.Decrypt(M_bt_Data, false); //对数据进行解密 textBox5.Text = Encoding.UTF8.GetString(P_bt_Decrypt); //显示解密数据 } } 秘 笈心法 心法领悟578:如何判断字符串是否为日期格式? 判断字符串是否为日期格式时,可以使用正则表达式。验证日期格式的正则表达式主要有以下3 种: \b(?\d{2,4})/(?\d{1,2})/(?\d{1,2})\b 或 \b(?\d{2,4})-(?\d{1,2})-(?\d{1,2})\b 或 \b(?\d{2,4})年(?\d{1,2})月(?\d{1,2})日\b 实例579 以参数格式导入导出密钥 光盘位置:光盘\MR\19\579 高级 趣味指数: 实 例说明 本实例主要实现以参数格式导入导出密钥,从而实现对数据进行加密和解密的功能。运行本实例,在窗体 第19章 加密与解密技术 845 中输入明文数据,单击“加密”按钮,对输入的明文数据进行加密;单击“解 密”按钮,对加密后的数据进行解密。实例运行效果如图19.9 所示。 关 键技术 本实例实现时主要用到了RSACryptoServiceProvider 类的ExportParameters 方法、ImportParameters 方法、Encrypt 方法和Decrypt 方法,下面对本实例 中用到的关键技术进行详细讲解。 (1)RSACryptoServiceProvider 类的ExportParameters 方法 该方法主要用来导出RSAParameters标准参数,其语法格式如下: public override RSAParameters ExportParameters(bool includePrivateParameters) 参数说明  includePrivateParameters:如果要包括私有参数,则为true;否则为false。  返回值:RSA 算法的标准参数。 (2)RSACryptoServiceProvider 类的ImportParameters 方法 该方法主要用来导入指定的RSAParameters标准参数,其语法格式如下: public override void ImportParameters(RSAParameters parameters) 参数说明 parameters:RSA 算法的标准参数。  说明:关于RSACryptoServiceProvider 类的Encrypt 方法和Decrypt 方法的详细讲解,请参见实例578 中的 关键技术。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为KeyToParameter。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加3 个TextBox 控件,分别用来输入 明文数据、显示加密后的数据和解密后的数据;添加两个Button 控件,分别用来执行数据加密和解密操作。 (3)程序主要代码如下。 Frm_Main 窗体的后台代码中,首先创建RSACryptoServiceProvider 对象和RSAParameters 标准参数对象, 并且定义一个字节数组,用来存储临时数据,代码如下: RSACryptoServiceProvider RSACrypto; //声明RSA 算法加密解密对象 RSAParameters RSAParame; //声明RSAParameters 参数对象 byte[] M_bt_Data; //定义一个字节数组,用来存储临时数据 在Frm_Main 窗体的构造函数中,调用RSACryptoServiceProvider 类的ImportParameters 方法导入 RSAParameters标准参数,实现代码如下: public Frm_Main() { InitializeComponent(); RSACrypto = new RSACryptoServiceProvider(); //初始化RSA 算法加密解密对象 RSAParame = RSACrypto.ExportParameters(true); //初始化RSAParameters 参数 RSACrypto.Clear(); //清空RSACryptoServiceProvider 对象 RSACrypto = new RSACryptoServiceProvider(); //初始化RSA 算法加密解密对象 RSACrypto.ImportParameters(RSAParame); //导入密钥 } 当用户输入明文数据之后,单击“加密”按钮,调用RSACryptoServiceProvider 类的Encrypt方法对数据进 行加密,并且使用Encoding 类的UTF8 编码方式的GetString 方法得到加密后的数据,显示在文本框中。“加密” 按钮的Click事件代码如下: private void button1_Click(object sender, EventArgs e) { if (textBox1.Text != "") //判断是否输入了要加密的数据 { 图19.9 以参数格式导入导出密钥 C#开发实战1200 例(第II卷) 846 byte[] P_bt_Encrypt = Encoding.UTF8.GetBytes(textBox1.Text); //将要加密的数据转换为字节数组 M_bt_Data = RSACrypto.Encrypt(P_bt_Encrypt, false); //加密数据 textBox2.Text = Encoding.UTF8.GetString(M_bt_Data); //显示加密数据 } } 单击“解密”按钮,调用RSACryptoServiceProvider 类的Decrypt方法对加密过的数据进行解密,并且使用 Encoding 类的UTF8 编码方式的GetString 方法得到解密后的数据,显示在文本框中。“解密”按钮的Click 事 件代码如下: private void button2_Click(object sender, EventArgs e) { if (textBox2.Text != "") //判断是否有加密过的数据 { byte[] P_bt_Decrypt = RSACrypto.Decrypt(M_bt_Data, false); //对数据进行解密 textBox3.Text = Encoding.UTF8.GetString(P_bt_Decrypt); //显示解密数据 } } 秘 笈心法 心法领悟579:巧截字符串中的数字。 截取字符串中的数字时,可以先使用CharEnumerator 对象的MoveNext 方法循环访问字符串中的每个字符, 并将字符用System.Text.Encoding 类中ASCII 编码方式的GetBytes 方法进行编码,然后判断经过编码之后的字符 的ASCII码值是否介于48和57之间,如果是,则将其显示在textBox文本框中。截取字符串中数字的代码如下: CharEnumerator CEnumerator = textBox1.Text.GetEnumerator(); while (CEnumerator.MoveNext()) { byte[] array = new byte[1]; array = System.Text.Encoding.ASCII.GetBytes(CEnumerator.Current.ToString()); int asciicode = (short)(array[0]); if (asciicode >= 48 && asciicode <= 57) { textBox2.Text += CEnumerator.Current.ToString(); } } 19.2 文件的加密与解密 实例580 文本文件加密与解密 光盘位置:光盘\MR\19\580 高级 趣味指数: 实 例说明 在本实例的窗体中,首先选择要加密或解密的文本文件,然后单击“加 密”或“解密”按钮对文本文件进行加密或解密。实例运行效果如图19.10 所示。 关 键技术 本实例实现时主要用到了System.Security.Cryptography命名空间下的 RijndaelManaged 类的CreateDecryptor 方法、CreateEncryptor 方法和CryptoStream 类的Write 方法,下面对本实 例中用到的关键技术进行详细讲解。 (1)RijndaelManaged 类 该类是访问System.Security.Cryptography.Rijndael 对称加密算法的托管版本,其语法格式如下: public sealed class RijndaelManaged : Rijndael 图19.10 文本文件加密与解密 第19章 加密与解密技术 847  注意:此算法支持128、192或256 位的密钥长度。 (2)CreateDecryptor 方法 该方法位于RijndaelManaged 类中,使用指定的Key和初始化向量(IV)创建对称的Rijndael 解密器对象, 其语法格式如下: public override IcryptoTransform CreateDecryptor (byte[] rgbKey,byte[] rgbIV) 参数说明  rgbKey:用于对称算法的机密密钥。  rgbIV:用于对称算法的IV。  返回值:对称的Rijndael 解密器对象。 (3)CreateEncryptor 方法 该方法位于RijndaelManaged 类中,使用指定的Key和初始化向量(IV)创建对称的Rijndael 加密器对象, 其语法格式如下: public override ICryptoTransform CreateEncryptor (byte[] rgbKey,byte[] rgbIV) 参数说明  rgbKey:用于对称算法的机密密钥。  rgbIV:用于对称算法的IV。  返回值:对称的Rijndael 加密器对象。  说明:关于CryptoStream 类的Write 方法的详细讲解,请参见实例575中的关键技术。 设 计过程 (1) 打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为EncryptTextFileOne。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加一个TextBox 控件,用来显示文本 文件路径;添加一个OpenFileDialog 控件,用来选择要加密或解密的文本文件;添加3 个Button 控件,用来执 行选择文本文件、加密和解密操作。 (3)程序主要代码如下。 单击“加密”按钮实现对选择的文本文件进行加密,“加密”按钮的Click事件的代码如下: private void button2_Click(object sender, EventArgs e) { if (textBox1.Text == "") //若未选择要加密的文本文件 { MessageBox.Show("请选择要加密的文件"); } //如果没有选择则弹出提示 else { try{ string strPath = textBox1.Text; //加密文件的路径 int intLent=strPath.LastIndexOf("\\")+1; //设置截取的起始位置 int intLong = strPath.Length; //设置截取的长度 string strName = strPath.Substring(intLent,intLong-intLent); //要加密的文件名称 int intTxt = strName.LastIndexOf("."); //设置截取的起始位置 int intTextLeng = strName.Length; //设置截取的长度 string strTxt = strName.Substring(intTxt,intTextLeng-intTxt); //取出文件的扩展名 strName = strName.Substring(0,intTxt); //加密后的文件名及路径 string strOutName = strPath.Substring(0, strPath.LastIndexOf("\\") + 1) + strName + "Out" + strTxt; //加密文件密钥 byte[] key = { 24, 55, 102, 24, 98, 26, 67, 29, 84, 19, 37, 118, 104, 85, 121, 27, 93, 86, 24, 55, 102, 24, 98, 26, 67, 29, 9, 2, 49, 69, 73, 92 }; byte[] IV ={ 22, 56, 82, 77, 84, 31, 74, 24, 55, 102, 24, 98, 26, 67, 29, 99 }; RijndaelManaged myRijndael = new RijndaelManaged(); FileStream fsOut = File.Open(strOutName, FileMode.Create, FileAccess.Write); FileStream fsIn = File.Open(strPath, FileMode.Open, FileAccess.Read); //写入加密文本文件 CryptoStream csDecrypt = new CryptoStream(fsOut, myRijndael.CreateEncryptor(key, IV), CryptoStreamMode.Write); BinaryReader br = new BinaryReader(fsIn); //创建阅读器来读加密文本 csDecrypt.Write(br.ReadBytes((int)fsIn.Length), 0, (int)fsIn.Length); //将数据写入加密文本 C#开发实战1200 例(第II卷) 848 csDecrypt.FlushFinalBlock(); csDecrypt.Close(); //关闭CryptoStream 对象 fsIn.Close(); //关闭FileStream 对象 fsOut.Close(); //关闭FileStream 对象 if (MessageBox.Show("加密成功!加密后的文件名及路径为:\n" + strOutName + ",是否删除源文件", "信息提示", MessageBoxButtons. YesNo) == DialogResult.Yes) { File.Delete(strPath); //删除指定文件 textBox1.Text = ""; //清空文本框 }else { textBox1.Text = ""; } } catch (Exception ee) //如果出现异常 { MessageBox.Show(ee.Message); //输出异常信息 } } } 单击“解密”按钮实现对加密的文本文件进行解密,“解密”按钮的Click事件代码如下: private void button3_Click(object sender, EventArgs e) { if (textBox1.Text == "") //若未选择要解密的文件 { MessageBox.Show("请选择要解密的文件路径"); //如果没有选择则弹出提示 } else { string strPath = textBox1.Text; //加密文件的路径 int intLent = strPath.LastIndexOf("\\") + 1; //设置截取字符串的起始位置 int intLong = strPath.Length; //设置截取长度 string strName = strPath.Substring(intLent, intLong - intLent); //要加密的文件名称 int intTxt = strName.LastIndexOf("."); //截取字符串的起始位置 int intTextLeng = strName.Length; //截取长度 strName = strName.Substring(0, intTxt); //获取扩展名 if (strName.LastIndexOf("Out") != -1) { strName = strName.Substring(0, strName.LastIndexOf("Out")); } else { strName = strName + "In"; } //加密后的文件名及路径 string strInName = strPath.Substring(0, strPath.LastIndexOf("\\") + 1) + strName + ".txt"; //解密文件密钥 byte[] key = { 24, 55, 102, 24, 98, 26, 67, 29, 84, 19, 37, 118, 104, 85, 121, 27, 93, 86, 24, 55, 102, 24, 98, 26, 67, 29, 9, 2, 49, 69, 73, 92 }; byte[] IV ={ 22, 56, 82, 77, 84, 31, 74, 24, 55, 102, 24, 98, 26, 67, 29, 99 }; RijndaelManaged myRijndael = new RijndaelManaged(); //创建RijndaelManaged 对象 //创建FileStream 对象 FileStream fsOut = File.Open(strPath, FileMode.Open, FileAccess.Read); CryptoStream csDecrypt = new CryptoStream(fsOut, myRijndael.CreateDecryptor(key, IV), CryptoStreamMode.Read); StreamReader sr = new StreamReader(csDecrypt); //把文件读出来 StreamWriter sw = new StreamWriter(strInName); //解密后写入一个新文件 sw.Write(sr.ReadToEnd()); sw.Flush(); sw.Close(); sr.Close(); fsOut.Close(); if (MessageBox.Show("解密成功!解密后的文件名及路径为:"+strInName+",是否删除源文件", "信息提示", MessageBoxButtons.YesNo) == DialogResult.Yes) { File.Delete(strPath); //删除指定文件 textBox1.Text = ""; //清空文本框 } else { 第19章 加密与解密技术 849 textBox1.Text = ""; } } } 秘 笈心法 心法领悟580:如何存储变长字符串? 在程序中存储变长字符串时,需要使用StringBuilder对象。相对于string 对象来说,StringBuilder 对象是可 变的,不用生成中间对象,因此,在连接的字符串较多或字符串长度较长时,通常都使用StringBuilder 对象。 实例581 利用图片加密文件 光盘位置:光盘\MR\19\581 高级 趣味指数: 实 例说明 本实例在加密时,使用指定的图片生成加密密钥,然后对文本文件进 行加密;在解密时,使用加密时的图片生成解密密钥,然后对加密的文本 文件进行解密。运行本实例,首先打开一张图片,用来生成加密或解密的 密钥,然后选择要加密或解密的文本文件,最后单击“加密”或“解密” 按钮,实现对文本文件的加密或解密。实例运行效果如图19.11 所示。 关 键技术 本实例实现时主要用到了RC2CryptoServiceProvider 类、BinaryWriter 类的Write 方法、File 类的Delete 方法和Copy 方法,下面对本实例中用到 的关键技术进行详细讲解。 (1)RC2CryptoServiceProvider 类 该类定义访问RC2算法的加密服务提供程序(CSP)实现的包装对象,无法继承此类。 (2)BinaryWriter 类 该类以二进制形式将基元类型写入流,并支持用特定的编码写入字符串,其构造器的语法格式如下: public BinaryWriter (Stream output) 参数说明 output:表示输出流。 (3)BinaryWriter 类的Write 方法 该方法将一个无符号字节写入当前流,并将流的位置提升一个字节,其语法格式如下: public virtual void Write (byte value) 参数说明 value:表示要写入的无符号字节。 (4)File 类的Delete 方法 File 类提供用于创建、复制、删除、移动和打开文件的静态方法,并协助创建FileStream 对象,该类是个 静态类,其Delete方法用于删除指定的文件,如果指定的文件不存在,则引发异常。该方法的语法格式如下: public static void Delete (string path) 参数说明 path:表示要删除的文件的名称。 (5)File 类的Copy 方法 该方法将现有文件复制到新文件,不允许改写同名的文件,其语法格式如下: public static void Copy (string sourceFileName,string destFileName) 图19.11 利用图片加密文件 C#开发实战1200 例(第II卷) 850 参数说明  sourceFileName:要复制的文件。  destFileName:目标文件的名称,不能是一个目录或现有文件。 设 计过程 (1) 打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为EncryptTextFileTwo。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加一个TextBox 控件,用来显示加密 或解密文件的路径;添加一个OpenFileDialog 控件,用来选择要加密或解密的文件和打开密钥的图片;添加4 个Button 控件,分别用来执行加密、解密、打开文件和打开图片操作;添加一个PictureBox 控件,用于显示密 钥图片。 (3)程序主要代码如下。 单击“加密”按钮,实现利用图片对文本文件进行加密的功能,“加密”按钮的Click 事件的代码如下: private void button3_Click(object sender, EventArgs e) { try { if (pictureBox1.ImageLocation==null) //判断是否选择了图片 { MessageBox.Show("请选择一幅图片用于加密"); return; } //如果没有选择则弹出提示 if (textBox1.Text == "") //若未选择需要加密的文件 { MessageBox.Show("请选择加密文件路径"); return; } //如果没有选择则弹出提示 //图片流 FileStream fsPic = new FileStream(pictureBox1.ImageLocation, FileMode.Open, FileAccess.Read); //加密文件流 FileStream fsText = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read); //初始化对称算法的密钥和向量 byte[] bykey = new byte[16]; //定义存储密钥的字节数组 byte[] byIv = new byte[8]; //定义存储向量的字节数组 fsPic.Read(bykey, 0, 16); //把图片流写入密钥缓冲区 fsPic.Read(byIv, 0, 8); //把图片流写入向量缓冲区 //临时加密文件 string strPath = textBox1.Text; //加密文件的路径 int intLent = strPath.LastIndexOf("\\") + 1; int intLong = strPath.Length; string strName = strPath.Substring(intLent, intLong - intLent); //要加密的文件名称 string strLinPath = "C:\\" + strName; //临时加密文件路径 FileStream fsOut = File.Open(strLinPath, FileMode.Create, FileAccess.Write); //开始加密,首先创建RC2CryptoServiceProvider 对象 RC2CryptoServiceProvider desc = new RC2CryptoServiceProvider(); BinaryReader br = new BinaryReader(fsText); //创建BinaryReader 对象 //创建CryptoStream 对象,用于写入临时加密文件 CryptoStream cs = new CryptoStream(fsOut, desc.CreateEncryptor(bykey, byIv), CryptoStreamMode.Write); cs.Write(br.ReadBytes((int)fsText.Length), 0, (int)fsText.Length); //写入加密流 cs.FlushFinalBlock(); cs.Flush(); cs.Close(); fsPic.Close(); fsText.Close(); fsOut.Close(); File.Delete(textBox1.Text.TrimEnd()); //删除原文件 File.Copy(strLinPath, textBox1.Text); //复制加密文件 File.Delete(strLinPath); //删除临时文件 MessageBox.Show("加密成功"); pictureBox1.ImageLocation = null; textBox1.Text = ""; } catch (Exception ee) { MessageBox.Show(ee.Message); } } 第19章 加密与解密技术 851 单击“解密”按钮,实现利用图片对加密的文本文件进行解密的功能,“解密”按钮的Click事件的代码如下: private void button4_Click(object sender, EventArgs e) { try { //图片流 FileStream fsPic = new FileStream(pictureBox1.ImageLocation, FileMode.Open, FileAccess.Read); //解密文件流 FileStream fsOut = File.Open(textBox1.Text, FileMode.Open, FileAccess.Read); //初始化对称算法的密钥和向量 byte[] bykey = new byte[16]; //定义存储密钥的字节数组 byte[] byIv = new byte[8]; //定义存储向量的字节数组 fsPic.Read(bykey, 0, 16); //把图片流写入密钥缓冲区 fsPic.Read(byIv, 0, 8); //把图片流写入向量缓冲区 //创建临时解密文件 string strPath = textBox1.Text; //加密文件的路径 int intLent = strPath.LastIndexOf("\\") + 1; //获取不含文件名的路径长度 int intLong = strPath.Length; //获取含文件名的路径长度 //获取要解密文件的名称,即加密文件的名称 string strName = strPath.Substring(intLent, intLong - intLent); string strLinPath = "C:\\" + strName; //临时解密文件路径 FileStream fs = new FileStream(strLinPath, FileMode.Create, FileAccess.Write); //开始解密,首先创建RC2CryptoServiceProvider 对象 RC2CryptoServiceProvider desc = new RC2CryptoServiceProvider(); //创建CryptoStream 对象,用于读取加密文件 CryptoStream csDecrypt = new CryptoStream(fsOut, desc.CreateDecryptor(bykey, byIv), CryptoStreamMode.Read); BinaryReader sr = new BinaryReader(csDecrypt); //创建BinaryReader 对象 BinaryWriter sw = new BinaryWriter(fs); //创建BinaryWriter 对象 sw.Write(sr.ReadBytes(Convert.ToInt32(fsOut.Length))); //写入解密流 sw.Flush(); sw.Close(); sr.Close(); fs.Close(); fsOut.Close(); fsPic.Close(); csDecrypt.Flush(); File.Delete(textBox1.Text.TrimEnd()); //删除原文件 File.Copy(strLinPath, textBox1.Text); //复制加密文件 File.Delete(strLinPath); //删除临时文件 MessageBox.Show("解密成功"); //弹出提示信息 pictureBox1.ImageLocation = null; //清空图片 textBox1.Text = ""; //清空文本框 } catch (Exception ee) //如果出现异常 { MessageBox.Show(ee.Message); //输出异常 } } 秘 笈心法 心法领悟581:如何去除字符串尾空格? 去除字符串尾空格需要使用string 类的Trim 方法,该方法用来从字符串的开始和末尾处移除空白字符的所 有匹配项。例如,下面的代码用来去掉textBox1 文本框中字符串的尾空格,并将结果显示在textBox2 文本框中: textBox2.Text = textBox1.Text.Trim(); 实例582 对文件进行加密保护 光盘位置:光盘\MR\19\582 高级 趣味指数: 实 例说明 随着计算机的普及,文件的安全越来越重要,本实例使用C#制作了一个对文件进行加密保护的实例。运行 C#开发实战1200 例(第II卷) 852 本实例,选择要加密或解密的文件,用程序来判断是否是加密过的文件, 如果不是,输入加密密码,单击“加密”按钮,加密已选择的文件;如果 是,输入解密密码,单击“解密”按钮,解密选择的加密文件。实例运行 效果如图19.12 所示。 关 键技术 本实例制作对文件进行加密保护程序时,首先选择要加密或解密的文 件,并输入加密或解密密码,然后启动一个新的线程,使用输入的密码对 指定的文件进行加密或解密操作。另外,如果对文件执行的是加密操作,则加密成功后删除原文件。具体实现 过程中,主要用到了DES 类的CreateEncryptor 和CreateDecryptor 方法、CryptoStream 类的构造函数及其Write 方法。  说明:关于DES 类的CreateEncryptor 方法和CreateDecryptor 方法、CryptoStream 类的构造函数及其Write 方法的详细讲解,请参见实例575中的关键技术。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为ProtectFile。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加一个OpenFileDialog 控件,用来显 示“打开”对话框;添加两个TextBox 控件,分别用来显示选择的文件路径和输入加密、解密密码;添加3 个 Button控件,分别用来执行选择加密或解密的文件、加密文件和解密文件操作;添加一个ProgressBar控件,用 来显示加密或解密的进度。 (3)程序主要代码如下。 Frm_Main 窗体加载时,首先将加密文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值