【问题标题】:Pull separate columns from .csv into separate arrays in c#将 .csv 中的单独列拉到 c# 中的单独数组中
【发布时间】:2013-10-24 20:55:05
【问题描述】:

这个项目的背景。它最初是一项简单的家庭作业,需要我存储 5 个邮政编码及其对应的城市。当用户在文本框中输入邮政编码时,会返回相应的城市,反之亦然。我编写了返回这些值的代码,但后来我决定将所有邮政编码及其对应的城市存储在外部 .csv 中,并将这些值存储在数组中并运行代码,因为如果它值得做,它就值得过头了!澄清一下,这不再是家庭作业,只是为了了解更多关于在 C# 中使用外部文件的信息。

在下面的代码中,我已经调用成功打开文件,现在我只需要帮助弄清楚如何提取存储在两个单独列中的数据(一列用于城市,一列用于邮政编码)并存储它们在两个数组中,由 for 循环执行。这是我现在拥有的代码。您可以看到我之前如何将其他值存储在数组中并将它们取出:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void btnConvert2City_Click(object sender, EventArgs e)
    {
        try
        {
            string dir = System.IO.Path.GetDirectoryName(
                System.Reflection.Assembly.GetExecutingAssembly().Location);

            string path = dir + @"\zip_code_database_edited.csv";
            var open = new StreamReader(File.OpenRead(path));

            int EnteredZipcode = Convert.ToInt32(txtZipcode.Text.Trim());
            string result = "No Cities Found";

            string[] Cities = new String[5] { "FLINTSTONE", "JAMAICA", "SCHENECTADY", "COTTONDALE", "CINCINNATI" };
            int[] Zipcode = new int[5] { 30725, 11432, 12345, 35453, 45263 };

            for (int i = 0; i <= Zipcode.Length - 1; i++)
            {
                if (Zipcode[i] == EnteredZipcode)
                {
                    result = Cities[i];
                    break;
                }
            }
            string DisplayState = result;
            txtCity.Text = DisplayState;
        }
        catch (FormatException)
        {
            MessageBox.Show("Input must be numeric value.");
        }
        catch (OverflowException)
        {
            MessageBox.Show("Zipcode to long. Please Re-enter");
        }
    }

    private void btnConvert2Zipcode_Click(object sender, EventArgs e)
    {
        string dir = System.IO.Path.GetDirectoryName(
                System.Reflection.Assembly.GetExecutingAssembly().Location);

        string path = dir + @"\zip_code_database_edited.csv";
        var open = new StreamReader(File.OpenRead(path));

        String EnteredCity = txtCity.Text.ToUpper();
        string result = "No Zipcode Found";

        string[] Cities = new String[5] { "FLINTSTONE", "JAMAICA", "SCHENECTADY", "COTTONDALE", "CINCINNATI" };
        int[] Zipcode = new int[5] { 30725, 11432, 12345, 35453, 45263 };

        for (int i = 0; i <= Cities.Length - 1; i++)
        {
            if (Cities[i] == EnteredCity)
            {
                result = Convert.ToString(Zipcode[i]);
                break;
            }
        }           
        string DisplayZip = result;
        txtZipcode.Text = DisplayZip;
    }       
}

以下数据是我的 excel .csv 中数据的样子:

zip,primary_city
44273,Seville
44274,Sharon Center
44275,Spencer
44276,Sterling
44278,Tallmadge
44280,Valley City
44281,Wadsworth
44282,Wadsworth
44285,Wayland

以此类推,大约有 46,000 行。

如何将 zip 和 primary_city 拉入两个单独的数组(我猜是一些“.Split”、“line”),我的 for 循环可以在这些数组上运行?

另外,如果有更好的方法来解决这个问题,请告诉我(但请务必留下解释,因为我想了解您来自哪里)。

【问题讨论】:

  • 有很多读取 CSV 的示例和几个成熟的 CSV 阅读器。只需使用它们。如果您需要自己编写代码(假设它仍然用于家庭作业) - 请先尝试,然后使用小示例代码和详细的解释/错误文本/不起作用的消息提出问题。
  • CSV parser/reader for C#? 的可能重复项

标签: c# arrays excel csv for-loop


【解决方案1】:

不要创建两个单独的数组。为城市创建一个单独的类

class City
{
    public string Name{get;set;}
    public int ZipCode{get;set;}
}

现在从该 csv 文件中读取数据

List<City> cities=File.ReadAllLines(path)
                      .Select(x=>new City
                         {
                              ZipCode=int.Parse(x.Split(',')[0]),
                              Name=x.Split(',')[1]
                         }).ToList<City>();

或者你可以这样做

   List<City> cities=new List<City>();
   foreach(String s in File.ReadAllLines(path))
   {
       City temp=new City();
       temp.ZipCode=int.Parse(s.Split(',')[0]);
        temp.Name=s.Split(',')[1];
       cities.Add(temp);
   }

【讨论】:

  • 我正在使用您的第二个建议,但我遇到了 temp.ZipCode = int.Parse(s.Split(',')[0]); 的问题线。我收到 FormatException 错误。我正在尝试解决这个问题(似乎不认为我在为 ZipCode 输入数值)。有任何想法吗?解决此问题后,我会将其标记为答案。
  • @MarkP。在调试模式下,查看 s 包含的内容。很可能该字符串中可能有超过 1 个 , ..
  • 我相信解决了。因为我的 .csv 的第一行是 zip,primary_city,所以它会提取该值,而不是实际包含 zip 的第一行。我只需要编辑我的 .csv... 就可以了。有趣的。我不聪明...谢谢!
  • 我认为 foreach 中的 foreach 看起来很奇怪:P 感谢您的帮助!
【解决方案2】:

你可以试试这个:

    string dir = System.IO.Path.GetDirectoryName(
            System.Reflection.Assembly.GetExecutingAssembly().Location);

    string path = dir + @"\zip_code_database_edited.csv";
    var open = new StreamReader(File.OpenRead(path));
    var cities = new HashList<string>();
    var zipCodes = new HashList<int>();
    var zipAndCity = new string[2];
    string line = string.Empty;
    using (open)
{
        while ((line = reader.ReadLine()) != null)
        {
            zipAndCity = line.Split(",");
                zipCodes.Add(int.Parse(zipAndCity[0]));
                cities.Add(zipAndCity[1]);   
        }

}

【讨论】:

  • 我似乎遇到了 HashList 的问题。 Visual Studio 无法识别它,我已经初始化了所有正确的库(命名空间?)......有什么想法吗?
【解决方案3】:

自从我发布这个问题以来,我已经了解了更多关于 C# 的知识,因此我发布了这个答案。读取 CSV 时,有比String.Split() 更好的选择。

.NET Framework 已经有一个内置的专用 CSV 解析器,称为 TextFieldParser

它位于 Microsoft.VisualBasic.FileIO 命名空间中。

String.Split() 不仅有许多边缘情况无法正确处理,而且使用StreamReader 的速度也慢得多。

【讨论】:

    猜你喜欢
    • 2011-01-26
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 2018-11-22
    • 2014-06-10
    • 2018-05-17
    相关资源
    最近更新 更多