在删除标题的同时将相同的 CSV 附加在一起
Posted
技术标签:
【中文标题】在删除标题的同时将相同的 CSV 附加在一起【英文标题】:Appending identical CSVs together while removing headers 【发布时间】:2011-10-02 23:24:50 【问题描述】:我想将 6 个具有相同布局和标题的 CSV 附加在一起。
我已经能够通过将 6 个 csv 中的每一个加载到它们自己的单独数据表中并删除每个数据表的第一行来完成此操作。最后,我使用 ImportRow 方法将它们附加在一起。
DataTable table1 = csvToDataTable(@"C:\Program Files\Normalization\Scan1.csv");
DataTable table2 = csvToDataTable(@"C:\Program Files\Normalization\Scan2.csv");
DataTable table3 = csvToDataTable(@"C:\Program Files\Normalization\Scan3.csv");
DataTable table4 = csvToDataTable(@"C:\Program Files\Normalization\Scan4.csv");
DataTable table5 = csvToDataTable(@"C:\Program Files\Normalization\Scan5.csv");
DataTable table6 = csvToDataTable(@"C:\Program Files\Normalization\Scan6.csv");
foreach (DataRow dr in table2.Rows)
table1.ImportRow(dr);
foreach (DataRow dr in table3.Rows)
table1.ImportRow(dr);
foreach (DataRow dr in table4.Rows)
table1.ImportRow(dr);
foreach (DataRow dr in table5.Rows)
table1.ImportRow(dr);
foreach (DataRow dr in table6.Rows)
table1.ImportRow(dr);
CreateCSVFile(table1, @"C:\Program Files\Normalization\RackMap.csv");
我觉得这很笨拙且扩展性不强,但是当我尝试在 CSV 级别追加时,我在处理标题时遇到了麻烦。有什么建议吗?
TIA
【问题讨论】:
【参考方案1】:获取与掩码*.csv
匹配的所有文件的DirectoryInfo
创建一个 for 循环来迭代结果。
导入每个文件时删除第一行。
编辑:
如果您只想合并文件,而不是导入数据表,您可以将它们视为文本文件。连接它们,每次都删除标题行。这是一个例子:
string myPath = @"K:\csv";
DirectoryInfo csvDirectory = new DirectoryInfo(myPath);
FileInfo[] csvFiles = csvDirectory.GetFiles("*.csv");
StringBuilder sb = new StringBuilder();
foreach (FileInfo csvFile in csvFiles)
using (StreamReader sr = new StreamReader(csvFile.OpenRead()))
sr.ReadLine(); // Discard header line
while (!sr.EndOfStream)
sb.AppendLine(sr.ReadLine());
File.AppendAllText(Path.Combine(myPath, "output.csv"), sb.ToString());
【讨论】:
我已经有一种方法可以在将每个 csv 导入数据表时删除第一行。我正在寻找一种解决方案,将这些 csv 在 CSV 级别合并在一起(同时删除标题),然后将最终的 csv 加载到数据表中。如果不需要,我宁愿不使用创建 6 个数据表的内存。 @kmc 我添加了一个示例,使用三个 12MB 的 csv 文件进行了测试。 将其分解为文本文件级别的好主意。我想多了。这 10 行替换了我写的大约 100 行。非常感谢。 很高兴能提供帮助。正如 mikemann 建议的那样,请注意特殊情况,例如空文件、不存在或不同的标题等。您比其他任何人都更了解输入文件的潜力。干杯! :)【参考方案2】:如果您不想重复相同的行,那么您可以创建哈希码列表并在循环中查找列表是否包含行的哈希码。
List<int> rowHashCodes = new List<int>();
foreach (DataRow dr in table2.Rows)
int hash = dr.GetHashCode();
if (rowHashCodes.Contains(hash))
// We already have this row
else
table1.ImportRow(dr);
rowHashCodes.Add(hash);
从性能的角度来看,这可能不是理想的方式,但我希望这可以解决您的问题。
【讨论】:
【参考方案3】:正如 JYelton 建议的那样,您肯定希望动态查找文件夹中的所有 *.csv 文件,并对其进行迭代(而不是硬编码 6 个文件名)。从那时起,您可能会考虑这样的方法:
-
为您的“目标”文件创建一个可写文件流。
为每个 .CSV 文件打开一个可读的文件流。
通过读取直到并包括第一个 CRLF 并丢弃该数据来丢弃每个文件的标题行。
将所有剩余数据读入可写流。
对每个 CSV 文件重复 #2-4。
关闭可写流以保存完成的文件。
这种方法可以容纳任意数量的 CSV 文件,并且可能比使用 DataTables 更高效。
注意:为了简洁明了,我省略了一些你需要做的边缘情况处理。就像如何处理一个空的 csv 文件,或者一个包含标题行而没有其他内容的文件,或者一个在其最后一行之后没有尾随 CRLF 的文件。实现细节和边缘案例处理不是很有趣吗? ;)
【讨论】:
以上是关于在删除标题的同时将相同的 CSV 附加在一起的主要内容,如果未能解决你的问题,请参考以下文章
将相同的字符串附加到PowerShell中CSV列中的所有变量
使用特定于列的重复过滤器在 Python 中将行附加到 CSV