【问题标题】:Converting Text File into a List <int> (C#)将文本文件转换为列表 <int> (C#)
【发布时间】:2020-03-13 03:10:50
【问题描述】:

我使用这个link 作为起点。我对 C# 完全陌生,但在 C/C++ 方面有经验。我的目标是重新创建排序算法并让它们使用分叉相互竞争。我已经成功地重新创建了归并排序、冒泡和插入,并计划实施快速排序。

我创建了一个单独的类,该类创建一个包含 100,000 个随机整数的文件,以正确测试排序算法的速度。

StreamWriter sw = new StreamWriter(@"C:\pathtofile\randomNumbers.txt");

int count = 0;
Random rnd = new Random();
int randomNumber;
int lines = 0;
while (count++ < 100000)
{
    randomNumber = rnd.Next(1, 250);
    sw.Write(randomNumber);
    sw.Write(" "); // create white space
    if(lines == 25) //formatting
    {
        sw.WriteLine("");
        lines = 0;
    }
    lines++;
}

我从将这些整数存储到数组列表中的主类得到的错误此时失败:

lists.Add(Convert.ToInt32(listInts[j]));

//ERROR: System.FormatException: '输入字符串不正确 格式。'

据我所知,当它转换整数时,它会抓取一个不是整数的值并失败。但是,对我来说令人困惑的部分是当我手动输入整数时它工作得很好。

例如:134 0 13 42 232 48 424 166 109

任何帮助将不胜感激。

C#Nooby

【问题讨论】:

  • Use your debugger 查看listInts[j] 的值。它不是整数。
  • 您显示的代码不完整,提供 MCVE 或至少显示更多代码,特别是您从文件中读取的部分,因为在您显示的代码中,它可能正在写入文件或标准控制台输出(sw 是什么)?
  • 抱歉,本网站的格式是新手。括号切断了一行代码。我现在编辑了。
  • 如果不显示读取代码,我能说的最好的就是您应该在阅读时注意换行符,并用' '(空格)标记分割您的读取行,并注意最后一个元素返回的数组的末尾可能会附加“\n”。

标签: c# string arraylist text-files


【解决方案1】:

正如vetzascoaStas Ivanov 所提到的,您的代码中的异常可能是由未处理的空格和空字符串引起的。

为了解决这个问题,您可以修改将测试数据写入文件的方法如下:

static string Delimiter => " ";
static string LineBreak => "\r\n";

static void WriteTestFile(string fileName,
    int dataLength = 100000,
    int dataMinvalue = 1,
    int dataMaxValue = 250,
    int lineBreakPosition = 25)
{
    int iterator = 0;
    string delimiter;

    Random rndGenerator = new Random();
    int randomNumber;

    using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
    using (var streamWriter = new StreamWriter(fileStream))
    {
        while (iterator < dataLength)
        {
            randomNumber = rndGenerator.Next(dataMinvalue, dataMaxValue);
            delimiter = ++iterator % lineBreakPosition == 0 ? LineBreak : Delimiter;
            streamWriter.Write($"{randomNumber}{delimiter}");
        }
    }
}

通过这种方式,您可以避免在每行末尾出现多余的空格。另外,注意 FileStreamStreamReaderStreamWriterIDisposable 对象。因此,它们在using(...)try/finally 块内should be used

要读取文件并将其内容转换为List&lt;int&gt;,您可以使用以下代码:

static List<int> ReadTestFile(string fileName)
{
    string fileContents;

    using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
    using (var streamReader = new StreamReader(fileStream))
    {
        fileContents = streamReader.ReadToEnd();
    }

    var separators = string.Join("", LineBreak, Delimiter).ToCharArray();
    var query = from item in fileContents
                 .Split(separators, StringSplitOptions.RemoveEmptyEntries)                        
                 select int.Parse(item);

    return query.ToList();
}

使用StringSplitOptions.RemoveEmptyEntries 选项拆分文件内容字符串将由String.Split 方法生成exclude empty entries/substrings。这将确保无错误的字符串到整数的转换。

您可以在下面找到一个完整的最小可行解决方案来解决您的问题。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace FileToListInt
{
    class Program
    {
        static readonly string filePath = "randomNumbers.txt";

        static string Delimiter => " ";
        static string LineBreak => "\r\n";

        static void WriteTestFile(string fileName,
            int dataLength = 100000,
            int dataMinvalue = 1,
            int dataMaxValue = 250,
            int lineBreakPosition = 25)
        {
            int iterator = 0;
            string delimiter;

            Random rndGenerator = new Random();
            int randomNumber;

            using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
            using (var streamWriter = new StreamWriter(fileStream))
            {
                while (iterator < dataLength)
                {
                    randomNumber = rndGenerator.Next(dataMinvalue, dataMaxValue);
                    delimiter = ++iterator % lineBreakPosition == 0 ? LineBreak : Delimiter;
                    streamWriter.Write($"{randomNumber}{delimiter}");
                }
            }
        }

        static List<int> ReadTestFile(string fileName)
        {
            string fileContents;

            using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            using (var streamReader = new StreamReader(fileStream))
            {
                fileContents = streamReader.ReadToEnd();
            }

            var separators = string.Join("", LineBreak, Delimiter).ToCharArray();
            var query = from item in fileContents
                         .Split(separators, StringSplitOptions.RemoveEmptyEntries)                        
                         select int.Parse(item);

            return query.ToList();
        }

        static void Main(string[] args)
        {
            // Writing data to a test file
            WriteTestFile(filePath);

            // Reading result into a List<int>
            List<int> data = ReadTestFile(filePath);

            // Checking the number of readings
            Console.WriteLine(data.Count);

            // Deleting test file
            if (File.Exists(filePath))
                File.Delete(filePath);
        }
    }
}

【讨论】:

  • 非常感谢!另外,也感谢大家。没想到反应这么快。我将不得不筛选您在此处列出的所有这些方法调用,因为其中一些我不知道它们做什么以及为什么。但这为我学习 C# 打下了良好的基础。此外,这对我有用。谢谢!
  • 不客气!我很高兴它对你有用。如果您将此解决方案标记为已接受的答案,我将不胜感激。如果您对方法调用/逻辑有任何疑问,请在 cmets 中询问。
【解决方案2】:

查看您遇到的错误,在我看来您没有考虑换行符(至少我能够以这种方式重现它)。

这就是它对包含新行的文件的工作方式(我使用了 Split 的重载,它接受要分割的字符数组,此外它会忽略空条目,因为提供 StringSplitOptions):

using (var reader = new StreamReader(@"c:\temp\test.txt"))
{       
    var text = await reader.ReadToEndAsync();       
    var numbers = text.Split(new [] {' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).Select(word => Convert.ToInt32(word));
    // do something with numbers (IEnumerable<Int32>)
}

上面的代码将数字存储到一个 IEnumerable 集合中。如果你需要一个数组,你应该调用 ToArray()

【讨论】:

    【解决方案3】:

    我可以给你两个解决方案。 其中之一是修改您用来创建带有数字的文件的代码。 另一个是通过您告诉我们的链接修改您正在使用的代码。

    代码中的问题在于 while 循环内部,当您写入文件时出现空白:

    randomNumber = rnd.Next(1, 250);
    sw.Write(randomNumber);
    sw.Write(" "); // create white space  <------ this line
    

    这一行总是在数字后面写一个空格。这意味着您的文件将以空格结尾,而不是数字。这会导致行中的异常

    lists.Add(Convert.ToInt32(listInts[j])); 
    

    因为为文件的最后一行生成了listInts[j] = " "。

    第一个可能的解决方案

    当你要在文件中写入一个空白空间时,只有在写入最后一个数字之后才这样做。 您的 while 循环应该类似于:

    while (count++ < 100000)
    {
        randomNumber = rnd.Next(1, 250);
        sw.Write(randomNumber);
        if (count < 100000) //avoid write a white space if is last number to write
        {
            sw.Write(" "); // create white space
        }
        if(lines == 25) //formatting
        {
            sw.WriteLine("");
            lines = 0;
        }
        lines++;
    }
    

    第二种可能的解决方案

    在您用于读取文件的代码中,只需在使用函数 .Trim() 拆分为数组之前从每行中删除空白空格

    String[] listInts = listLines[i].Trim().Split(' ');
    

    代替当前行

    String[] listInts = listLines[i].Split(' ');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-19
      • 2013-06-12
      • 2023-03-10
      • 2014-03-04
      • 2016-04-14
      相关资源
      最近更新 更多