簡體   English   中英

將文本文件轉換為列表<int> (C#)</int>

[英]Converting Text File into a List <int> (C#)

我正在使用此鏈接作為起點。 我對 C# 完全陌生,但有 C/C++ 方面的經驗。 我的目標是重新創建排序算法並讓它們使用分叉相互競爭。 我已經成功地重新創建了歸並排序、冒泡和插入,並計划實施快速排序。

我創建了一個單獨的 class,它創建了一個包含 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++;
}

我從將這些整數存儲到數組列表中的主要 class 得到的錯誤此時失敗:

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

//錯誤:System.FormatException:'輸入字符串的格式不正確。'

據我所知,當它轉換整數時,它會獲取一個不是 integer 的值並且失敗。 但是,對我來說令人困惑的部分是當我手動輸入整數時它工作得很好。

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

任何幫助將不勝感激。

C#Nooby

正如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塊中使用。

要讀取文件並將其內容轉換為List<int> ,您可以使用以下代碼:

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方法生成的空條目/子字符串 這將確保無錯誤的字符串到整數的轉換。

下面,您可以找到一個完整的最小工作解決方案來解決您的問題。

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);
        }
    }
}

查看您遇到的錯誤,在我看來您沒有考慮換行符(至少我能夠以這種方式重現它)。

這就是它對包含新行的文件的工作方式(我使用了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()

我可以給你兩個解決方案。 其中之一是修改您用來創建帶有數字的文件的代碼。 另一個是通過您告訴我們的鏈接修改您正在使用的代碼。

您的代碼中的問題出在 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++;
}

第二種可能的解決方案

在您用於讀取文件的代碼中,只需從每行中刪除空白空格,然后再使用 function.Trim() 拆分為數組

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

而不是當前行

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM