文章目录
1、面向对象编程(OOP)
.net是围绕OOP原则构建的,促进了代码的可重用性、继承、多态性和封装。
2、反射
反射的目的就是为了扩展未知的应用。比如你写了一个程序,这个程序定义了一些接口,只要实现了这些接口的dll都可以作为插件来插入到这个程序中。那么怎么实现呢?就可以通过反射来实现。就是把dll加载进内存,然后通过反射的方式来调用dll中的方法。
3、web.config和app.config
**3.1、app.config 是 Windows 应用程序(如控制台应用程序、Windows Forms 应用程序)的专属配置文件。**它如同一个精密的设置箱,将应用程序所需的各种配置信息,如数据库连接字符串、应用程序的默认设置等,以 XML 格式进行存储。这种存储方式使得开发者在后期维护和调整应用程序时,无需重新编译整个项目,只需轻松修改 app.config 文件中的相关配置,就能实现应用程序行为的改变。例如,在一个 Windows Forms 的财务管理应用程序中,通过 app.config 可以方便地配置数据库连接字符串,当数据库服务器地址发生变化时,直接修改配置文件中的地址信息,应用程序就能顺利连接到新的数据库 。
创建如下:按以下的步骤创建完项目,就会生成一个app.config的配置文件
3.2、web.config 则是ASP.NET Web 应用程序的得力配置助手。它承担着存储 Web 应用程序配置设置的重任,包括但不限于身份验证方式、授权规则、页面编译设置等。以一个在线商城的 Web 应用为例,web.config 可以配置用户的身份验证模式为表单验证,同时指定登录页面的 URL,还能设置页面的编译调试模式,在开发阶段设置为调试模式以便及时发现错误,上线后切换为发布模式提高性能 。
创建如下:按以下的步骤创建完项目,就会生成一个web.config的配置文件
3.3、比如解决方案中包含多个项目,怎么判断具体是调用那个配置文件呢?
我的理解如下,如有更好的理解麻烦留言补充,谢谢!!!
a、如果是Windows 分类下创建的项目的则是使用app.config
b、如果是web分类下创建的项目则是使用wb.config
4、获取app.config或者web.config中的内容
appSettings:放程序需要的配置信息
connectionStrings:放数据库的连接信息之类的
using System.Configuration;//需要引用这个命名空间
string connectionString = ConfigurationManager.AppSettings["Test"];//获取appSettings键为Test的对应的值
string connectionString02 = ConfigurationManager.ConnectionStrings["Test"].ConnectionString;//获取connectionStrings键为Test的对应的值
string[] allKeys = ConfigurationManager.AppSettings.AllKeys;//获取appSettings的所以键
5、.net对于xml文件的操作
a、读取xml的数据,存在datatable
DataTable dt = null;
//获取下面所有文件
DataSet dsSql = new DataSet();
string[] files = Directory.GetFiles(Application.StartupPath, "*.xml", SearchOption.AllDirectories);
foreach (string xmlFilePath in files)
{
DataSet ds = new DataSet();
ds.ReadXml(xmlFilePath);
string tableName = new FileInfo(xmlFilePath).Name.Split('.')[0];//用xml的文件名为后面的查询语句的dataTable命名
if (ds.Tables.Contains("Command"))
{
DataTable dt02 = ds.Tables["Command"].Copy();
dt02.TableName = tableName;
if (!dsSql.Tables.Contains(tableName))
{
dsSql.Tables.Add(dt02);
}
}
}
b、 对象转成xml文件
Message mes = new Message();
mes.QrUrl = "www.baicu.com";
mes.TableName = "baidu";
// 创建XmlSerializer对象,并指定实体类型
XmlSerializer serializer = new XmlSerializer(typeof(Message));
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(@"C:\Users\31640\Desktop\test.xml", settings);
serializer.Serialize(writer, mes);
public class Message
{
public string QrUrl { get; set; }
public string TableName { get; set; }
}
c、对象列表转成xml文件
// 创建一个List<Person>实例
List<Message> listMes = new List<Message>();
Message mes = new Message();
mes.QrUrl = "www.baidu.com";
mes.TableName = "baidu";
listMes.Add(mes);
mes.QrUrl = "www.xiaomi.com";
mes.TableName = "xiaomi";
listMes.Add(mes);
// 创建XmlSerializer对象,并指定实体类型
XmlSerializer serializer = new XmlSerializer(typeof(List<Message>));
// 创建一个StringWriter对象,用于写入XML字符串
///StringWriter writer = new StringWriter();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(@"C:\Users\31640\Desktop\test.xml", settings);
serializer.Serialize(writer, listMes);
public class Message
{
public string QrUrl { get; set; }
public string TableName { get; set; }
}
d、把datatable写入xml文件(通过dataset)
// 创建一个DataTable实例
DataTable dt = new DataTable();
dt.TableName = "t_people";
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int));
dt.Rows.Add("张三", 25);
dt.Rows.Add("李四", 30);
dt.Rows.Add("王五", 35);
DataSet ds = new DataSet();
ds.Tables.Add(dt);
ds.WriteXml(@"C:\Users\31640\Desktop\test.xml"); // 写入文件
6、C#静态成员的调用方法
如下报错:
总结:不是静态方法调用的时候是需要进行实例化的。直接用类名调用的话需要把方法定义成静态方法。
修改如下:
7、连接数据库并查询数据
DataTable dt = null;
DataSet dsSql = new DataSet();
//connectionString 是获取配置文件中的数据库连接信息,具体操作见目录4
string connectionString = ConfigurationManager.ConnectionStrings["Test"].ConnectionString;
//获取自定义xml中的sql语句,具体操作见目录5
string[] files = Directory.GetFiles(Application.StartupPath, "*.xml", SearchOption.AllDirectories);
foreach (string xmlFilePath in files)
{
DataSet ds = new DataSet();
ds.ReadXml(xmlFilePath);
string tableName = new FileInfo(xmlFilePath).Name.Split('.')[0];
if (ds.Tables.Contains("Command"))
{
DataTable dt02 = ds.Tables["Command"].Copy();
dt02.TableName = tableName;
if (!dsSql.Tables.Contains(tableName))
{
dsSql.Tables.Add(dt02);
}
}
}
dt = dsSql.Tables["sql"];
//这边使用using,使用完会自动释放,就不需要最后在来个connection.Close();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
this.chkSQL.Checked = true;
//因为测试的xml中就写了一条sql语句所以直接获取第一行的sql语句就行
//多条的话就可以通过dt.select()的方法去获取对应的sql语句
string ID = "Query";
DataRow[] row = dt.Select("ID = '" +ID+ "'");
string query = Convert.ToString(row[0]["CommandString"]);
//string query = Convert.ToString(dt.Rows[0]["CommandString"]);
// 创建SqlCommand对象
using (SqlCommand command = new SqlCommand(query, connection))
{
//这边是存在需要传入查询参数的情况;
//比如sql语句为:select * from t_user where name = @name
command.Parameters.AddWithValue("@name", "张三");
// 创建SqlDataAdapter对象
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
// 创建DataTable对象
DataTable dataTable = new DataTable();
// 使用SqlDataAdapter填充DataTable
adapter.Fill(dataTable);
// 将DataTable绑定到DataGridView
dataGridView1.DataSource = dataTable;
}
}
}
8、泛型
泛型(Generics) 是C#语言中一种非常强大的特性,允许你在定义类、结构、接口、方法和委托时使用类型参数,进而在使用时指定实际的类型。泛型提供了代码的重用性、类型安全性和性能优势。
简单来说,泛型使得你能编写一个方法或类,而不必预先指定具体的数据类型,只有在使用时才指定具体类型。
public class Result<T>//
{
public string type { get; set; }
public T list { get; set; }
}
public class People
{
public string name { get; set; }
public int age { get; set;}
}
//调用如下
Result<People> tsetList = new Result<People>();
tsetList.type = "泛型测试";
People people = new People();
people.name = "张三";
people.age = 20;
tsetList.list = people;
9、数组、集合、队列、栈、字典
//数组
int[] num1 = new int[5];
num1[0] = 1;
//集合
List<int> num2 = new List<int>();
num2.Add(2);
//队列
Queue<int> queue = new Queue<int>();
queue.Enqueue(1);
//栈
Stack<int> stack = new Stack<int>();
stack.Push(1);
//字典
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add("age", 18);
10、线程
a、多线程
using System.Threading;
private void button4_Click(object sender, EventArgs e)
{
Thread newThread = new Thread(new ThreadStart(Run));
newThread.Start();
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Main thread: Start work.");
Thread.Sleep(100); // 线程暂停一百毫秒
}
newThread.Join(); // 等待新线程结束
Console.WriteLine("Main thread: New thread has ended.");
}
private void Run()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("New thread: A New Work...");
Thread.Sleep(200); // 线程暂停两百毫秒
ThreadFunction();
}
}
private void ThreadFunction()
{
if (this.textBox1.InvokeRequired)//等待异步
{
FlushClient fc = new FlushClient(ThreadFunction);
this.Invoke(fc);//通过代理调用刷新方法
}
else
{
this.textBox1.Text = DateTime.Now.ToString();//通过代理的方法去更新控件的值
}
}
注解:
ThreadStart 委托指向 Run 方法,该方法将在新线程中执行。
newThread.Start() 启动新线程。
newThread.Join() 使主线程等待新线程完成。一般情况下,主线程创建并启动子线程,如果子线程中执行大量耗时运算,主线程可能早于子线程结束。如果主线程需要知道子线程的执行结果时,就需要等待子线程执行结束。主线程可以sleep(xx),但这样的xx时间不好确定,因为子线程的执行时间不确定,join()方法比较合适这个场景。
在newThread.Start()后会开始执行Run()内的内容,也会继续往下执行主程序下的内容
b、线程池
using System.Threading;
private void button4_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Process));
for (int i = 0; i < 100; i++)
{
Console.WriteLine("Main thread: Start work");
Thread.Sleep(100);
}
Thread.Sleep(2000); // 主线程等待的时间,以便线程池线程完成工作
}
static void Process(object state)
{
for (int i = 0; i < 50; i++)
{
Console.WriteLine("ThreadPool thread: A New Work...");
Thread.Sleep(200);
}
}
注解:
ThreadPool.QueueUserWorkItem 将 Process 方法添加到线程池队列中,线程池会自动分配一个线程来执行该方法。
线程池适用于执行短期的异步任务,可以减少线程创建和销毁的开销。
c、Task
using System.Threading;
private void button4_Click(object sender, EventArgs e)
{
Task newTask = Task.Run(() =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Task: Task Working...");
Task.Delay(200).Wait();
}
});
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Main thread: Start work.");
Task.Delay(100).Wait();
}
newTask.Wait(); // 等待任务完成
}
注解:
Task.Run 启动一个新任务,该任务在后台线程中执行。
Task.Delay 是 Thread.Sleep 的异步版本,不会阻塞线程。
newTask.Wait() 等待任务完成,类似于 Thread.Join()。
11、Lambda表达式
Lambda表达式通常用于简化代码,特别是在LINQ查询和函数式编程中。
12、Show()和ShowDialog()
a、Show():
1、调用Show()方法后,代码继续执行,不会等待新窗体关闭。
2、用户可以在新窗体和主窗体之间自由切换。
3、Show()方法没有返回值。
b、ShowDialog():
1、调用ShowDialog()方法后,代码执行暂停,直到新窗体关闭。
2、ShowDialog()方法可以返回窗体的对话结果(如DialogResult.OK、DialogResult.Cancel等)。
13、socket与plc
a、发送消息到plc端
//连接plc
private void button6_Click(object sender, EventArgs e)
{
ToIP = "127.0.0.1";//plc的地址
ToPort = 2000;
if (string.IsNullOrEmpty(ToIP)) return;
if (socketSend != null)
{
socketSend.Close();
}
try
{
socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketSend.Connect(ToIP, ToPort);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//发送消息到plc
private void button7_Click(object sender, EventArgs e)
{
try
{
string msg = "1000";
if (chkHex.Checked)//单选框:是否哈希值发送
{
socketSend.Send(HexStrTobyte(msg));
}
else
{
bool containsChinese = Regex.IsMatch(msg, @"[\u4e00-\u9fa5]");
byte[] strSenMsg = null;
if (containsChinese)//是否包含中文
{
Encoding encoding = Encoding.GetEncoding("GBK");
strSenMsg = encoding.GetBytes(msg);
}
else
{
strSenMsg = Encoding.UTF8.GetBytes(msg);
}
socketSend.Send(strSenMsg);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public byte[] HexStrTobyte(string hexString)
{
hexString = hexString.Replace(" ", "");
if ((hexString.Length % 2) != 0)
hexString += " ";
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16);
return returnBytes;
}
b、监听plc的值
private void button8_Click(object sender, EventArgs e)
{
socConnections.Clear();
dictThread.Clear();
//定义一个套接字用于监听客户端发来的信息 包含3个参数(IP4寻址协议,流式连接,TCP协议)
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//服务端发送信息 需要1个IP地址和端口号
IP = "127.0.0.1";
SourcePort = 2000;
//socketWatch.Connect(IP, SourcePort);
IPAddress ipaddress = IPAddress.Parse(IP); //获取文本框输入的IP地址
//将IP地址和端口号绑定到网络节点endpoint上
IPEndPoint endpoint = new IPEndPoint(ipaddress, SourcePort); //获取文本框上输入的端口号
//监听绑定的网络节点
socketWatch.Bind(endpoint);
//将套接字的监听队列长度限制为20
socketWatch.Listen(1);
//创建一个监听线程
threadWatch = new Thread(WatchConnecting);
//将窗体线程设置为与后台同步
threadWatch.IsBackground = true;
//启动线程
threadWatch.Start();
}
private void WatchConnecting()
{
Socket socConnection = socketWatch.Accept();
while (true) //持续不断监听客户端发来的请求
{
try
{
//定义一个1M的内存缓冲区 用于临时性存储接收到的信息
byte[] arrRecMsg = new byte[1024 * 1024];
//将客户端套接字接收到的数据存入内存缓冲区, 并获取其长度
int length = socConnection.Receive(arrRecMsg);
//将套接字获取到的字节数组转换为人可以看懂的字符串
string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
//将发送的信息追加到聊天内容文本框中
Console.WriteLine("ThreadPool thread message :" + strRecMsg);
this.Invoke((MethodInvoker)delegate
{
textBox1.Text = textBox1.Text + strRecMsg + "\r\n";
});
}
catch (Exception ex)
{
Console.WriteLine("远程服务器已中断连接");
}
}
}
14、RestSharp
RestSharp是一个专门用于.NET的HTTP客户端库,旨在简化与API(接口)的交互。它提供了直观的接口和丰富的功能,使得处理HTTP请求和响应变得更加简单和高效。
using Newtonsoft.Json;
using RestSharp;
private void button9_Click(object sender, EventArgs e)
{
var client = new RestSharp.RestClient("http://127.0.0.1:5301");
var requestPost = new RestRequest("api/File/Update", Method.POST);
//var client = new RestSharp.RestClient("http://127.0.0.1:5301/api/File/Update");
//var requestPost = new RestRequest("", Method.POST);
Message message = new Message();
message.Url = "https://blog.youkuaiyun.com/weixin_51238200/article/details/145466271";
message.Name = ".net的基本知识";
var json = JsonConvert.SerializeObject(message);
requestPost.AddParameter("application/json", json, ParameterType.RequestBody);
IRestResponse responsePost = client.Execute(requestPost);
ReturnMessage jsonRtn = JsonConvert.DeserializeObject<ReturnMessage>(responsePost.Content);
if (jsonRtn.status == "success")
{
Console.WriteLine("success");
}
else
{
Console.WriteLine("false");
}
}
public class Message
{
public string Url { get; set; }
public string Name { get; set; }
}
public class ReturnMessage
{
public string status { get; set; }
}
GET请求将参数直接附加到URL后面,以问号分隔URL和传输数据,参数之间以&相连。如果数据是英文字母/数字,原样发送;如果是空格,则转换为+;如果是中文/其他字符,则直接把字符串用BASE64加密4。
POST请求是把请求的数据放在请求体中。
15、C#连接SQLite数据库
using System.Data.SQLite;
private static string SQLiteDBPath = @"C:\Users\Desktop\system.db";
private void button13_Click(object sender, EventArgs e)
{
try
{
if (!File.Exists(SQLiteDBPath))
{
SQLiteConnection.CreateFile(SQLiteDBPath);
}
if (File.Exists(SQLiteDBPath))
{
string connectionString = string.Format("Data Source={0};Version=3;", SQLiteDBPath);
//连接数据库
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
{
connection.Open();
//修改密码
//connection.ChangePassword("123456");
//创建表
//string commandText = "CREATE TABLE IF NOT EXISTS T_USER ( ID INT IDENTITY(1,1), Name NVARCHAR(10), age int)";
//插入表
//string commandText = string.Format("INSERT INTO T_USER (Name, age) values ('{0}','{1}')", "张三", "20");
/*
using (SQLiteCommand command = new SQLiteCommand(commandText, connection))
{
command.ExecuteNonQuery();//执行sql
}
*/
//查询数据
string commandText = "select * from T_USER";
using (SQLiteCommand command = new SQLiteCommand(commandText, connection))
{
using (SQLiteDataAdapter adapter = new SQLiteDataAdapter(command))
{
// 创建DataTable对象
DataTable dataTable = new DataTable();
// 使用SqlDataAdapter填充DataTable
adapter.Fill(dataTable);
// 将DataTable绑定到DataGridView
dataGridView1.DataSource = dataTable;
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
16、读取及解析二维码内容
需引入如下包
a、ThoughtWorks.QRCode
using ThoughtWorks.QRCode.Codec;
using ThoughtWorks.QRCode.Codec.Data;
打开对应的二维码图片(此步骤不要也行,直接用路径去访问对应的二维码)
OpenFileDialog p = new OpenFileDialog();
p.Title = "请选择二维码文件";
p.Filter = "图像文件(JPeg, Gif, Bmp, etc.)|*.jpg;*.jpeg;*.gif;*.bmp;*.tif; *.tiff; *.png| JPeg 图像文件(*.jpg;*.jpeg)"
+ "|*.jpg;*.jpeg |GIF 图像文件(*.gif)|*.gif |BMP图像文件(*.bmp)|*.bmp|Tiff图像文件(*.tif;*.tiff)|*.tif;*.tiff|Png图像文件(*.png)"
+ "| *.png |所有文件(*.*)|*.*";
p.Multiselect = false;
if (p.ShowDialog() == DialogResult.OK)
{
filepath = p.FileName;
System.Threading.Thread t = new System.Threading.Thread(ss);
t.IsBackground = true;
t.Start();
}
解析对应路径的二维码
private void ss()
{
if (filepath != "")
{
try
{
picPhoto.Image = new Bitmap(filepath); //picPhoto这个是winform中的pictureBox控件
//Bitmap myBitmap = new Bitmap(Image.FromFile(filepath));
QRCodeDecoder qrDecoder = new QRCodeDecoder();
string txtMsg = qrDecoder.decode(new QRCodeBitmapImage(new Bitmap(picPhoto.Image)), Encoding.UTF8);
//string txtMsg = qrDecoder.decode(new QRCodeBitmapImage(myBitmap), Encoding.UTF8);
this.txt_Guid.Text = txtMsg;
}
catch (Exception ex)
{
Util.Message.ShowInfo(ex.Message+"识别失败!");
}
}
System.Threading.Thread.CurrentThread.Abort();
}
b、ZXing包
这个包到NuGet Package Manager去下载,如下载遇到包报错,可参考文章NuGet Package Manager下载新的dll包的时候报错
需引入如下包:
using ZXing;
和上面那种方法相差就在在于ss()中,此就只放这段代码
private void ss()
{
if (filepath != "")
{
try
{
picPhoto.Image = new Bitmap(filepath);//picPhoto这个是winform中的pictureBox控件
BarcodeReader reader = new BarcodeReader();
reader.Options.CharacterSet = "UTF-8";
Result result = reader.Decode((Bitmap)picPhoto.Image);
string txtMsg = result.Text;
this.txt_Guid.Text = txtMsg;
}
catch (Exception ex)
{
Util.Message.ShowInfo(ex.Message+"识别失败!");
}
}
System.Threading.Thread.CurrentThread.Abort();
}
17、net的写入与读取
a、数据写入到txt中
private void button14_Click(object sender, EventArgs e)
{
string pathName = @"C:\Users\30\Desktop\text.txt";
string[] content = { "去年今日此门中", "人面桃花相映红","人面不知何处去","桃花依旧笑春风" };
FileStream fs;
//判断是否已经有了这个文件
if (!System.IO.File.Exists(pathName))
{
//没有则创建这个文件,创建写入文件,设置文件属性为隐藏
fs = new FileStream(pathName, FileMode.Create, FileAccess.Write);
}
else
{
fs = new FileStream(pathName, FileMode.Open, FileAccess.Write);
}
File.SetAttributes(@pathName, FileAttributes.Normal);
StreamWriter sw = new StreamWriter(fs);
foreach (string item in content)
{
sw.WriteLine(item.Trim());//写入值
}
sw.Flush();
sw.Dispose();
sw.Close();
fs.Close();
}
b、从txt中读取数据到textBox
private void button15_Click(object sender, EventArgs e)
{
string pathName = @"C:\Users\310\Desktop\text.txt";
StreamReader sR = File.OpenText(pathName);
string nextLine;
while ((nextLine = sR.ReadLine()) != null)
{
this.textBox1.Text = this.textBox1.Text + nextLine + "\r\n";
}
sR.Close();
}
c、创建excel文件、读取excel文件、把数据写入到excel中
//********创建excel表格******************
string importExcelPath = @"C:\Users\31640\Desktop\import.xlsx";
//声明工作本对象(XSSFWorkbook后缀名.xlsx;HSSFWorkbook后缀名.xls)
string fileExt = Path.GetExtension(importExcelPath).ToLower();
IWorkbook wbk = null;
if (fileExt == ".xlsx")
{
wbk = new XSSFWorkbook();
}
else if (fileExt == ".xls")
{
wbk = new HSSFWorkbook();
}
//创建一个sheet
ISheet mysheet = wbk.CreateSheet("Sheet");
//将excel数据赋值给文件流,并excel文件的Write方法参数,保存wbk文件到本地磁盘
//using (FileStream fs = File.OpenWrite(path))
//{
// wbk.Write(fs);
//}
//或如下,不用File.OpenWrite(Path),直接new一个Filestream对象也可以
using (FileStream fs = new FileStream(importExcelPath, FileMode.Create))
{
wbk.Write(fs);
}
//上面的保存Excel方式,要注意FileMode必须是Create,如果是Open,Excel文件损坏
//*********************读取excel表格,并写入数据****************
if (!File.Exists(importExcelPath))
{
MessageBox.Show("文件不存在,退出");
return;
}
//读取excel,需要通过filestream读取excel,然后文件流对象作为参数传给workbook构造函数参数
FileStream fs_read = File.OpenRead(importExcelPath);
if (fileExt == ".xlsx")
{
wbk = new XSSFWorkbook(fs_read);
}
else if (fileExt == ".xls")
{
wbk = new HSSFWorkbook(fs_read);
}
//获取wbksheet数量
int sheetCnt = wbk.NumberOfSheets;
//激活第一个sheet
wbk.SetActiveSheet(0);
//获取sheet对象
ISheet sheet = wbk.GetSheetAt(0);
for (int i = 0; i < 3; i++)
{
//创建行
IRow myRow = sheet.CreateRow(i);
//创建单元格,写入值
// $符号允许在字符串中直接插入变量,而不需要使用传统的字符串拼接方式。
myRow.CreateCell(0).SetCellValue($"第{ i + 1}行,第1列");
myRow.CreateCell(1).SetCellValue($"第{ i + 1}行,第2列");
myRow.CreateCell(2).SetCellValue($"第{ i + 1}行,第3列");
}
//获取当前行的单元格数量,注意,这个数字是列数,不是最后一个单元格索引
int cellCnt = sheet.GetRow(0).LastCellNum;
//自动调整列宽
for (int i = 0; i < cellCnt; i++)
{
sheet.AutoSizeColumn(i);
}
//关闭excel文件的读取流
fs_read.Close();
//保存到磁盘
using (FileStream fs_write = File.OpenWrite(importExcelPath))
{
wbk.Write(fs_write);
}
d、把数据从excel读写到datatable中
string importExcelPath = @"C:\Users\31640\Desktop\import.xlsx";
//声明工作本对象(XSSFWorkbook后缀名.xlsx;HSSFWorkbook后缀名.xls)
string fileExt = Path.GetExtension(importExcelPath).ToLower();
IWorkbook wbk = null;
DataTable dt = new DataTable();
dt.TableName = "table";
FileStream fs_read = File.OpenRead(importExcelPath);
if (fileExt == ".xlsx")
{
wbk = new XSSFWorkbook(fs_read);
}
else if (fileExt == ".xls")
{
wbk = new HSSFWorkbook(fs_read);
}
//获取wbksheet数量
int sheetCnt = wbk.NumberOfSheets;
//激活第一个sheet
wbk.SetActiveSheet(0);
//获取sheet对象
ISheet sheet = wbk.GetSheetAt(0);
int rowCount = sheet.LastRowNum;//总行数
if (rowCount > 0)
{
IRow firstRow = sheet.GetRow(0);//第一行
int cellCount = firstRow.LastCellNum;//列数
//把列名填充DataTable
for (int i = 0; i < cellCount; i++)
{
ICell cell = firstRow.GetCell(i);
dt.Columns.Add(cell.StringCellValue, typeof(string));
}
for (int j = 1; j <= rowCount; j++)
{
IRow row = sheet.GetRow(j);//第二行开始
int cellNum = row.LastCellNum;//列数
DataRow dtRow = dt.NewRow();
for (int z = 0; z < cellNum; z++)
{
ICell cell = row.GetCell(z);
cell.ToString();
CellType type = cell.CellType;
//Type Type = cell.GetType();
//if (Type == typeof(string)){ }
if (type.ToString() == "String")
{
dtRow[z] = cell.StringCellValue;
}
else if (type.ToString() == "Numeric")
{
dtRow[z] = cell.NumericCellValue;
}
else if (type.ToString() == "RichString")
{
dtRow[z] = cell.RichStringCellValue;
}
else if (type.ToString() == "Boolean")
{
dtRow[z] = cell.BooleanCellValue;
}
}
dt.Rows.Add(dtRow.ItemArray);
}
}
e、读取csv,数据存到datatable
DataTable dt = new DataTable();
string importExcelPath = @"C:\Users\31640\Desktop\import.csv";
//文件流读取
System.IO.FileStream fs = new System.IO.FileStream(importExcelPath, System.IO.FileMode.Open);
System.IO.StreamReader sr = new System.IO.StreamReader(fs, Encoding.GetEncoding("gb2312"));
//UTF-8:国际通用字库,支持现今世界各种不同语言。
//gb2312 :是国标,是中国的字库,里面仅涵盖了汉字和一些常用外文
string tempText = "";
bool isFirst = true;
while ((tempText = sr.ReadLine()) != null)
{
string[] arr = tempText.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
//一般第一行为标题,所以取出来作为标头
if (isFirst)
{
foreach (string str in arr)
{
dt.Columns.Add(str,typeof(string));
}
isFirst = false;
}
else
{
//从第二行开始添加到datatable数据行
DataRow dr = dt.NewRow();
for (int i = 0; i < dt.Columns.Count; i++)
{
dr[i] = arr[i] ;
}
dt.Rows.Add(dr);
}
}
//展示到页面
dataGridView1.DataSource = dt;
//关闭流
sr.Close(); fs.Close();
17、对象与JSON的互相转换
a、普通对象和json互转
public class Parameter
{
public string userNo;
public string userName;
public string position;
}
private void glassButton1_Click(object sender, EventArgs e)
{
Parameter parameteradd = new Parameter
{
userNo= "5555",
userName= "张三",
position= "经理",
};
//把对象实例化的值转化成JSON
string jsonStr = JsonConvert.SerializeObject(parameteradd);
//JSON格式的值转化成对象
Parameter paibanStatus = JsonConvert.DeserializeObject<Parameter>(jsonStr);
}
b、JONS中含有数组的情况,对象与json转化
情况如下:
public class PushCheck
{
public string A{ get; set; }
public string B{ get; set; }
public string C{ get; set; }
public Detail[] D{ get; set; }
}
public class Detail
{
public string D1{ get; set; }
public string D2{ get; set; }
public string D3{ get; set; }
public string D4{ get; set; }
}
List<PushCheck> lpc = new List<PushCheck>();"实例化一个数组
PushCheck lpc_data = new PushCheck();"实例化一个对象
List<Detail> lst = new List<Detail>();"实例化一个数组
Detail lst_data = new Detail();"实例化一个对象
lpc_data.A= "1";
lpc_data.B= "1";
lpc_data.C= "1";
lst_data.D1= "1";
lst_data.D2= "1";
lst_data.D3= "1";
lst_data.D4= "1";
lst.Add(lst_data);
lpc_data.D= lst.ToArray();
lpc.Add(lpc_data);
var json = JsonConvert.SerializeObject(lpc);
17、小知识合计
a、dataGridView1中选中的行复制到dataGridView2中
DataTable dtQuery = (dataGridView1.DataSource as DataTable);
DataTable dt03 = dtQuery.Clone();
for (int i = 0; i < dataGridView1.SelectedRows.Count; i++)
{
int rowId = this.dataGridView1.SelectedRows[i].Index;
DataRow row = dtQuery.Rows[rowId];
dt03.Rows.Add(row.ItemArray);
}
DataView dv = dt03.DefaultView;
dv.Sort = "ID Asc";//排序,可有可没有
dataGridView2.DataSource = dv.ToTable();
b、解决假死现场,更新前台显示
private void button12_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10000; i++)
{
label1.Text = i.ToString();
//没加下面这句的时候,text的值会直接变成9999
//加了之后就会实时更新
Application.DoEvents();
}
}
c、DataTable的Compute
private void button11_Click(object sender, EventArgs e)
{
DataTable dt = (dataGridView1.DataSource as DataTable);
//计算年龄总和
object sumAge;
sumAge = dt.Compute("Sum(age)", "");
//计算年纪>20的人数
object countAge;
countAge = dt.Compute("Count(name)", "age > 20");
//计算年纪最小值
object minAge;
minAge = dt.Compute("Min(age)", "");
//计算年纪最大值
object MaxAge;
MaxAge = dt.Compute("Max(age)", "");
//计算年纪的平均值
object avgAge;
avgAge = dt.Compute("avg(age)", "");
}
d、Dock的页面顺序调整
//在对应的Designer文件中修改对应的顺序:
this.panel1.Controls.Add(this.D);
this.panel1.Controls.Add(this.A);
this.panel1.Controls.Add(this.C);
this.panel1.Controls.Add(this.B);
// 改成
this.panel1.Controls.Add(this.C);
this.panel1.Controls.Add(this.D);
this.panel1.Controls.Add(this.B);
this.panel1.Controls.Add(this.A);
e、DataTable与DataRow[]互转
//DataTable 转DataRow[]
DataRow[] dtRow = dt.Select();
//DataRow[] 转DataTable
DataTable dt02 = dtRow .CopyToDataTable();
f、对文件是否存在的一些操作
//路径
string folderPath = @"C:\Users\Desktop\test";
string filePath = @"C:\Users\Desktop\test.txt";
try
{
//判断文件夹是否存在的
if (System.IO.Directory.Exists(folderPath) == false)
{
System.IO.Directory.CreateDirectory(folderPath);
}
MessageBox.Show("创建成功");
//判断文件是否存在
if (System.IO.File.Exists(filePath) == false)
{
System.IO.File.CreateText(filePath);
}
MessageBox.Show("创建成功");
}
catch (Exception ex)
{
MessageBox.Show("创建失败");
throw ex;
}
g、把datatable的值赋给下拉框
this.name.DisplayMember = "Value";//下拉框要显示的值
this.name.ValueMember = "Value";//下拉框要显示的内部值
DataRow row1 = dtName.NewRow();
row1["Type"] = null;
dtName.Rows.InsertAt(row1, 0);//增加一行插在table的最前面,给下拉框留一行空行
this.name.DataSource = dtName;//直接把查询出来的datatable赋值给下拉框的DataSource