进制

表示某一位置上的数运算时是逢X进一位。二进制就是逢二进一, 十进制是逢十进一,十六进制是逢十六进一,以此类推。

so:二进制001010101只有0和1计算机中的数据都是二进制表示,四进制以0、1、2、3四个数字表示任何实数。十进制0~9数字组成,十六进制0~9以及ABCEDF组成(表示十进制数)10~15。

Directory类

用来操作文件夹的

 1 Directory.CreateDirectory("d:/ccc/cc"); //创建文件夹
2
3 Directory.Delete("d:/ccc",true); //true删除非空文件夹
4
5 Directory.Move(@"d:/ccc", @"d:/cccc"); //剪切操作 源目录没了 必须同一卷轴d盘
6
7 string[] s = Directory.GetFiles(@"D:\项目\Web\Images\shiji"); //获得文件夹目录下所有文件全路径
8
9 string[] s = Directory.GetFiles(@"D:\项目\Web\Images\shiji","*.jpg"); //获得文件夹目录下指定后缀名文件全路径
10
11 string[] s = Directory.GetDirectories(@"D:\项目\Web\Images"); //获得文件夹目录下的文件夹的全路径
12
13 Directory.Exists(@"D:\项目\Web\Images") //是否存在某文件夹

进程

我们可以把计算机中每一个运行的应用程序当作是一个进程

 1 ///获得当前程序中正在运行的进程
2 Process[] pros = Process.GetProcesses();
3 foreach (var item in pros)
4 {
    //item.Kill(); //关闭所有进程.
    //item.ProcessName; //进程名
5 Console.Write(item.ToString());
6 }
7 //通过进程打开一些程序
8 Process.Start("calc"); //打开计算器
9 Process.Start("notepad"); //打开记事本
10 //打开指定文件
11 ProcessStartInfo pro = new ProcessStartInfo(@"d:\11.txt");
12 Process pr = new Process();
13 pr.StartInfo = pro;
14 pr.Start();

线程

每一个进程是由多个线程组成的。

单线程:让程序做多件事时,会引发卡死 假死状态。

多线程:让一个程序同时处理多个事情,后台运行程序,提高程序的运行效率。

前台线程:只有所有的前台线程都关闭才能完成程序关闭。(winform多窗口时)

后台线程:只要所有的前台线程结束,后台线程自动结束。

 1 //实例化Thread类,并传入一个指向线程所要运行的方法。(这时线程已经产生,但还没有运行)
2 //调用Thread类的Start方法,标记线程可以被CPU执行了,但具体执行事件由CPU决定。
3 Thread th = new Thread(Test); //创建一个线程去执行这个方法。
4 th.IsBackground = true; //将线程设置为后台线程,前台关闭后 线程结束。
5 th.Start(); //标记准备就绪,可以随意被执行,具体什么时候执行由CPU决定。
6 //在.net下是不允许跨线程访问的。
7 //有时候需要手动释放线程 关闭时 判断线程是否关闭
8 if (th != null)
9 {
10 th.Abort(); //结束这个线程 不能再Start()
11 }
12 Thread.Sleep(3000); //睡眠3秒后执行
13 //线程执行带参数方法
14 Thread.Start("123"); object类型参数 在start后括号写参数

多用于大量数据时,多分一个线程去搜索数据,然后存储到缓存里,页面再用异步获取缓存中的数据。

GDI+

是一种绘图装置接口,可以用来绘制图片。

画直线

Graphics g = this.CreateGraphics(); //创建GDI对象
Pen pen = new Pen(Brushes.Yellow); //创建画笔
Point p1 = new Point(30, 50); //创建两个点
Point p2 = new Point(250, 250);
g.DrawLine(pen, p1, p2);

画验证码

 1 /// <summary>
