只读取文本文件中的某些列

Read only certain columns from a text file

我需要从一个文本文件中读取并且只从中获取某些数据。文本文件有多行,类似下面

12/05/2014 06:52 c:\BACKUPS\INT100\BACKUP\BACKUP.ZIP 
12/05/2014 06:51 c:\BACKUPS\INT1000\BACKUP\BACKUP.ZIP

我需要日期、时间和数字(在本例中为 100 和 1000),但无法弄清楚如何摆脱 "c:\backups\INT" 和“\BACKUP\BACKUP 等其他内容.ZIP".

我想过使用子字符串方法,但它只能部分起作用。再加上INT号可以在1-9999之间。

这就是我目前从文本文件读取数据到 DataTable 然后再到 GridView:

StreamReader readData = new StreamReader(@"c:\Users84814\desktop\date.txt");

DataTable listOFDates = new DataTable();
listOFDates.Columns.Add("Dates");

while (!readData.EndOfStream)
{
    string shortenLine = readData.ReadLine();

    // shortenLine = shortenLine.Substring(0, 35);

    listOFDates.Rows.Add(shortenLine);
}
gv_textFile.DataSource = listOFDates;

如果 "12/05/2014 06:51 c:\BACKUPS\INT1000\BACKUP\BACKUP.ZIP" 是一致的格式,那么你可以这样做,假设 Lines 是一个字符串 [] 与你的文件行:

string[] Lines= File.ReadAllLines("file.txt");

foreach(var Line in Lines)
{
 string[] Parameters= Line.Split(' ');
 string Date= Parameters[0];
 string Time= Parameters[1];
 string[] PathInfo= Parameters[2].Split('\');
 int Number= Convert.ToInt32(PathInfo[2].Replace("Int",""));
}

如果您的路径并不总是相同的,我可以为您提供另一个示例。

可能的解决方案

 StreamReader readData = new StreamReader(@"c:\Users84814\desktop\date.txt");

 DataTable listOFDates = new DataTable();
 listOFDates.Columns.Add("Dates", typeof(DateTime));
 listOFDates.Columns.Add("Numbers", typeof(int));

 while (!readData.EndOfStream)
 {
     string line = readData.ReadLine();
     string[] parts = line.Split(' ');
     DateTime dt = DateTime.ParseExact(string.Join(" ", parts[0], parts[1]), "dd/MM/yyyy hh:mm", CultureInfo.CurrentCulture, DateTimeStyles.None);
     int number = Convert.ToInt32(Regex.Match(parts[2], @"\d+").Value);
     listOFDates.Rows.Add(new object[] {dt, number});
 }
 gv_textFile.DataSource = listOFDates;

当然,这假设您的日期部分始终采用上述格式,并且路径中的数字仅在该位置出现一次。

如果所有行都相同,您可以获得日期,然后是那些行的数字:

var text = File.ReadAllLines(@"c:\Users84814\desktop\date.txt");

var dates = text.Select(line => DateTime.Parse(line.Substring(0, 16)));
var numbers = text.Select(line => line.Substring(31, line.IndexOf(@"\BACKUP\") - 31));

对于日期,您取字符串的开头并将其解析为 DateTime

对于数字,获取数字索引,然后取东西,直到您点击 \BACKUP\ 部分(这是数字之后的最小唯一部分)。 -31 是因为 Substring 采用 length,而不是结束索引。

如果你提取幻数:

const int END_OF_DATE = 16;
const int START_OF_NUMBER = 31;

var text = File.ReadAllLines(@"c:\Users84814\desktop\date.txt");

var dates = text.Select(line => DateTime.Parse(line.Substring(0, END_OF_DATE)));
var numbers = text.Select(line => line.Substring(START_OF_NUMBER, line.IndexOf(@"\BACKUP\") - START_OF_NUMBER));

您最终得到两个 IEnumerable,您可以用它们填充您的行。

之后有多种方法可以添加您的值,但是如果我们按照您的操作进行操作(将每个条目手动添加为一行),您可以通过使用 for 循环遍历这些值来实现该结果:

DataTable listOFDates = new DataTable();
listOFDates.Columns.Add("Dates");
listOFDates.Columns.Add("Numbers");
for (int i = 0; i < dates.Count(); i++)
{
    listOFDates.Rows.Add(dates[i], numbers[i]);
}

我们可以安全地迭代具有相同索引的两个列表,因为我们知道它们具有相同的大小。

但是,此方法需要您通过添加 .ToList() 以及日期和数字查询的末尾将之前的 LINQ 查询转换为列表。如果您希望将其保留为通用 IEnumerable 而不是列表,您可以使用 .ElementAt(i) 而不是 [i]

如果您正在使用 DataTable,您还可以使用 OLEDB 来像处理数据库一样处理文本文件。您将使用 SQL 查询与文件交互。

只需导入 System.Data.OleDb 并像使用任何其他数据库一样使用 OleDb 对象(连接、数据读取器等)。当然,您不会有存储过程,但是您可以使用参数化查询。

如果您使用正确的连接字符串,这也适用于 Excel 个文件。

更多信息: http://www.connectionstrings.com/textfile/

这并非始终是正确的方法,但有时它正是您所需要的。