【问题标题】:How to read a portion of a line in a text file?如何读取文本文件中一行的一部分?
【发布时间】:2020-09-18 10:42:19
【问题描述】:

所以,我有一个包含数千行格式的文本文件:

123456:0.8525000:1590882780:91011

这些文件的长度几乎总是不同的,我只需要阅读该行的前两部分,即123456:0.8525000。

我知道我可以使用 C# 拆分每一行,但我不确定如何只读取前 2 部分。任何人都知道如何做到这一点?对不起,如果我的问题没有意义,如果需要,我可以重新提出。

【问题讨论】:

  • 当您说“仅读取前 2 部分”时,您是在尝试优化文件读取的某些方面吗?在低级别,必须扫描文件的每个字节才能找到 EOL 标记。更直接地说:为什么拆分对你不起作用?
  • 如果文件行总是固定宽度或者你需要提取的部分总是16个字符,做一个substing,对于大文件会更快
  • 这能回答你的问题吗? To get specific part of a string in c#

标签: c#


【解决方案1】:

有很多方法可以做到这一点,但我将建议一些涉及阅读整行的选项,因为它更容易使用/理解,并且你的行长度不同。我确实在附录末尾添加了关于在文件上使用 StreamReader 的建议,但您可能需要找出认真的解决方法来跳过您不想要的行、在新行上重新启动字符迭代循环等。

我首先演示了 NetCore 3.x 中最新最好的 IAsyncEnumerable,然后是类似的基于字符串的方法。通过分享一个稍微高级且也是异步的 Int 示例,我希望也能帮助其他人,并在 2020 年展示一种相当现代的方法。仅流式传输您需要的数据对于保持快速和内存占用少。

public static async IAsyncEnumerable<int> StreamFileOutAsIntsAsync(string filePathName)
{
    if (string.IsNullOrWhiteSpace(filePathName)) throw new ArgumentNullException(nameof(filePathName));
    if (!File.Exists(filePathName)) throw new ArgumentException($"{filePathName} is not a valid file path.");

    using var streamReader = File.OpenText(filePathName);
    string currentLine;

    while ((currentLine = await streamReader.ReadLineAsync().ConfigureAwait(false)) != null)
    {
        if (int.TryParse(currentLine.AsSpan(), out var output))
        {
            yield return output;
        }
    }
}

这会将每个 int 从文件中流出,检查文件是否存在以及文件名路径是否为空或空白等。

串流对于初学者来说可能太多了,所以我不知道你的水平。

您可能只想将文件转换为字符串列表。

将我之前的示例修改为不太复杂的内容,但为您拆分字符串。我建议学习流式传输,这样您在处理它时就不会在内存中保留所有字符串......或者您可能想要它们全部。我不是来评判的。

一旦你从文件中取出你的字符串行,你就可以做任何其他需要做的事情了。

public static async Task<List<string>> GetStringsFromFileAsync(string filePathName)
{
    if (string.IsNullOrWhiteSpace(filePathName)) throw new ArgumentNullException(nameof(filePathName));
    if (!File.Exists(filePathName)) throw new ArgumentException($"{filePathName} is not a valid file path.");

    using var streamReader = File.OpenText(filePathName);

    string currentLine;
    var strings = new List<string>();

    while ((currentLine = await streamReader.ReadLineAsync().ConfigureAwait(false)) != null)
    {
        var lineAsArray = currentLine.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries);

        // Simple Data Validation
        if (lineAsArray.Length == 4)
        {
            strings.Add($"{lineAsArray[0]}:{lineAsArray[1]}");
            strings.Add($"{lineAsArray[2]}:{lineAsArray[3]}");
        }
    }

    return strings;
}

代码的肉真的很简单,打开文件阅读!

using var streamReader = File.OpenText(filePathName);

然后循环遍历该文件...

while ((currentLine = await streamReader.ReadLineAsync()) != null)
{
    var lineAsArray = currentLine.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries);

    // Simple Data Validation
    if (lineAsArray.Length == 4)
    {
        // Do whatever you need to do with the first bits of information.
        // In this case, we add them all to a list for return.
        strings.Add($"{lineAsArray[0]}:{lineAsArray[1]}");
        strings.Add($"{lineAsArray[2]}:{lineAsArray[3]}");
    }
}

这表明,对于我读出的每一行不为空,分成四个部分(基于“:”)字符删除所有空条目。

然后,我们使用称为字符串插值 ($"") 的 C# 功能将前两个与“:”一起作为字符串。然后是后两个。或者你需要做的任何事情来阅读每一行。

这就是它的全部内容!希望对您有所帮助。

附录:如果您确实需要读取部分文件,请使用 StreamReader.Read 和 Peek()

using (var sr = new StreamReader(path))
{
    while (sr.Peek() >= 0)
    {
        Console.Write((char)sr.Read());
    }
}

Reading each character

【讨论】:

    【解决方案2】:

    一些简单的代码:

    string fileName = @"c:\some folder\path\file.txt";
    using (StreamReader sr = new StreamReader(fileName))
    {
        while (!sr.EndOfStream)
        {
            String[] values = sr.ReadLine().Split(":".ToCharArray());
            if (values.Length >= 2)
            {
                // ... do something with values[0] and values[1] ...
                Console.WriteLine(values[0] + ", " + values[1]);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      Split 函数返回一个string[],一个strings 的数组。

      只取Split结果的前2个元素(以:为分隔符)。

          var read = "123456:0.8525000:1590882780:91011";
          var values = read.Split(":");
          Console.WriteLine(values[0]); // 123456
          Console.WriteLine(values[1]); // 0.8525000
      

      .NET Fiddle

      不要忘记 values 的元素是 string 而不是 int 或 double 值。字符串转数字类型见How to convert string to integer in C#。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-05
        • 2014-04-30
        • 1970-01-01
        相关资源
        最近更新 更多