2 /// 字符
3 /// </summary>
4 /// <param name="len">几位</param>
5 /// <returns></returns>
6 public static string validation(int cd)
7 {
8 var ran = new Random();
9 int num, tem;
10 string rtuStr = "";
11 for (int i = 0; i < cd; i++)
12 {
13 num = ran.Next();
14 if (i % 2 == 1)
15 tem = num % 10 + '0'; //数字
16 else
17 tem = num % 26 + 'A'; //字母
18 rtuStr += Convert.ToChar(tem).ToString();
19 }
20 //写入cookie
21 HttpCookie cookie = new HttpCookie("check");
22 cookie.Value = rtuStr.ToLower();
23 HttpContext.Current.Response.Cookies.Add(cookie);
24 return rtuStr;
25 }
26
27 /// <summary>
28 /// 生成图像
29 /// </summary>
30 /// <param name="check">字符</param>
31 public static byte[] drawImg(string check)
32 {
33 Bitmap img = new Bitmap(90, 34);
34 var ht = Graphics.FromImage(img);
35 ht.Clear(Color.White);
36 ht.DrawLine(new Pen(Color.SpringGreen), 1, 1, 90, 34);
37 Font font = new Font("微软雅黑", 20, FontStyle.Bold);
38 var jianbian = new LinearGradientBrush(new Rectangle(0, 0, img.Width, img.Height), Color.Teal, Color.Snow, 2f, true);
39 ht.DrawString(check, font, jianbian, 0, 0);
40 ht.DrawRectangle(new Pen(Color.Aqua), 0, 0, img.Width - 1, img.Height - 1);
41 MemoryStream ms = new MemoryStream();
42 img.Save(ms, ImageFormat.Jpeg);
43 ht.Dispose();
44 img.Dispose();
45 return ms.ToArray();
46 }

mvc中调用

1 public ActionResult ShowValidate()
2 {
3 var check = Common.Validate.validation(4);
4 byte[] buffer = Common.Validate.drawImg(check);
5 return File(buffer, "image/jpeg");
6 }

前台

<img src="/Login/ShowValidate" id="img" onclick="changeCode()" class="validateImg">

if (validateCode.toLowerCase() == getCode()) {
return true;
} function changeCode() {
$("#img").attr("src", $("#img").attr("src") + "?");
} function getCode() {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var validate = cookies[i].split("=");
if (validate[0].replace(/(^\s*)|(\s*$)/g, "") == "check") {
return validate[1].replace(/(^\s*)|(\s*$)/g,"");
}
}
}

XML文件

可扩展标记性语言,用来保存轻量级数据。

XML的标签是成对出现的、并且是区分大小写的。

XML文档必须包含根节点,且只有一个。

创建XML文件

 1 //创建XML对象
2 XmlDocument doc = new XmlDocument();
3 //创建文档描述信息
4 XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
5 doc.AppendChild(dec);
6
7 //创建根节点
8 XmlElement books = doc.CreateElement("Books");
9 doc.AppendChild(books);
10
11 //创建子节点
12 XmlElement book1 = doc.CreateElement("Book");
13 books.AppendChild(book1); //将子节点添加到books
14
15 //给book1子节点追加子节点
16 XmlElement name1 = doc.CreateElement("Name");
17 name1.InnerText = "c#"; //赋值 文本值
18 book1.AppendChild(name1);
19
20 XmlElement price1 = doc.CreateElement("Price");
21 price1.InnerXml = "<b>10.0</b>"; //赋值 html标签
22 book1.AppendChild(price1);
23
24 XmlElement items = doc.CreateElement("Items");
25 //给节点增加属性
26 items.SetAttribute("Name", "c#");
27 items.SetAttribute("Price", "10.0");
28 book1.AppendChild(items);
29
30 doc.Save("Books.xml"); //保存
31
32 //创建后
33 <?xml version="1.0" encoding="utf-8"?>
34 <Books>
35 <Book>
36 <Name>c#</Name>
37 <Price>
38 <b>10.0</b>
39 </Price>
40 <Items Name="c#" Price="10.0" />
41 </Book>
42 </Books>

向已有XML文件中追加

1 XmlDocument doc = new XmlDocument();
2 if (File.Exists("Books.xml"))
3 {
4 doc.Load("Books.xml"); //加载 xml
5 XmlElement books = doc.DocumentElement; //得到根节点
6 //再建立元素进行追加
7 }

