【问题标题】:How can I write a string to format row data to save as a CSV file?如何编写字符串来格式化行数据以保存为 CSV 文件?
【发布时间】:2017-10-27 05:55:09
【问题描述】:

我目前有一个程序,它使用 StreamReader 访问 CSV 文件并将值存储在数据网格中,但是在保存此数据时,它会为数据行的每一列值打印一个新行。

程序当前将 csv 文件打印为:

headerText、headerText、headerText、headerText
第 1 栏、第 2 栏、第 1 栏、第 2 栏、第 3 栏、第 1 栏、第 2 栏、第 3 栏、第 4 栏

我需要打印的是:

headerText、headerText、headerText、headerText
第 1 栏、第 2 栏、第 3 栏、第 4 栏

string CsvFpath = "C:/StockFile/stockfiletest.csv";

try
{
    StreamWriter csvFileWriter = new StreamWriter(CsvFpath, false);
    string columnHeaderText = "";
    int countColumn = stockGridView.ColumnCount - 1;

    if (countColumn >= 0)
    {
        columnHeaderText = stockGridView.Columns[0].HeaderText;
    }

    for (int i = 1; i <= countColumn; i++)
    {
        columnHeaderText = columnHeaderText + ',' + stockGridView.Columns[i].HeaderText;
    }

    csvFileWriter.WriteLine(columnHeaderText);

    foreach (DataGridViewRow dataRowObject in stockGridView.Rows)
    {
        if (!dataRowObject.IsNewRow)
        {
            string dataFromGrid = "{0} += {1} += {2} += {3}";
            dataFromGrid = dataRowObject.Cells[0].Value.ToString();

            for (int i = 1; i <= countColumn; i++)
            {
                dataFromGrid = dataFromGrid + ',' + dataRowObject.Cells[i].Value.ToString();
                csvFileWriter.Write(dataFromGrid);
            }
            csvFileWriter.WriteLine();
        }
    }

    csvFileWriter.Dispose();

    MessageBox.Show("Saved stockfile.csv");
}
catch (Exception exceptionObject)
{
    MessageBox.Show(exceptionObject.ToString());
}

谁能告诉我我的字符串格式有什么问题以及如何实现所需的文件输出?

【问题讨论】:

  • 请注意,发明自己的序列化代码通常是个坏主意...有很多现有的 CSV 库可以处理来自值的引号、逗号和其他有趣的字符...
  • @Alexei Levenkov 谢谢你的建议,在这个项目中我被限制在某些条件下,我目前正在学习编程 cert IV 所以即使我不能在这个项目上使用那个建议我肯定会将来带上它,如果我能找到一种更简单的方法,我会一直采用它,有时懒惰可能是一件好事,因为它不使用比必要更多的代码或使用其他来源更好地执行功能。谢谢伙计,我会接受你的建议。

标签: c# string csv datagridview


【解决方案1】:

正如另一个答案中提到的,问题是您在处理每一列时写入文件inside,而不是在循环之后,当您已收集该行的所有列信息。

您可以这样做的另一种方法是使用string.Join 和System.Linq 更简洁地连接每行的列值。

还请注意,我们可以将 csvFileWriter 包装在 using 块中,以便在块执行完成时自动关闭并释放它:

using (var csvFileWriter = new StreamWriter(CsvFpath, false))
{
    // Write all the column headers, joined with a ','
    csvFileWriter.WriteLine(string.Join(",",
        stockGridView.Columns.Cast<DataGridViewColumn>().Select(col => col.HeaderText)));

    // Grab all the rows that aren't new and, for each one, join the cells with a ','
    foreach (var row in stockGridView.Rows.Cast<DataGridViewRow>()
        .Where(row => !row.IsNewRow))
    {
        csvFileWriter.WriteLine(string.Join(",",
            row.Cells.Cast<DataGridViewCell>().Select(cell => cell.Value.ToString())));
    }
}

另一件事:除了编写自己的 csv 解析器之外,您还可以使用现有的工具来编写 csv 文件,例如 CsvHelper,它们将处理可能导致问题的其他类型的边缘情况,例如有逗号。

【讨论】:

  • 那段代码工作得非常完美,它也让我看到了清理和简化代码是多么容易,我之前的块与你的 sn-p 相比就像一本书,所以非常感谢很多。这是非常赞赏和重视的知识。
【解决方案2】:

你的问题在这里:

for (int i = 1; i <= countColumn; i++)
{
  dataFromGrid = dataFromGrid + ',' + dataRowObject.Cells[i].Value.ToString();
      csvFileWriter.Write(dataFromGrid);
}

您每次都添加到字符串中......并且在任何时候都不会清除它。所以在第 1 行第一列你得到 ",col1" col2 是 ",col1,col2" .. 但你每次也写出来..

有一个 CSV 写入器类,但是,您可以做您正在做的事情,但是,只需将写入移出循环,然后将其重置。不过..

for (int i = 1; i <= countColumn; i++)
{
      if (i>1) csvFileWriter.Write(",");
      csvFileWriter.Write(dataRowObject.Cells[i].Value.ToString());
}

会阻止你在开始时获得额外的“,”,并在开始时写

【讨论】:

  • 非常感谢您指出我做错了什么,当 Rufus 发布他的代码 sn-p 时,我正处于实践过程中,它不仅完美运行,还向我展示了如何我可以将过大的代码块减少到更易读和更易于管理的东西。您的帮助非常宝贵,再次感谢。
猜你喜欢
  • 2012-02-27
  • 1970-01-01
  • 2018-08-09
  • 2022-08-23
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 1970-01-01
  • 2016-06-01
相关资源
最近更新 更多