【问题标题】:Read delimited text files dynamically动态读取分隔文本文件
【发布时间】:2021-03-27 21:42:54
【问题描述】:

我想根据标题动态读取文本文件。考虑这样的例子

name|email|phone|othername|company
john|john@example.com|1234||example
doe|doe@example.com||pin
jane||98485|

下面的记录要这样读取的值

name  email               phone  othername  company
john  john@example.com    1234              example
doe   doe@example.com              pin        
jane                      98485        

我试过用这个

using (StreamReader sr = new StreamReader(new MemoryStream(textFile)))
{
while (sr.Peek() >= 0)
{
       string line = sr.ReadLine(); //Using readline method to read text file.
       string[] strlist = line.Split('|'); //using string.split() method to split the string.
       Obj obj = new Obj();

       obj.Name = strlist[0].ToString();
       obj.Email = strlist[1].ToString();
       obj.Phone  = strlist[2].ToString();
       obj.othername = strlist[3].ToString();
       obj.company = strlist[4].ToString();
}
}                         

如果所有分隔符都被准确放置,上面的代码就可以工作,但是当像上面那样动态给出时,上面的代码就不起作用了。有什么可能的解决方案吗?

【问题讨论】:

  • 什么是“不起作用”,会发生什么,“动态”是什么意思?您的意思是列名可能不同,您要查找的数据可能位于其他位置?
  • 不,我的意思是如果给定的文本文件只有两列的数据,它就不起作用。如果文本文件只有 2 列,则不会读取它们
  • c# 4.0?真的吗?
  • 在使用特定索引之前检查数组长度,以确保您没有遇到 Index out of Range 异常。
  • @VDWWD 但我将获得不同数量的数据。只有标题会被修复。

标签: c# asp.net .net c#-4.0


【解决方案1】:

如果您对此有任何控制权,则应该使用更好的序列化技术,或者至少使用可以处理这种格式的 csv 解析器。但是,如果你想使用string.Split,你也可以利用ElementAtOrDefault

返回序列中指定索引处的元素或默认值 索引超出范围时的值。

给定

public class Data
{
   public string Name { get; set; }
   public string Email { get; set; }
   public string Phone { get; set; }
   public string OtherName { get; set; }
   public string Company { get; set; }
}

用法

var results = File
   .ReadLines(SomeFileName)           // stream the lines from a file
   .Skip(1)                           // skip the header
   .Select(line => line.Split('|'))   // split on pipe
   .Select(items => new Data()        // populate some funky class 
   {
      Name = items.ElementAtOrDefault(0),
      Email = items.ElementAtOrDefault(1),
      Phone = items.ElementAtOrDefault(2),
      OtherName = items.ElementAtOrDefault(3),
      Company = items.ElementAtOrDefault(4)
   });


foreach (var result in results)
   Console.WriteLine($"{result.Name}, {result.Email}, {result.Phone}, {result.OtherName}, {result.Company}");

输出

john, john@example.com, 1234, , example
doe, doe@example.com, , pin,
jane, , 98485, ,

【讨论】:

  • 如果它作为一个单独的对象存在,比如public class Data { public Details details {get; set;} public OtherDetails otherDetails {get; set;}} 会怎样?
  • @ismav 你必须先创建这些子属性
  • 你能用一些代码解释一下吗,我想不通。我是新开发者。
  • @ismav new Data() { details = new Details { Name = items.ElementAtOrDefault(0)}, ...
  • 假设有一个datetime类型的字段怎么处理?像这样DOB = items.ElementAtOrDefault(11),其中 DOB 的类型是日期时间
【解决方案2】:

当您像string[] strlist = line.Split('|'); 这样拆分行时,您可能会得到不希望的结果。
例如:jane||98485| 生成一个只有 4 个元素的数组,您可以在此处查看 https://rextester.com/WBOT6074 在线。

您应该在生成数组strList 后检查它,就像测量大小一样。
由于您没有就问题给出明确的细节,我无法给出更具体的答案。

【讨论】:

  • 编辑问题,让你更好地理解
  • 您是否尝试过这是问题所在?如果您在说您的代码无法正常工作时告诉我们您遇到了什么样的问题,那将会很有帮助。
猜你喜欢
  • 1970-01-01
  • 2019-12-07
  • 2019-09-05
  • 1970-01-01
  • 2016-08-16
  • 2013-09-26
  • 2023-03-31
  • 2020-05-15
  • 1970-01-01
相关资源
最近更新 更多