获取XML文件

 1 XmlDocument doc = new XmlDocument();
2 doc.Load("Books.xml");
3
4 XmlElement books = doc.DocumentElement;
5 XmlNodeList xnl = books.ChildNodes; //得到所有节点
6
7 foreach (XmlNode v in xnl) //遍历得到所有节点值
8 {
9 Console.WriteLine(v.InnerText);
10 }
11
12 XmlNodeList xnl1 = doc.SelectNodes("Books/Book/Items"); //查找节点列表
13 foreach (XmlNode node in xnl1)
14 {
15 Console.WriteLine(node.Attributes["Name"].Value); //得到name属性的值
16 Console.WriteLine(node.Attributes["Price"].Value); //得到price属性的值
17 }

删除XML文件

1 XmlDocument doc = new XmlDocument();
2 doc.Load("Books.xml");
3
4 XmlNode xnl = doc.SelectSingleNode("Books/Book"); //查找单一节点
5 xnl.RemoveAll(); //删除全部
6 doc.Save("Books.xml");
7 Console.ReadKey();

LinqToXml

 1 //兼容传统方法创建
2 XDocument xDoc = new XDocument();
3 //xDoc.Declaration = new XDeclaration() 默认UTF-8 第一行不需要单独建
4 XElement xRoot = new XElement("root", "值"); //定义元素
5
6 XElement xRoot1 = new XElement("root1"); //定义元素2
7 xRoot1.Value = "值1";
8
9 XAttribute xattr = new XAttribute("Id", "1"); //定义属性
10
11 xDoc.Add(xRoot); //统一使用add添加
12 xRoot.Add(xattr);
13
14 xDoc.Save(@"d:\linqtoxml.xml");
15
16 //真正的linq语法
17 //F# 函数式编程语言
18 new XDocument(
19 new XElement("root",
20 new XAttribute("id", "001"),
21 "值")
22 ).Save(@"d:\2.xml");
23 //链式编程,流水线生产 f1().f2().f3()...
24
25 //查找xml
26 XDocument xdoc = new XDocument(new XElement("root"));//根节点
27 xdoc.Root.Add(new XElement("person",
28 new XAttribute("id", "1"),
29 new XAttribute("name", "zhangsan"),
30 new XAttribute("sex", "1")
31 )); //添加子节点
32 xdoc.Root.Add(new XElement("person",
33 new XAttribute("id", "2"),
34 new XAttribute("name", "lisi"),
35 new XAttribute("sex", "2")
36 ));
37 xdoc.Save(@"d:\2.xml");
38
39 <?xml version="1.0" encoding="utf-8"?>
40 <root>
41 <person id="1" name="zhangsan" sex="1" />
42 <person id="2" name="lisi" sex="2" />
43 </root>
44
45 //开始查找、修改、删除
46
47 XDocument xdoc = XDocument.Load(@"d:\2.xml"); //加载xml
48 foreach (XElement xlt in xdoc.Root.Elements()) //Root根节点 Elements 元素集合
49 {
50 if (xlt.Name.LocalName == "person") //Name节点名 LocalName不带命名空间的节点名
51 {
52 if (xlt.Attribute("id").Value == "1") //判断属性值为1时
53 {
54 Response.Write(xlt.Attribute("name").Value); //输出name
55 xlt.Attribute("name").Value = "newname"; //修改name
56 xlt.Remove(); //删除此节点
57 xdoc.Save(@"d:2.xml");
58 }
59 }
60 }
61
62 //Linq查询语法
63 //Descendants()所有子节点 可加某节点下所有节点
64 var query = from s in xdoc.Descendants() //从集合里找
65 where s.Name.LocalName == "person"
66 select s;
67 foreach (XElement xlt in query)
68 {
69 Response.Write(xlt.Value);
70 }
71
72 //Linq方法语法(lambda表达式)
73 foreach (XElement xlt in xdoc.Descendants().Where(s =>
74 {
75 if (s.Name.LocalName == "name")
76 {
77 return true;
78 }
79 return false;
80 }))
81 {
82 Response.Write(xlt.Value);
83 }

正则表达式

