开发一个小工具重温C#经典问题
2011-12-26 22:53
387 查看
利用业余时间为公司的国际化开发一个小工具,功能很简单,但可以重新温习C#的一些经典问题。
1. 两个基本功能
根据源文件和新文件对比,生成对比结果文件。
对比结果要包括:新文件中更改的词条、新加的词条、删除的词条。
输入文件格式:文件开头有些注释,正文的每行由id号、空格、引号围绕的词条三部分。
对比结果文件格式:
实例1:
txt1.txt(源文件)
----------
id1 "a"
id2 "b"
id3 "c"
txt2.txt(新文件)
----------
id1 "a2"
id3 "c"
id4 "d"
生成结果:
result.txt
------------
id1 "a" "a2"
id2 "b" ""
id4 "" "d"
图形界面1
第二个功能是,专门的翻译人员将对比出来变化了的词条的翻译结果存到对比结果文件中,每种语言占据一列。
具体例子就不列了,主要来看C#的一些常见问题。
图形界面2
2. 集合类Hashtable的使用
哈希表的简单操作
查找:HashtableObject[key];
在哈希表中添加一个keyvalue键值对:HashtableObject.Add(key,value);
在哈希表中去除某个keyvalue键值对:HashtableObject.Remove(key);
从哈希表中移除所有元素: HashtableObject.Clear();
判断哈希表是否包含特定键key: HashtableObject.Contains(key);
下面控制台程序将包含以上所有操作:
using System;
using System.Collections; file使用Hashtable时,必须引入这个命名空间
class hashtable
{
public static void Main()
{
Hashtable ht=new Hashtable(); file创建一个Hashtable实例
ht.Add(E,e);添加keyvalue键值对
ht.Add(A,a);
ht.Add(C,c);
ht.Add(B,b);
string s=(string)ht[A];
if(ht.Contains(E)) file判断哈希表是否包含特定键,其返回值为true或false
Console.WriteLine(the E keyexist);
ht.Remove(C);移除一个keyvalue键值对
Console.WriteLine(ht[A]);此处输出a
ht.Clear();移除所有元素
Console.WriteLine(ht[A]); file此处将不会有任何输出
}
}
遍历哈希表
遍历哈希表需要用到DictionaryEntry Object,代码如下:
for(DictionaryEntry de in ht) fileht为一个Hashtable实例
{
Console.WriteLine(de.Key);de.Key对应于keyvalue键值对key
Console.WriteLine(de.Value);de.Key对应于keyvalue键值对value
}
3. 使用OpenDialog选取文件。
OpenFileDialog ofd = new OpenFileDialog(); // new一个方法
ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // 打开文件的默认位置
ofd.ShowDialog(); // 显示打开文件的窗口
fileName = ofd.FileName; // 获得选择的文件路径
textBox1.Text = fileName;
extendedName = Path.GetExtension(fileName); // 文件扩展名
fileName1 = Path.GetFileName(fileName); // 文件名
使用FolderBrowserDialog选取文件夹,选择对比结果文件的保存位置。
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.ShowDialog();
folderName = fbd.SelectedPath; //获得选择的文件夹路径
textBox3.Text = folderName;
4. 读写文件
StreamReader sr = new StreamReader(path, Encoding.Default);
string line;
while ((line = sr.ReadLine()) != null)
{...
}
StreamWriter sw = new StreamWriter(path, true, Encoding.Default); // true to append to existing file
sw.WriteLine(...);
5. using自动关闭文件流
using语句,定义一个范围,在范围结束时处理对象。
场景:
当在某个代码段中使用了类的实例,而希望无论因为什么原因,只要离开了这个代码段就自动调用这个类实例的Dispose。
要达到这样的目的,用try...catch来捕捉异常也是可以的,但用using也很方便。
例如:
using (Class1 cls1 = new Class1(), cls2 = new Class1())
这里触发cls1和cls2的Dispose条件是到达using语句末尾或者中途引发了异常并且控制离开了语句块。
如果资源1和资源2的类型不同,则可以用嵌套using的写法
using (StreamWriter sw = new ...)
{using (StreamReader sr = new ...)
{...
}
}
6. 在内存中简单的保存一些数据,只需用ListView控件。
如需求2中用户需选择多个目标文件的保存。
注意,添加行时第一列的值要这样添加:item.SubItems[0].Text = ...;
而接下来的其他列要item.SubItems.Add(...);
1 private void ShowResultTest()
2 {
3 lvSearchResult.Clear();
4
5 //设置listView的显示属性
6 lvSearchResult.GridLines = false;
7 lvSearchResult.FullRowSelect = true;
8 lvSearchResult.View = View.Details;
9 lvSearchResult.Scrollable = true;
10 lvSearchResult.MultiSelect = false;
11 lvSearchResult.HeaderStyle = ColumnHeaderStyle.Nonclickable;
12
13 // 针对数据库的字段名称,建立与之适应显示表头
14 lvSearchResult.Columns.Add("用户呢称", 150, HorizontalAlignment.Right);
15 lvSearchResult.Columns.Add("移动电话", 100, HorizontalAlignment.Left);
16 lvSearchResult.Columns.Add("电子邮箱", 150, HorizontalAlignment.Left);
17
18 //添加列表项
19 for (int index = 0; index < 5; index++)
20 {
21 ListViewItem item = new ListViewItem();
22 item.SubItems.Clear();
23 item.SubItems[0].Text = "Name" + index.ToString();
24 item.SubItems.Add("Phone"+index.ToString());
25 item.SubItems.Add("Email"+index.ToString());
26 lvSearchResult.Items.Add(item);
27
28 }
29 }
删除按钮事件:
[align=left]foreach (string filename in ofd.FileNames)[/align]
[align=left]{[/align]
[align=left] ListViewItem row = new ListViewItem();[/align]
[align=left] row.SubItems[0].Text = (++rowCount).ToString();[/align]
[align=left] row.SubItems.Add(filename);[/align]
[align=left] if (!listTarget.Items.Contains(row))[/align]
[align=left] listTarget.Items.Add(row);[/align]
}
7. 退出按钮,程序退出用Application.Exit()。
8. 读取Excel文件
(此部分转载自http://blog.csdn.net/gisfarmer/ )
另外我们还要注意一些简单的问题1.excel文件只能存储65535行数据,如果你的数据大于65535行,那么就需要将excel分割存放了。2.关于乱码,这主要是字符设置问题。
8.1.加载Excel(读取excel内容)返回值是一个DataSet
view
plain
//加载Excel
public static DataSet LoadDataFromExcel(string filePath)
{
try
{
string strConn;
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties='Excel 8.0;HDR=False;IMEX=1'";
OleDbConnection OleConn = new OleDbConnection(strConn);
OleConn.Open();
String sql = "SELECT * FROM [Sheet1$]";//可是更改Sheet名称,比如sheet2,等等
OleDbDataAdapter OleDaExcel = new OleDbDataAdapter(sql, OleConn);
DataSet OleDsExcle = new DataSet();
OleDaExcel.Fill(OleDsExcle, "Sheet1");
OleConn.Close();
return OleDsExcle;
}
catch (Exception err)
{
MessageBox.Show("数据绑定Excel失败!失败原因:" + err.Message, "提示信息",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
}
8.2.写入Excel内容,参数:excelTable是要导入excel的一个table表
view
plain
public static bool SaveDataTableToExcel(System.Data.DataTable excelTable, string filePath)
{
Microsoft.Office.Interop.Excel.Application app =
new Microsoft.Office.Interop.Excel.ApplicationClass();
try
{
app.Visible = false;
Workbook wBook = app.Workbooks.Add(true);
Worksheet wSheet = wBook.Worksheets[1] as Worksheet;
if (excelTable.Rows.Count > 0)
{
int row = 0;
row = excelTable.Rows.Count;
int col = excelTable.Columns.Count;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
string str = excelTable.Rows[i][j].ToString();
wSheet.Cells[i + 2, j + 1] = str;
}
}
}
int size = excelTable.Columns.Count;
for (int i = 0; i < size; i++)
{
wSheet.Cells[1, 1 + i] = excelTable.Columns[i].ColumnName;
}
//设置禁止弹出保存和覆盖的询问提示框
app.DisplayAlerts = false;
app.AlertBeforeOverwriting = false;
//保存工作簿
wBook.Save();
//保存excel文件
app.Save(filePath);
app.SaveWorkspace(filePath);
app.Quit();
app = null;
return true;
}
catch (Exception err)
{
MessageBox.Show("导出Excel出错!错误原因:" + err.Message, "提示信息",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return false;
}
finally
{
}
}
9. DataSet的遍历方法
C#中的Dataset就像一个数据库,有多个表(Table),一般只有一个表,然后每个表中有行(DataRow)和列(DataColumn),DataRow[DataColumn]可以得到某行某列数据。
10. 边读边修改文件的方法
创建一个新的临时文件,一边读旧文件,一边将修改结果保存到新的临时文件中。
处理完成后,将临时文件覆盖到旧文件。
只能一行一行读取
然后读取一行改一行
再把改好的每一行存入到另一个文件里
就是说边改边存
全部改好后删除源文件,重命名新文件名为源文件名
11. 总结
实践是最好的温习方式,写一个简单的小工具,就可以重新温习C#一些典型的问题。
再总结起来以供日后查阅,何乐而不为,哈哈!
1. 两个基本功能
根据源文件和新文件对比,生成对比结果文件。
对比结果要包括:新文件中更改的词条、新加的词条、删除的词条。
输入文件格式:文件开头有些注释,正文的每行由id号、空格、引号围绕的词条三部分。
对比结果文件格式:
实例1:
txt1.txt(源文件)
----------
id1 "a"
id2 "b"
id3 "c"
txt2.txt(新文件)
----------
id1 "a2"
id3 "c"
id4 "d"
生成结果:
result.txt
------------
id1 "a" "a2"
id2 "b" ""
id4 "" "d"
图形界面1
第二个功能是,专门的翻译人员将对比出来变化了的词条的翻译结果存到对比结果文件中,每种语言占据一列。
具体例子就不列了,主要来看C#的一些常见问题。
图形界面2
2. 集合类Hashtable的使用
哈希表的简单操作
查找:HashtableObject[key];
在哈希表中添加一个keyvalue键值对:HashtableObject.Add(key,value);
在哈希表中去除某个keyvalue键值对:HashtableObject.Remove(key);
从哈希表中移除所有元素: HashtableObject.Clear();
判断哈希表是否包含特定键key: HashtableObject.Contains(key);
下面控制台程序将包含以上所有操作:
using System;
using System.Collections; file使用Hashtable时,必须引入这个命名空间
class hashtable
{
public static void Main()
{
Hashtable ht=new Hashtable(); file创建一个Hashtable实例
ht.Add(E,e);添加keyvalue键值对
ht.Add(A,a);
ht.Add(C,c);
ht.Add(B,b);
string s=(string)ht[A];
if(ht.Contains(E)) file判断哈希表是否包含特定键,其返回值为true或false
Console.WriteLine(the E keyexist);
ht.Remove(C);移除一个keyvalue键值对
Console.WriteLine(ht[A]);此处输出a
ht.Clear();移除所有元素
Console.WriteLine(ht[A]); file此处将不会有任何输出
}
}
遍历哈希表
遍历哈希表需要用到DictionaryEntry Object,代码如下:
for(DictionaryEntry de in ht) fileht为一个Hashtable实例
{
Console.WriteLine(de.Key);de.Key对应于keyvalue键值对key
Console.WriteLine(de.Value);de.Key对应于keyvalue键值对value
}
3. 使用OpenDialog选取文件。
OpenFileDialog ofd = new OpenFileDialog(); // new一个方法
ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // 打开文件的默认位置
ofd.ShowDialog(); // 显示打开文件的窗口
fileName = ofd.FileName; // 获得选择的文件路径
textBox1.Text = fileName;
extendedName = Path.GetExtension(fileName); // 文件扩展名
fileName1 = Path.GetFileName(fileName); // 文件名
使用FolderBrowserDialog选取文件夹,选择对比结果文件的保存位置。
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.ShowDialog();
folderName = fbd.SelectedPath; //获得选择的文件夹路径
textBox3.Text = folderName;
4. 读写文件
StreamReader sr = new StreamReader(path, Encoding.Default);
string line;
while ((line = sr.ReadLine()) != null)
{...
}
StreamWriter sw = new StreamWriter(path, true, Encoding.Default); // true to append to existing file
sw.WriteLine(...);
5. using自动关闭文件流
using语句,定义一个范围,在范围结束时处理对象。
场景:
当在某个代码段中使用了类的实例,而希望无论因为什么原因,只要离开了这个代码段就自动调用这个类实例的Dispose。
要达到这样的目的,用try...catch来捕捉异常也是可以的,但用using也很方便。
例如:
using (Class1 cls1 = new Class1(), cls2 = new Class1())
这里触发cls1和cls2的Dispose条件是到达using语句末尾或者中途引发了异常并且控制离开了语句块。
如果资源1和资源2的类型不同,则可以用嵌套using的写法
using (StreamWriter sw = new ...)
{using (StreamReader sr = new ...)
{...
}
}
6. 在内存中简单的保存一些数据,只需用ListView控件。
如需求2中用户需选择多个目标文件的保存。
注意,添加行时第一列的值要这样添加:item.SubItems[0].Text = ...;
而接下来的其他列要item.SubItems.Add(...);
1 private void ShowResultTest()
2 {
3 lvSearchResult.Clear();
4
5 //设置listView的显示属性
6 lvSearchResult.GridLines = false;
7 lvSearchResult.FullRowSelect = true;
8 lvSearchResult.View = View.Details;
9 lvSearchResult.Scrollable = true;
10 lvSearchResult.MultiSelect = false;
11 lvSearchResult.HeaderStyle = ColumnHeaderStyle.Nonclickable;
12
13 // 针对数据库的字段名称,建立与之适应显示表头
14 lvSearchResult.Columns.Add("用户呢称", 150, HorizontalAlignment.Right);
15 lvSearchResult.Columns.Add("移动电话", 100, HorizontalAlignment.Left);
16 lvSearchResult.Columns.Add("电子邮箱", 150, HorizontalAlignment.Left);
17
18 //添加列表项
19 for (int index = 0; index < 5; index++)
20 {
21 ListViewItem item = new ListViewItem();
22 item.SubItems.Clear();
23 item.SubItems[0].Text = "Name" + index.ToString();
24 item.SubItems.Add("Phone"+index.ToString());
25 item.SubItems.Add("Email"+index.ToString());
26 lvSearchResult.Items.Add(item);
27
28 }
29 }
删除按钮事件:
[align=left]foreach (string filename in ofd.FileNames)[/align]
[align=left]{[/align]
[align=left] ListViewItem row = new ListViewItem();[/align]
[align=left] row.SubItems[0].Text = (++rowCount).ToString();[/align]
[align=left] row.SubItems.Add(filename);[/align]
[align=left] if (!listTarget.Items.Contains(row))[/align]
[align=left] listTarget.Items.Add(row);[/align]
}
7. 退出按钮,程序退出用Application.Exit()。
8. 读取Excel文件
(此部分转载自http://blog.csdn.net/gisfarmer/ )
另外我们还要注意一些简单的问题1.excel文件只能存储65535行数据,如果你的数据大于65535行,那么就需要将excel分割存放了。2.关于乱码,这主要是字符设置问题。
8.1.加载Excel(读取excel内容)返回值是一个DataSet
view
plain
//加载Excel
public static DataSet LoadDataFromExcel(string filePath)
{
try
{
string strConn;
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties='Excel 8.0;HDR=False;IMEX=1'";
OleDbConnection OleConn = new OleDbConnection(strConn);
OleConn.Open();
String sql = "SELECT * FROM [Sheet1$]";//可是更改Sheet名称,比如sheet2,等等
OleDbDataAdapter OleDaExcel = new OleDbDataAdapter(sql, OleConn);
DataSet OleDsExcle = new DataSet();
OleDaExcel.Fill(OleDsExcle, "Sheet1");
OleConn.Close();
return OleDsExcle;
}
catch (Exception err)
{
MessageBox.Show("数据绑定Excel失败!失败原因:" + err.Message, "提示信息",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
}
8.2.写入Excel内容,参数:excelTable是要导入excel的一个table表
view
plain
public static bool SaveDataTableToExcel(System.Data.DataTable excelTable, string filePath)
{
Microsoft.Office.Interop.Excel.Application app =
new Microsoft.Office.Interop.Excel.ApplicationClass();
try
{
app.Visible = false;
Workbook wBook = app.Workbooks.Add(true);
Worksheet wSheet = wBook.Worksheets[1] as Worksheet;
if (excelTable.Rows.Count > 0)
{
int row = 0;
row = excelTable.Rows.Count;
int col = excelTable.Columns.Count;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
string str = excelTable.Rows[i][j].ToString();
wSheet.Cells[i + 2, j + 1] = str;
}
}
}
int size = excelTable.Columns.Count;
for (int i = 0; i < size; i++)
{
wSheet.Cells[1, 1 + i] = excelTable.Columns[i].ColumnName;
}
//设置禁止弹出保存和覆盖的询问提示框
app.DisplayAlerts = false;
app.AlertBeforeOverwriting = false;
//保存工作簿
wBook.Save();
//保存excel文件
app.Save(filePath);
app.SaveWorkspace(filePath);
app.Quit();
app = null;
return true;
}
catch (Exception err)
{
MessageBox.Show("导出Excel出错!错误原因:" + err.Message, "提示信息",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return false;
}
finally
{
}
}
9. DataSet的遍历方法
C#中的Dataset就像一个数据库,有多个表(Table),一般只有一个表,然后每个表中有行(DataRow)和列(DataColumn),DataRow[DataColumn]可以得到某行某列数据。
foreach (DataTable dt in YourDataset.Tables)
{
foreach (DataRow dr in dt.Rows)
foreach (DataColumn dc in dt.Columns)
Console.WriteLine("{0}, {1}, {2} ", dt.TableName, dc.ColumnName,
dr[dc]);
}
10. 边读边修改文件的方法
创建一个新的临时文件,一边读旧文件,一边将修改结果保存到新的临时文件中。
处理完成后,将临时文件覆盖到旧文件。
只能一行一行读取
然后读取一行改一行
再把改好的每一行存入到另一个文件里
就是说边改边存
全部改好后删除源文件,重命名新文件名为源文件名
11. 总结
实践是最好的温习方式,写一个简单的小工具,就可以重新温习C#一些典型的问题。
再总结起来以供日后查阅,何乐而不为,哈哈!
相关文章推荐
- 开发一个小工具重温C#经典问题
- 开发一个小工具重温C#经典问题
- 开发一个小工具重温C#经典问题
- 转载一个很经典的--C# Socket TCP和UDP报文及端口测试工具的开发(提供源码)
- 发现浏览器开发工具的一个小问题
- 转载一个ie的F12开发人员工具不显示问题
- 用C#开发的一个通用的地铁换乘查询工具
- 一个用C#开发的.NET开发工具
- [项目管理]工程与产品开发的差异——一个老项目的经典问题
- C#使用TcpListener及TcpClient开发一个简单的Chat工具实例
- 关于C#来开发类似画CAD图的工具的问题
- c#2.0开发的一个文本字符串替换工具,控制台工具,可以批量替换
- 用C#开发一个WinForm版的批量图片压缩工具
- 用C#开发一个WinForm版的批量图片压缩工具
- 利用c#开发一个telnet unix服务器或者防火墙的小工具(转)
- [C#]使用TcpListener及TcpClient开发一个简单的Chat工具
- 在知乎回答的一个问题:C#初学者以后往WP开发走,还是往unity3d走?哪个更有前景呢
- MVC5中Model层开发数据注解 EF Code First Migrations数据库迁移 C# 常用对象的的修饰符 C# 静态构造函数 MSSQL2005数据库自动备份问题(到同一个局域网上的另一台电脑上) MVC 的HTTP请求
- 用c#开发了一个asp.net网站,遇Session超时的问题
- 解决一个问题,发布一个自己开发的小工具