C# 解析txt文件,经典问题! 本帖最后由 gidiyis 于 2010-02-02 23:37:52 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 楼主的实际问题一定不会是这几行数据了.可以把这两类数据建成三个数据表表1: 试样信息 aa|10|1|良好商品| ...表2: 产品信息 abc|10|测试1|2|备注| ...表3: 产品统计 id,name,count,res,goodproductNo,badproductNo用数据库解决统计问题就很容易了。 string[] temp = System.IO.File.ReadAllLines("E:\\aaa.txt", System.Text.Encoding.GetEncoding("gb2312")); Dictionary<int, product> dic = new Dictionary<int, product>(); foreach (string s in temp) { if (s.StartsWith("abc")) { string[] pInfo = s.Split('|'); int id = int.Parse(pInfo[1]); if (!dic.ContainsKey(id)) { product p = new product(); p.id = id; p.name = pInfo[2]; p.count = int.Parse(pInfo[3]); p.res = pInfo[4]; dic.Add(id, p); } } else if (s.StartsWith("aa")) { string[] qInfo = s.Split('|'); int id = int.Parse(qInfo[1]); if (dic.ContainsKey(id)) { product p = dic[id]; int count = int.Parse(qInfo[2]); string quality = qInfo[3]; if (quality == "良好商品") p.goodproductNo += count; else if (quality == "不良商品") p.badproductNo += count; } } } foreach (int i in dic.Keys) { product p = dic[i]; Console.WriteLine("Id:{0},name:{1},count:{2},res:{3},goodproductNo:{4},badproductNo:{5}", p.id, p.name, p.count, p.res, p.goodproductNo, p.badproductNo); }/*输出:Id:10,name:测试1,count:2,res:备注,goodproductNo:2,badproductNo:0Id:11,name:测试2,count:3,res:备注,goodproductNo:2,badproductNo:1*/ 支持读到datatable里,然后再操作 3楼的程序设计是对的,可以满足楼主的需求,csdn高手还是很多啊,欣喜................ 读到DataTable中,然后循环呗判断呗或者先直接把每行都new一个pruduct实例,这样你就可以得到一个List<Product>的集合,然后用linq来写判断条件跟方便了 用OLEDB 连接TXT文件 用sql语句 查询载入文件前创建txt分割相关的配置文件 abc表示该行描述的是一个产品,10/11代表产品编号,2表示产品数量 aa表示该行是对产品的描述信息(产品良好或不良),10/11来自abc编号,1表示产品数量最好把这两个能分成两个文件存储。 这才是正解...虽然效率也一般,但在数据源不能改变时这个才能叫解决方案...用ReadAllLines这个txt文件很大怎么办?数据源改变时怎么办?重ReadAllLines? static void Main(string[] args) { string FilePath = @"C:\Users\chenjun\Desktop"; INIClass iniMake = new INIClass(@"C:\Users\chenjun\Desktop\Schema.ini"); iniMake.IniWriteValue("11.txt", "Format", "Delimited(|)"); iniMake.IniWriteValue("11.txt", "ColNameHeader", "false"); iniMake.IniWriteValue("11.txt", "col1", "RowType TEXT WIDTH 100 "); iniMake.IniWriteValue("11.txt", "col2", "ProductID TEXT WIDTH 100 "); iniMake.IniWriteValue("11.txt", "col3", "Colmn1 TEXT WIDTH 100"); iniMake.IniWriteValue("11.txt", "col4", "Colmn2 TEXT WIDTH 100 "); iniMake.IniWriteValue("11.txt", "col5", "Colmn3 TEXT WIDTH 100 "); string constr = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + FilePath + "';Extended Properties='text;HDR=No;FMT=Delimited(|);'"; OleDbDataAdapter da = new OleDbDataAdapter(); OleDbConnection OConn = new OleDbConnection(); OConn.ConnectionString = constr; OConn.Open(); OleDbCommand OCmm = new OleDbCommand(); OCmm.Connection = OConn; da.SelectCommand = OCmm; OCmm.CommandTimeout = 0; DataTable ProtuctTable = new DataTable(); DataTable QualityTable = new DataTable(); OCmm.CommandText = "Select ProductID,Colmn1 as ProductName,Colmn2 as ProductCount,Colmn3 as ProductComment from [11.txt] where RowType='abc'"; da.Fill(ProtuctTable); OCmm.CommandText = "Select ProductID,Sum(Colmn1) as Amount,Colmn2 as ProductMass from [11.txt] where RowType='aa' Group By ProductID,Colmn2"; da.Fill(QualityTable); da.Dispose(); OCmm.Dispose(); OConn.Dispose(); foreach (DataRow dr in ProtuctTable.Rows) { DataRow[] rows = QualityTable.Select("ProductID=" + dr["ProductID"]); foreach (DataRow row in rows) { Console.WriteLine(dr["ProductID"] + " " + dr["ProductName"] + " " + row["ProductMass"] + " " + row["Amount"]); } } Console.ReadLine(); } INIClass /// <summary> /// ini文件操作 /// </summary> public class INIClass { public string inipath; [DllImport("kernel32")] private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); [DllImport("kernel32")] private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath); /// <summary> /// 构造方法 /// </summary> /// <param name="INIPath">文件路径</param> public INIClass(string INIPath) { inipath = INIPath; } /// <summary> /// 写入INI文件 /// </summary> /// <param name="Section">项目名称(如[TypeName] )</param> /// <param name="Key">键</param> /// <param name="Value">值</param> public void IniWriteValue(string Section, string Key, string Value) { WritePrivateProfileString(Section, Key, Value, this.inipath); } /// <summary> /// 读出INI文件 /// </summary> /// <param name="Section">项目名称(如[TypeName] )</param> /// <param name="Key">键</param> public string IniReadValue(string Section, string Key) { StringBuilder temp = new StringBuilder(500); int i = GetPrivateProfileString(Section, Key, "", temp, 500, this.inipath); return temp.ToString(); } } 对txt硬搞不是好办法吧,最好以这个txt为数据库来操作用txt做数据源连接字符串//text作为数据源的链接字符串 string strConnection = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\test;Extended Properties=""text;HDR=Yes;FMT=Delimited"";";注意:c:\\test是个文件夹,里面有相应的txt文档做数据源。 http://blog.csdn.net/LCL_data/archive/2009/12/18/5032160.aspx ojlovecd (三楼)确实是高人啊,谢谢你的解答,我的问题解决了 闲来无事,参照3楼的改写成逐行分析的,这样在文件较大时候也不会出问题了,呵呵 有剽窃嫌疑……using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;namespace ParseTXT{ class Program { static void Main(string[] args) { string TxtFilePath = "Product.txt"; Dictionary<int, Product> productDic = new Dictionary<int, Product>(); using (StreamReader TxtSR = new StreamReader(TxtFilePath, Encoding.GetEncoding("gb2312"))) { String temp = TxtSR.ReadLine(); while (!string.IsNullOrEmpty(temp)) { Console.WriteLine(temp); string[] tempProduct = temp.Split('|'); if (tempProduct[0] == "abc") { int productID = Int32.Parse(tempProduct[1]); if (!productDic.ContainsKey(productID)) { Product pro = new Product(); pro.id = Int32.Parse(tempProduct[1]); pro.name = tempProduct[2]; pro.count = Int32.Parse(tempProduct[3]); productDic.Add(productID, pro); } } if (tempProduct[0] == "aa") { int productID = Int32.Parse(tempProduct[1]); if (tempProduct[3] == "良好商品") { productDic[productID].goodproductNo += Int32.Parse(tempProduct[2]); } if (tempProduct[3] == "不良商品") { productDic[productID].badproductNo += Int32.Parse(tempProduct[2]); } } temp = TxtSR.ReadLine(); } } //TxtSR.Close(); foreach (int productID in productDic.Keys) { Console.WriteLine( "Product Name: {0}, "+ "Product Count: {1}, "+ "Product Good Number: {2}, "+ "Product Bad Number: {3}", productDic[productID].name, productDic[productID].count, productDic[productID].goodproductNo, productDic[productID].badproductNo); } } } class Product { public Product() { // } public int id; public string name; public int count;//(数量) public bool res; public int goodproductNo; //(良品数量) public int badproductNo;//(次品数量) }} /// <summary> /// 读入一个pds导出的管线文件,通过参数返回 /// </summary> /// <param name="FilePath">文件路径</param> /// <param name="data">数据</param> /// <param name="columns">列表栏位</param> /// <param name="Msg">消息,成功读取时为空,由于考虑需要一次对整个文件进行检验,所以没有直接抛出异常,而使用msg返回</param> /// <returns>bool</returns> public bool PipingFileReader(string FilePath, out List<Dictionary<string, string>> data, out List<string> columns, out string Msg) { string strLine; string strHeader; string strDataArea; string[] strArray; char[] charArray = new char[] {'|'}; int RowCnt = 0; int cntHeaderColumns; int cntDataAreaCloums; int cntDataAreaRows = 0; //初始返回 data = new List<Dictionary<string, string>>(); columns = new List<string>(); Msg = ""; try { FileStream aFile = new FileStream(FilePath, FileMode.Open); StreamReader sr = new StreamReader(aFile,Encoding.Default);//使用默认编码,防止乱码 // Obtain the columns from the first line // Split row of data into string array strLine = sr.ReadLine(); RowCnt++; //顺序读取直到表头区域 while (strLine != null) { if (IsHeaderRow(strLine)) { break; } strLine = sr.ReadLine(); RowCnt++; } //对数据表头进行检查 if (CheckTableHeader(strLine)) { strHeader = TrimHeaderRow(strLine); strArray = strHeader.Split(charArray); cntHeaderColumns = strArray.GetUpperBound(0);//GetUpperBound(0) 返回 Array 的第一维的索引上限,GetUpperBound(Rank - 1) 返回 Array 的最后一维的上限。此方法的运算复杂度为 O(1)。 columns.Add("行号");//记录该行数据在源文件中的行号 for (int x = 0; x <= cntHeaderColumns; x++) { columns.Add(strArray[x].Trim()); } } else { Msg = "错误的单线材料表表头\r\n"; return false; } strLine = sr.ReadLine(); RowCnt++; while (strLine != null) { if (IsDataRow(strLine)) {//如果遇到数据行 // Split row of data into string array strDataArea = TrimDataRow(strLine); strArray = strDataArea.Split(charArray); Dictionary<string, string> dataRow = new Dictionary<string, string>(); cntDataAreaCloums=strArray.GetUpperBound(0); if (cntDataAreaCloums != cntHeaderColumns) { Msg += "第" + RowCnt + "数据格式错误\r\n"; } else { dataRow.Add("行号", RowCnt.ToString());//记录该行数据在源文件中的行号 for (int x = 0; x <= cntDataAreaCloums; x++) { //将索引该为1,0号位已经改为“行号” dataRow.Add(columns[x + 1], strArray[x].Trim()); //但是此索引任然应该从0开始 } data.Add(dataRow); cntDataAreaRows++; } } strLine = sr.ReadLine(); RowCnt++; } sr.Close(); if (Msg == "") { if (cntDataAreaRows % 2 == 0) { return true; } else { Msg = "数据区异常:没有保存数据区的2行缺省\r\n"; return false; } } else { return false; } } catch (IOException ex) { Msg += ex.ToString(); return false; } } /// <summary> /// 对单线转换为datatable的预处理 /// </summary> /// <param name="Path">文件路径</param> /// <param name="Msg">错误消息</param> /// <returns></returns> public DataTable PrePipingTable(string Path, out string Msg) { List<Dictionary<string, string>> data; List<string> columns; DataTable dt = new DataTable(); bool IsSuccess = PipingFileReader(Path, out data, out columns,out Msg); if (!IsSuccess) { return dt; } foreach (string column in columns) { dt.Columns.Add(column,System.Type.GetType("System.String")); } foreach (Dictionary<string, string> row in data) { DataRow dr = dt.NewRow(); foreach (string clolumn in columns) { dr[clolumn] = row[clolumn]; } dt.Rows.Add(dr); } return dt; }给你个参考,这个是我写的读pds单线材料表的类,格式和你这个差不多,只是有验证,所以你稍微删除修改下就可以把你那个文件读到datatable了,想做什么都统计都好办了。可以通用的。 C#的treeview节点选择 电子报的实现 求助,调用shell命令从fstp下载文件,process.WaitForExit()无响应 这样使用PictureImage 控件是否正确 sql 查询问题 100分求各位强人给看看啊!修复IIS的时候出现这个错误,怎么解决啊 C# 批量请求访问网络的方式 【讨论,求助】 C# 如何一次过隐藏全部 show 出来的窗体~~ webApp 中,在网页resize的时候怎么能让程序不破坏页面的布局呢? 如何保存用户设置,如果用ini文件,该怎么做?---当天结贴 【求助】winform连接数据库的问题 郁闷了
表1: 试样信息 aa|10|1|良好商品| ...
表2: 产品信息 abc|10|测试1|2|备注| ...
表3: 产品统计 id,name,count,res,goodproductNo,badproductNo用数据库解决统计问题就很容易了。
string[] temp = System.IO.File.ReadAllLines("E:\\aaa.txt", System.Text.Encoding.GetEncoding("gb2312"));
Dictionary<int, product> dic = new Dictionary<int, product>();
foreach (string s in temp)
{
if (s.StartsWith("abc"))
{
string[] pInfo = s.Split('|');
int id = int.Parse(pInfo[1]);
if (!dic.ContainsKey(id))
{
product p = new product();
p.id = id;
p.name = pInfo[2];
p.count = int.Parse(pInfo[3]);
p.res = pInfo[4];
dic.Add(id, p);
}
}
else if (s.StartsWith("aa"))
{
string[] qInfo = s.Split('|');
int id = int.Parse(qInfo[1]);
if (dic.ContainsKey(id))
{
product p = dic[id];
int count = int.Parse(qInfo[2]);
string quality = qInfo[3];
if (quality == "良好商品")
p.goodproductNo += count;
else if (quality == "不良商品")
p.badproductNo += count;
}
}
}
foreach (int i in dic.Keys)
{
product p = dic[i];
Console.WriteLine("Id:{0},name:{1},count:{2},res:{3},goodproductNo:{4},badproductNo:{5}", p.id, p.name, p.count, p.res, p.goodproductNo, p.badproductNo);
}
/*
输出:
Id:10,name:测试1,count:2,res:备注,goodproductNo:2,badproductNo:0
Id:11,name:测试2,count:3,res:备注,goodproductNo:2,badproductNo:1*/
载入文件前创建txt分割相关的配置文件
aa表示该行是对产品的描述信息(产品良好或不良),10/11来自abc编号,1表示产品数量最好把这两个能分成两个文件存储。
{
string FilePath = @"C:\Users\chenjun\Desktop"; INIClass iniMake = new INIClass(@"C:\Users\chenjun\Desktop\Schema.ini"); iniMake.IniWriteValue("11.txt", "Format", "Delimited(|)");
iniMake.IniWriteValue("11.txt", "ColNameHeader", "false");
iniMake.IniWriteValue("11.txt", "col1", "RowType TEXT WIDTH 100 ");
iniMake.IniWriteValue("11.txt", "col2", "ProductID TEXT WIDTH 100 ");
iniMake.IniWriteValue("11.txt", "col3", "Colmn1 TEXT WIDTH 100");
iniMake.IniWriteValue("11.txt", "col4", "Colmn2 TEXT WIDTH 100 ");
iniMake.IniWriteValue("11.txt", "col5", "Colmn3 TEXT WIDTH 100 ");
string constr = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + FilePath + "';Extended Properties='text;HDR=No;FMT=Delimited(|);'";
OleDbDataAdapter da = new OleDbDataAdapter();
OleDbConnection OConn = new OleDbConnection();
OConn.ConnectionString = constr;
OConn.Open();
OleDbCommand OCmm = new OleDbCommand();
OCmm.Connection = OConn;
da.SelectCommand = OCmm;
OCmm.CommandTimeout = 0;
DataTable ProtuctTable = new DataTable();
DataTable QualityTable = new DataTable();
OCmm.CommandText = "Select ProductID,Colmn1 as ProductName,Colmn2 as ProductCount,Colmn3 as ProductComment from [11.txt] where RowType='abc'";
da.Fill(ProtuctTable);
OCmm.CommandText = "Select ProductID,Sum(Colmn1) as Amount,Colmn2 as ProductMass from [11.txt] where RowType='aa' Group By ProductID,Colmn2";
da.Fill(QualityTable);
da.Dispose();
OCmm.Dispose();
OConn.Dispose();
foreach (DataRow dr in ProtuctTable.Rows)
{
DataRow[] rows = QualityTable.Select("ProductID=" + dr["ProductID"]);
foreach (DataRow row in rows)
{
Console.WriteLine(dr["ProductID"] + " " + dr["ProductName"] + " " + row["ProductMass"] + " " + row["Amount"]);
}
}
Console.ReadLine();
}
/// ini文件操作
/// </summary>
public class INIClass
{
public string inipath;
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
/// <summary>
/// 构造方法
/// </summary>
/// <param name="INIPath">文件路径</param>
public INIClass(string INIPath)
{
inipath = INIPath;
}
/// <summary>
/// 写入INI文件
/// </summary>
/// <param name="Section">项目名称(如[TypeName] )</param>
/// <param name="Key">键</param>
/// <param name="Value">值</param>
public void IniWriteValue(string Section, string Key, string Value)
{
WritePrivateProfileString(Section, Key, Value, this.inipath);
}
/// <summary>
/// 读出INI文件
/// </summary>
/// <param name="Section">项目名称(如[TypeName] )</param>
/// <param name="Key">键</param>
public string IniReadValue(string Section, string Key)
{
StringBuilder temp = new StringBuilder(500);
int i = GetPrivateProfileString(Section, Key, "", temp, 500, this.inipath);
return temp.ToString();
}
}
string strConnection = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\test;
Extended Properties=""text;HDR=Yes;FMT=Delimited"";";注意:c:\\test是个文件夹,里面有相应的txt文档做数据源。
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;namespace ParseTXT
{
class Program
{
static void Main(string[] args)
{
string TxtFilePath = "Product.txt";
Dictionary<int, Product> productDic = new Dictionary<int, Product>();
using (StreamReader TxtSR = new StreamReader(TxtFilePath, Encoding.GetEncoding("gb2312")))
{
String temp = TxtSR.ReadLine();
while (!string.IsNullOrEmpty(temp))
{ Console.WriteLine(temp);
string[] tempProduct = temp.Split('|');
if (tempProduct[0] == "abc")
{
int productID = Int32.Parse(tempProduct[1]);
if (!productDic.ContainsKey(productID))
{
Product pro = new Product();
pro.id = Int32.Parse(tempProduct[1]);
pro.name = tempProduct[2];
pro.count = Int32.Parse(tempProduct[3]);
productDic.Add(productID, pro);
}
}
if (tempProduct[0] == "aa")
{
int productID = Int32.Parse(tempProduct[1]);
if (tempProduct[3] == "良好商品")
{
productDic[productID].goodproductNo += Int32.Parse(tempProduct[2]);
}
if (tempProduct[3] == "不良商品")
{
productDic[productID].badproductNo += Int32.Parse(tempProduct[2]);
} } temp = TxtSR.ReadLine();
}
}
//TxtSR.Close();
foreach (int productID in productDic.Keys)
{
Console.WriteLine(
"Product Name: {0}, "+
"Product Count: {1}, "+
"Product Good Number: {2}, "+
"Product Bad Number: {3}", productDic[productID].name, productDic[productID].count, productDic[productID].goodproductNo, productDic[productID].badproductNo);
}
}
} class Product
{
public Product()
{
//
}
public int id;
public string name;
public int count;//(数量)
public bool res;
public int goodproductNo; //(良品数量)
public int badproductNo;//(次品数量)
}
}
/// <summary>
/// 读入一个pds导出的管线文件,通过参数返回
/// </summary>
/// <param name="FilePath">文件路径</param>
/// <param name="data">数据</param>
/// <param name="columns">列表栏位</param>
/// <param name="Msg">消息,成功读取时为空,由于考虑需要一次对整个文件进行检验,所以没有直接抛出异常,而使用msg返回</param>
/// <returns>bool</returns>
public bool PipingFileReader(string FilePath, out List<Dictionary<string, string>> data, out List<string> columns, out string Msg)
{
string strLine;
string strHeader;
string strDataArea;
string[] strArray;
char[] charArray = new char[] {'|'};
int RowCnt = 0;
int cntHeaderColumns;
int cntDataAreaCloums;
int cntDataAreaRows = 0;
//初始返回
data = new List<Dictionary<string, string>>();
columns = new List<string>();
Msg = ""; try
{
FileStream aFile = new FileStream(FilePath, FileMode.Open);
StreamReader sr = new StreamReader(aFile,Encoding.Default);//使用默认编码,防止乱码 // Obtain the columns from the first line // Split row of data into string array
strLine = sr.ReadLine();
RowCnt++;
//顺序读取直到表头区域
while (strLine != null)
{
if (IsHeaderRow(strLine))
{
break;
}
strLine = sr.ReadLine();
RowCnt++;
}
//对数据表头进行检查
if (CheckTableHeader(strLine))
{
strHeader = TrimHeaderRow(strLine);
strArray = strHeader.Split(charArray);
cntHeaderColumns = strArray.GetUpperBound(0);//GetUpperBound(0) 返回 Array 的第一维的索引上限,GetUpperBound(Rank - 1) 返回 Array 的最后一维的上限。此方法的运算复杂度为 O(1)。
columns.Add("行号");//记录该行数据在源文件中的行号
for (int x = 0; x <= cntHeaderColumns; x++)
{
columns.Add(strArray[x].Trim());
}
}
else
{
Msg = "错误的单线材料表表头\r\n";
return false;
}
strLine = sr.ReadLine();
RowCnt++;
while (strLine != null)
{
if (IsDataRow(strLine))
{//如果遇到数据行
// Split row of data into string array
strDataArea = TrimDataRow(strLine);
strArray = strDataArea.Split(charArray);
Dictionary<string, string> dataRow = new Dictionary<string, string>();
cntDataAreaCloums=strArray.GetUpperBound(0);
if (cntDataAreaCloums != cntHeaderColumns)
{
Msg += "第" + RowCnt + "数据格式错误\r\n";
}
else
{
dataRow.Add("行号", RowCnt.ToString());//记录该行数据在源文件中的行号
for (int x = 0; x <= cntDataAreaCloums; x++)
{ //将索引该为1,0号位已经改为“行号”
dataRow.Add(columns[x + 1], strArray[x].Trim());
//但是此索引任然应该从0开始
}
data.Add(dataRow);
cntDataAreaRows++;
}
}
strLine = sr.ReadLine();
RowCnt++;
} sr.Close();
if (Msg == "")
{
if (cntDataAreaRows % 2 == 0)
{
return true;
}
else
{
Msg = "数据区异常:没有保存数据区的2行缺省\r\n";
return false;
}
}
else
{
return false;
}
}
catch (IOException ex)
{
Msg += ex.ToString();
return false;
}
} /// <summary>
/// 对单线转换为datatable的预处理
/// </summary>
/// <param name="Path">文件路径</param>
/// <param name="Msg">错误消息</param>
/// <returns></returns>
public DataTable PrePipingTable(string Path, out string Msg)
{
List<Dictionary<string, string>> data;
List<string> columns;
DataTable dt = new DataTable();
bool IsSuccess = PipingFileReader(Path, out data, out columns,out Msg);
if (!IsSuccess)
{
return dt;
} foreach (string column in columns)
{
dt.Columns.Add(column,System.Type.GetType("System.String"));
} foreach (Dictionary<string, string> row in data)
{
DataRow dr = dt.NewRow();
foreach (string clolumn in columns)
{
dr[clolumn] = row[clolumn];
}
dt.Rows.Add(dr);
}
return dt;
}给你个参考,这个是我写的读pds单线材料表的类,格式和你这个差不多,只是有验证,所以你稍微删除修改下就可以把你那个文件读到datatable了,想做什么都统计都好办了。可以通用的。