用于字符串处理、表单验证等。
var regx = "^[a-zA-Z0-9]{6,20}$";
if ( ! Regex.IsMatch("abcdef;sd123",regex)
{
//长度必须6-20,字母和数字
}
^ 匹配一行的开始 例如正则表达式 ^when 能够匹配到 ”when in the“ 的开始,但不能匹配到 ”what and when in the“
$ 匹配一行的结束。 例如正则表达式 food$ 能够匹配到 “he's food” 的末尾
.点 匹配任何单个字符,例如正则表达式 r.t 能够匹配 “rat、rut、r t”,但是不能匹配root
* 匹配0或多个正好在它之前的那个字符,例如 .* 能够匹配任意数量的任何字符。
[] 匹配匹配一个出现在[]中的字符
| 或 敏感词 ab|cd|ed|df
() 提高优先级 a(bc) 实现分组
+ 紧跟在+前面的字符出现任意次,至少1次
? 紧跟在?前面的字符出现或不出现
{n} {n,} {n,m} 匹配一定范围个数 {1,} 相当与+ {0,} 相当于*
\d 代表 [0-9] \D 代表 [^0-9] 非0-9
\i 代表 [a-z]
\u 代表 [A-Z]
\a 代表 [A-Za-z]
\w 代表 [a-zA-Z0-9]
常用表达式
匹配身份证:\d{15}|\d{18}
匹配中国邮政编码:[1-9]\d{5}(?!\d)
匹配腾讯QQ号:[1-9][0-9]{4,}
匹配国内电话号码:\d{3}-\d{8}|\d{4}-\d{7}
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
匹配网址URL的正则表达式:[a-zA-z]+://[^\s]*
匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
匹配首尾空白字符的正则表达式:^\s*|\s*$
匹配HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? />
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
限制网页表单里的文本框输入内容:
只能输入中文:<input type="text" onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))" />
只能输入数字:<input type="text" onkeyup="value=value.replace(/[^\d]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))" />
只能输入数字和英文:<input type="text" onkeyup="value=value.replace(/[\W]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text).replace(/[^\d]/g,''))" />

委托 使用delegate定义委托,将一个方法作为参数传给另一个方法。 委托所指向的函数必须返回值与参数相同

  1 /// <summary>
