C#学习笔记

这一学期结束了,虽然一直在搞Android开发,但是C#上课我也是认真听的,是没怎么深学,课下不练习也就很快忘了,为了应付考试( ̄^ ̄),我整理了下以前的代码,主要的内容提取下做个笔记,反正内容也不是很多,万一以后用到了呢?
o( ̄▽ ̄)ゞ)) ̄▽ ̄)o

文件操作

在这之前记得添加引用:using System.IO;

利用打开对话框本地硬盘获取文件

先写一个最简单的设置背景图片的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
//打开的文件选择对话框上的标题
openFileDialog.Title = "请选择文件";
//设置文件类型
openFileDialog.Filter = "文本文件(*.txt)|*.txt|所有文件(*.*)|*.*";
//设置默认文件类型显示顺序
openFileDialog.FilterIndex = 1;
//保存对话框是否记忆上次打开的目录
openFileDialog.RestoreDirectory = true;
//设置是否允许多选
openFileDialog.Multiselect = false;
//设置默认路径
openFileDialog.InitialDirectory = "d:\\";
//按下确定选择的按钮
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
//如果为多选的时候
//MessageBox.Show(openFileDialog.FileName); //完整路径
//MessageBox.Show(openFileDialog.FileNames[0]); //完整路径 - 多选文件
//MessageBox.Show(openFileDialog.SafeFileName); //文件名
//MessageBox.Show(openFileDialog.SafeFileNames[0]);

//获得文件路径
string localFilePath = openFileDialog.FileName.ToString();
//获取文件路径,不带文件名
//FilePath = localFilePath.Substring(0, localFilePath.LastIndexOf("\\"));
//获取文件名,带后缀名,不带路径
string fileNameWithSuffix = localFilePath.Substring(localFilePath.LastIndexOf("\\") + 1);
//去除文件后缀名
string fileNameWithoutSuffix = fileNameWithSuffix.Substring(0, fileNameWithSuffix.LastIndexOf("."));
//在文件名前加上时间
//string fileNameWithTime = DateTime.Now.ToString("yyyy-MM-dd ") + fileNameExt;
//在文件名里加字符
string newFileName = localFilePath.Insert(1, "dameng");
}
}

按照指定规则遍历文件

这里演示下从指定目录过滤出jpg图片文件。规则可以是正则表达式(未证实)
.可以表示可执行程序所在的目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 string filepath = "./src/";
List<string> namelist = new List<string>();

//获取文件夹中的信息
DirectoryInfo folder = new DirectoryInfo(filepath);

private void GetAllFiles(DirectoryInfo folder)
{
//遍历文件夹的内容,筛选出符合规则的文件
foreach (FileInfo file in folder.GetFiles("*.jpg"))
{
//将文件名添加到集合/容器
namelist.Add(file.Name);
}
//遍历文件夹--然后进行递归遍历文件
foreach (DirectoryInfo dd in d.GetDirectories())
{
GetAllFiles(dd);
}
}

补充一个关于读取文件流编码相关的

1
2
3
4
5
6
7
StreamReader sr = new StreamReader(filepath + "文本文档.txt",Encoding.Default);
String line;
while ((line = sr.ReadLine()) != null)
{
//每次读取一行
//...
}

数据库ADO操作

还是首先要先添加引用:
using System.Data;
using System.Data.SqlClient;
这里其实没什么特别的,就固定的那么几句,其他的就是执行sql语句了,这里写一下标准的几句固定的语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class DBHelper
{
//获得一个链接
private static SqlConnection getConn()
{
string strConn = "data source=.;initial catalog=test;uid=sa;password=..";
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
return conn;
}
//主要是传入一个查询语句,获得一个数据表格
public static DataTable getDT(string strSQL)
{
SqlConnection conn = getConn();

DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(strSQL, conn);
da.Fill(dt);
conn.Close();
return dt;
}
//主要执行非查询语句(增删改) 返回所影响的行数
public static int cmdSQL(string strSQL)
{
SqlConnection conn = getConn();

SqlCommand cmd = new SqlCommand(strSQL, conn);
int i = cmd.ExecuteNonQuery();
conn.Close();
return i;
}
}

dt.Rows[0][0]; dataTable的行集合
dt.Columns[0][0]; dataTable的列集合

再补充一个随机从数据库取得数据的sql语句:
select top 20 * from Exam order by newid()
原理大概猜测是是根据ID经过N次排序后抽取前20条记录(未证实)

字符串相关

字符串的分割

  • 按照指定字符分割,返回一个string数组
  • 按照字符数组进行分割,返回一个string数组
  • 按照指定的位置分割,返回一个string
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //按照字符分割
    string[] ss = str.Split('-');
    //按照字符数组进行分割
    //第二个参数,指定字符串的切割规则,这里是删除空字符
    //从字符串头部开始遍历,遇到含有的字符就进行分割 (大概 = =
    string[] ss = richTextBox1.Text.Split(new char[] { ' ', '-','\n',',' },StringSplitOptions.RemoveEmptyEntries);
    //按照指定长度/位置分割
    //第二个数字是长度,不是下标! 这里从输入(textBox)获取
    string s1 = str.Substring(0, Convert.ToInt32(textBox2.Text));

关于Split的重载还有很多,这里不多介绍,就学了这些 = =

从字符串再选择一段字符串

这是一个让选中的改变颜色的例子:

1
2
3
4
//选中要改变颜色的字符,第一个是开始位置,第二个是长度
richTextBox1.Select(i, 1);
//改变选中的字符的颜色
richTextBox1.SelectionColor = Color.Red;

正则

还是首先添加引用:
using System.Text.RegularExpressions;
match会捕获第一个匹配。而matches会捕获所有的匹配。
match类型就是一个单独的捕获,matchcollection就是一组捕获。