2 /// 委托语法
3 /// </summary>
4 class Program
5 {
6 public delegate void delSayhi(string name); //定义委托
7 static void Main(string[] args)
8 {
9 delSayhi del = new delSayhi(sayHiChinese); //实例化委托调用具体方法
10 del("san"); //执行
11
12 delSayhi del1 = sayHiChinese; //直接赋值方式
13 del1("si");
14
15 //匿名函数
16 delSayhi del2 = delegate(string name) { Console.WriteLine(name + ",思密达"); };
17 del2("韩国");
18
19 //lambda表达式 ()没参数也要写 => { //方法体 } 没参数可以e=> Console.WriteLine(""); 如果只有一句话不用{} 返回的return可以省略
20 delSayhi del3 = (string name) => { Console.WriteLine(name + ",萨瓦迪卡"); };
21 del2("泰国");
22
23 sayHi("david", sayHiEnglish); //调用自定义方法 参数要调用的方法
24 Console.ReadKey();
25 }
26
27 public static void sayHi(string name, delSayhi del) //定义方法 类型委托
28 {
29 del(name);
30 }
31
32 public static void sayHiChinese(string name)
33 {
34 Console.WriteLine("你好, 我叫" + name);
35 }
36 public static void sayHiEnglish(string name)
37 {
38 Console.WriteLine("hello, my name is {0}, nice to meet you!", name);
39 }
40 }
41
42
43
44 /// <summary>
45 /// 求任意数组最大值
46 /// </summary>
47 class Program
48 {
49 public delegate int delCompre(object o1, object o2); //定义比较委托
50 static void Main(string[] args)
51 {
52 //比较int
53 object[] objs = new object[] { 1, 2, 3, 4, 5, 32, 1, 243, };
54 var max = getMax(objs, getIntMax); //传入比较int方法
55 Console.WriteLine(max);
56
57 var max2 = getMax(objs, delegate(object o1, object o2)
58 {
59 return int.Parse(o1.ToString()) - int.Parse(o2.ToString());
60 }); //匿名函数 与比较int一样
61 Console.WriteLine(max2);
62
63 //比较string
64 object[] strs = new object[] { "abc", "efd", "asdf", "sd", "asdff" };
65 var maxstrs = getMax(strs, delegate(object o1, object o2)
66 {
67 return o1.ToString().Length - o2.ToString().Length;
68 }); //匿名函数
69 Console.WriteLine(maxstrs);
70
71 var maxstrs2 = getMax(strs, (object o1, object o2) =>
72 {
73 return o1.ToString().Length - o2.ToString().Length;
74 }); //lambda 表达式
75 Console.WriteLine(maxstrs2);
76
77 Console.ReadKey();
78 }
79
80 public static int getIntMax(object o1, object o2) //比较int方法
81 {
82 int n1 = int.Parse(o1.ToString());
83 int n2 = int.Parse(o2.ToString());
84 return n1 - n2;
85 }
86 /// <summary>
87 /// 取一个任意数组的最大值
88 /// </summary>
89 /// <param name="objs">数组</param>
90 /// <param name="del">委托</param>
91 /// <returns></returns>
92 public static object getMax(object[] objs, delCompre del)
93 {
94 object max = objs[0];
95 for (int i = 0; i < objs.Length; i++)
96 {
97 //if (max < objs[i]) object 无法确定是什么类型 所以不能用<
98 if (del(max, objs[i]) < 0) //如果委托值小于0 成立 传入如何比较即可
99 {
100 max = objs[i];
101 }
102 }
103 return max;
104 }
105 }
106
107
108 /// <summary>
109 /// 泛型<T>委托
110 /// </summary>
111 class Program
112 {
113 public delegate int delCompre<T>(T t1, T t2); //定义泛型委托
114 static void Main(string[] args)
115 {
116 //int
117 int[] nums = { 1, 2, 3, 4, 5 };
118 int max = getMax<int>(nums, (int t1, int t2) => { return t1 - t2; });
119 Console.WriteLine(max);
120
121 //string
122 string[] strs = { "asd", "sdf", "zxcvv", "123", "qwe" };
123 string maxStr = getMax(strs, (string s1, string s2) => { return s1.Length - s2.Length; });
124 Console.WriteLine(maxStr);
125
126 Console.ReadKey();
127 }
128
129 public static T getMax<T>(T[] objs, delCompre<T> del)
130 {
131 T max = objs[0];
132 for (int i = 0; i < objs.Length; i++)
133 {
134 if (del(max, objs[i]) < 0)
135 {
136 max = objs[i];
137 }
138 }
139 return max;
140 }
141 }

多播委托 注册多个方法,调用时将这些方法依次执行一遍。

1 public delegate void my1();
2
3 my1 my = Fun1();
4 my+= Fun2(); //+=实现多播委托
5
6 public static void Fun1(){
7 }
8 public static void Fun2(){
9 }

进程、线程、GDI+、XML、委托的更多相关文章

  1. android 进程/线程管理(一)----消息机制的框架

    一:android 进程和线程 进程是程序运行的一个实例.android通过4大主件,弱化了进程的概念,尤其是在app层面,基本不需要关系进程间的通信等问题. 但是程序的本质没有变,尤其是多任务系统, ...

  2. python学习笔记-进程线程

    1.什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述 ...

  3. 获取系统中所有进程&线程信息

    读书笔记--[计算机病毒解密与对抗] 目录: 遍历进程&线程程序 终止进程 获取进程信息 获取进程内模块信息 获取进程命令行参数 代码运行环境:Win7 x64 VS2012 Update3 ...

  4. [skill] 进程 线程

    在业务逻辑上: 进程线程没有区别. 在系统资源上: 进程拥有自己的地址空间.线程拥有自己的堆栈和临时变量,与其他线程共享地址空间. 在通信代价上: 线程间通信代价更低,实现更方便.进程通信相对开销比较 ...

  5. pyhon——进程线程、与协程基础概述

    一直以来写博客都是实用主义者,只写用法,没信心写原理,但是每一次写作业的过程都有一种掘地三尺的感觉,终于,写博客困难症重症患者经历了漫长的思想斗争,还是决定把从网上淘到的各种杂货和自己的总结放在一起, ...

  6. C#中的线程一(委托中的异步)

    C#中的线程一(委托中的异步) 一.同步委托 我们平时所用的委托以同步居多,我们编写一个方法和相关委托进行演示: publicdelegatevoid DoSomethingDelegate(stri ...

  7. android 进程/线程管理(二)----关于线程的迷思

    一:进程和线程的由来 进程是计算机科技发展的过程的产物. 最早计算机发明出来,是为了解决数学计算而发明的.每解决一个问题,就要打纸带,也就是打点. 后来人们发现可以批量的设置命令,由计算机读取这些命令 ...

  8. android 进程/线程管理(三)----Thread,Looper / HandlerThread / IntentService

    Thread,Looper的组合是非常常见的组合方式. Looper可以是和线程绑定的,或者是main looper的一个引用. 下面看看具体app层的使用. 首先定义thread: package ...

  9. android 进程/线程管理(四)续----消息机制的思考(自定义消息机制)

    继续分析handler 和looper 先看看handler的 public void dispatchMessage(Message msg) { if (msg.callback != null) ...

  10. android 进程/线程管理(四)----消息机制的思考(自定义消息机制)

    关于android消息机制 已经写了3篇文章了,想要结束这个系列,总觉得少了点什么? 于是我就在想,android为什么要这个设计消息机制,使用消息机制是现在操作系统基本都会有的特点. 可是andro ...

随机推荐

  1. linux配置LAMP

    VPS注意:最近在VPS安装过程中,MYSQL老是报错 dpkg: error processing package mysql-server-5.6 (--configure): subproces ...

  2. [改善Java代码]用偶判断,不用奇判断

    建议21: 用偶判断,不用奇判断 public class Client { public static void main(String[] args) { Scanner in = new Sca ...

  3. 关于Override在JDK1.5和JDK1.6上子类实现接口中方法使用@Override注解编译错误.

    遇到这个问题说来也怪.新开了一个path的工作空间用来打patch.该Eclipse的默认全局的编译版本是1.6.但是唯独其中的一个插件项目的版本是1.5(可能是唯一的一个,不确定,不知道为什么会是这 ...

  4. Wince 文本函数和字体应用

    好像又进入了一个疲惫期了,晚上状态不好,但是还是想继续更新下博客,继上次分析了wince下设备环境以及怎么绘制相关图像后,,笔者在这片文章中讲到文本函数以及其相关应用.文本输出函数是输出文本的内容,也 ...

  5. UML建模文章总结

    一.为什么要学习UML UML是Unified Modeling Language(统一建模语言)的简称.UML是对软件密集型系统中的制品进行可视化.详述.构造和文档化的语言.制品{Artifact} ...

  6. js 正则实例

    1.匹配url参数 var re = /([^&=]+)=?([^&]*)/g while (r = re.exec("aaa1a=aabbbbbbb")) { a ...

  7. 【Qt】QT5 获取IP地址

    QT获取本机IP地址 #include <QtNetwork/QHostAddress> #include <QtNetwork/QNetworkInterface> #inc ...

  8. [DevExpress]ChartControl之基准线示例

    关键代码: /// <summary> /// 创建基准线ConstantLine /// </summary> /// <param name="chart& ...

  9. VS2010水晶报表的添加与使用

    最近在学习VS2010水晶报表,发现原先安装的VS2010旗舰版没有 Crystal Report Viewer 控件,网上搜索一下发现要安装一个插件----CRforVS_13_0, 于是下载安装: ...

  10. 新贵HTML5,2016的发展方向会怎样?

    2014年下半年,微信捧火了HTML5小游戏,自此国内各行各业开始对HTML5保持高涨关注.2015年是国内HTML5行业迅速发展的一年,在媒体大肆渲染“互联网寒冬”之际,HTML5作品的生产数量和传 ...