1
2
3
4
5
6
7
8
string strRegex = "正则内容";
//IgnoreCase是忽略大小写,这样会降低匹配
Regex r = new Regex(strRegex, RegexOptions.IgnoreCase);
MatchCollection mc = r.Matches(richTextBox1.Text);
foreach (Match m in mc)
{
listBox1.Items.Add(m.Value);
}

多线程

多线程和委托有着很紧密的联系,使用多线程一般都会使用到委托,和Android一样,多线程不能操作UI,想要更新UI就必须使用委托。
为了防止一些其他问题,最佳的做法是一个线程最好只操作UI的一个控件。
线程不能被强制终止,只能自己停下来,也就是说不同线程直接是没法进行操作的,我们所做的终止线程只是做了一个终止的标记而已(未测试)。

1
2
3
4
5
6
7
8
9
private Thread t1;
//带参数的开启方式 注意只写方法名即可不需要加()
t1 = new Thread(new ParameterizedThreadStart(执行的方法));
t1.Start(参数);
//不带参数的开启方式
//t1 = new Thread(new ThreadStart(执行的方法));
//t1.Start();

t1.Abort();

因为不知道传入的参数是什么类型的,所以是个obj类型的,用的时候需要强转,定义的时候也要定义成obj类型的。

下面再来看委托,用在需要更新UI的地方

1
2
3
4
5
6
7
8
9
10
11
12
//定义委托
private delegate void updateListDele(string str);
//定义符合委托入口参数和返回值的方法
private void updateList(string str)
{
lock (this)
{
//加了个同步锁,具体的更新UI的逻辑
}
}
//然后就是使用了 可以看出第二个是需要的参数
this.listBox1.Invoke(new updateListDele(updateList), new object[] { f.FullName });

类似的还有BeginInvoke方法,至于区别:

  • Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托。
  • Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句柄所在线程上异步执行指定委托。

网络操作

老规矩,先添加引用:
using System.Net;

先来看看最基本的发送网络请求的写法:

1
2
3
4
5
6
7
8
9
//AS相当于就是强制类型转换
HttpWebRequest request = WebRequest.Create("http") as HttpWebRequest;
//模拟一个浏览器
request.UserAgent = "Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;

Stream stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream, Encoding.Default);
string str = sr.ReadToEnd();

然后是socket编程之类
下面主要是发送消息的,也就是客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//得到本机IP,设置UDP端口号
IPAddress localip = getValidIP("127.0.0.1");
int localport = getValidPort("1234");
ipLocalPoint = new IPEndPoint(localip, localport);

//定义网络类型,数据连接类型和网络协议UDP
mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

//绑定网络地址
mySocket.Bind(ipLocalPoint);
//发送UDP数据包
RemotePoint = (EndPoint)(ipLocalPoint); //用本地作为接收地址了
string msg = "发送的消息"
byte[] data = Encoding.Default.GetBytes(msg);
mySocket.SendTo(data, data.Length, SocketFlags.None, RemotePoint);

然后是接收消息的,也就是服务端

1
2
3
4
5
6
//最开始的定义与上面相同,直接引用上面的了
//接收数据处理线程
string msg;
byte[] data = new byte[1024];
int rlen = mySocket.ReceiveFrom(data, ref RemotePoint);
msg = Encoding.Default.GetString(data, 0, rlen);

其他补充

修改字体样式

举个修改label字体的例子:

1
2
3
4
//font是一个类  要先声明
Font ff = new Font("微软雅黑", 28);
label2.Font = ff;
label2.ForeColor = Color.Red;//设置前背景,文字颜色

强制类型转换

1
2
3
4
5
int a = Convert.ToInt32(转换的内容);
//强制类型转换 效率高 上面其实就是调用 int.Parse
int a = int.Parse(string); //类似的有 double.Parse ....
//强制类型转换函数,如果成功返回true,存在number中,如果失败,返回 false,number为0
int.TryParse("string",out number);

timer的使用

具体执行的代码双击控件,然后再写就可以了。

1
2
3
//设置timer的开关和刷新时间
timer1.Enabled = true;
timer1.Interval = 888;

随机数的产生

1
2
Random r = new Random()  //创建能够产生随机数的对象
int sjs = r.Next(1,10) //随机数的范围 [ )区间 //让这个对象用函数来产生随机数

关于get和set

get,set方法在Java中已经非常熟悉了,c#中不太一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//获取部分
Demo de = new Demo();
//设置属性值
de.show = 2;
//de.show 这样就是获取属性值
MessageBox.Show(de.show+"");


//定义部分
class Demo
{
int a;
//定义属性,注意没有(),不需要传入参数
public int show
{
//这get 和 set 可以认为是个关键字了吧
get
{
return a;
}
set
{
//value 就是指传进来的值,固定名称
a = value;
}
}
}

手动添加点击事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//绑定点击事件
bt[b].Click += Form1_Click;

//事件的定义 通过tag属性来辨别是拿一个按钮对象
private void Form1_Click(object sender, EventArgs e)
{
Button but = new Button();
but = (Button)sender;
switch (but.Tag.ToString())
{
case "0":
BackColor = Color.Red;
break;
case "1":
BackColor = Color.Pink;
break;
}
}

总结

就内容来说确实不多,并且和Java也有很多类似的地方,但是很多地方只知道怎么用,具体什么个原理没深究,有些参数都不造啥意思….⊙﹏⊙b汗,这些坑以后有时间慢慢填吧。
C#写form程序还是很顺手的,以后说不定什么时候就能用的上,做下记录总是不会错的!
假期来啦,最佳的学习时段来啦!

喜欢就请我吃包辣条吧!

评论框加载失败,无法访问 Disqus

你可能需要魔法上网~~