从具有混合数据类型的 CSV 文件中读取数据
本文关键字:文件 读取 数据 CSV 混合 数据类型 | 更新日期: 2023-09-27 18:33:18
只要每个'项目'都是数字或每个项目都是字母数字,这就可以工作。 当我有数字和字母数字的"项目"时,它无法正确填写值。
这是代码:
public void updateInventory()
{
try
{
if (File.Exists(inventoryUpdateDirectory + "inventoryUpdate.csv"))
{
csvReader csv = new csvReader();
DataTable inventory = csv.read(inventoryUpdateDirectory + "inventoryUpdate.csv");
//int test = inventory.Rows.Count;
string sql = "";
foreach (DataRow inventoryItem in inventory.Rows)
{
try
{
sql = " Update Inventory set OnHand = " + inventoryItem[1] + " WHERE Sku = '" + inventoryItem[0].ToString().Trim() + "'";
//executeSQL(sql);
}
catch { }
}
File.Delete(inventoryUpdateDirectory + "inventoryUpdate.csv");
}
else
{
writeToFile("fileDoesntExist", inventoryUpdateDirectory + "error.txt");
}
}
catch { }
}
这是它读取的文件:
ALB001,0
ALB002,66
10001,0
10016,348
这将起作用:
ALB001,0
ALB002,66
这将起作用:
10001,0
10016,348
这将不起作用:
ALB001,0
ALB002,66
10001,0
10016,348
它将inventoryItem
数组填充为空{}
+ inventoryItem[0] {} object {System.DBNull}
哪个应该具有ALB001
的值
CSV 中的第一个"列"应始终被视为字符串,因为它可以包含字母数,第二个"列"将始终是数字。
有人能帮我解决这个问题吗?
我想我只需要编辑 sql 查询以将它们转换为字符串,但我不确定。
CSV 阅读器编辑:
namespace CSV
{
public class csvReader
{
public DataTable read(string strFileName)
{
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; Data Source = " + System.IO.Path.GetDirectoryName(strFileName) + "; Extended Properties = '"Text;HDR=NO;FMT=Delimited'"");
conn.Open();
string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]";
OleDbDataAdapter adapter = new OleDbDataAdapter(strQuery, conn);
DataSet ds = new DataSet("CSV File");
adapter.Fill(ds);
return ds.Tables[0];
}
public DataTable read(string strFileName, bool firstRowHeaders)
{
string hdr = "NO";
if (firstRowHeaders) { hdr = "YES"; }
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; Data Source = " + System.IO.Path.GetDirectoryName(strFileName) + "; Extended Properties = '"Text;HDR=" + hdr + ";FMT=Delimited'"");
conn.Open();
string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]";
OleDbDataAdapter adapter = new OleDbDataAdapter(strQuery, conn);
DataSet ds = new DataSet("CSV File");
adapter.Fill(ds);
return ds.Tables[0];
}
}
}
问题显然出在 CsvReader 类中。由于您没有附加其源代码,因此很难知道为什么它没有用内容填充该数据表,我能做的最好的事情就是猜测。
我会尽力帮助你,建议你使用这个来自codeproject的csv阅读器:http://www.codeproject.com/Articles/86973/C-CSV-Reader-and-Writer
您不需要使用数据表,因为它使您能够使用简单的 while 循环遍历文件行。您的代码将如下所示:
using (CsvReader reader = new CsvReader(FilePath, Encoding.Default))
{
while (reader.ReadNextRecord())
{
sql = " Update Inventory set OnHand = " + reader.Fields[1] + " WHERE Sku = '" + reader.Fields[0] + "'";
}
}
我知道这是一个较老的问题,我已经尝试了很多事情来解决与此类似的问题,所以我想我会提供我的解决方案。 即使我使用的是 C#,您也可以继承 VB 库,并且 TextFieldParser 库可以很好地处理这个问题。 对于我的数据,我不知道将导入多少列,尽管每一行的列数相同。 某些列包含逗号,但不用引号 " 括起来。我首先创建了一个 DataTable 将所有列转换为字符串,稍后我将在其中验证类型。我还删除了文件具有的标题行,我首先用于创建数据表。 我希望这可以帮助某人。
我正在使用的数据示例:
标头 1,标头2,标头 3
A,123,A
B,123,A
C,A,一些数据,然后 更多数据
这是我最终想出的解决方案,效果很好。
using Microsoft.VisualBasic.FileIO;
private static DataTable GetDataTableFromCsv(string path)
{
var dataTable = new DataTable("ImportData");
var rows = File.ReadAllLines(path);
var columns = rows[0].Split(',');
foreach (var column in columns)
{
dataTable.Columns.Add(new DataColumn(column.Trim(), typeof(string)));
}
using (var parser = new TextFieldParser(path))
{
parser.Delimiters = new[] { "," };
while (true)
{
var parts = parser.ReadFields();
dataTable.Rows.Add(parts);
if (parser.EndOfData) break;
}
}
dataTable.Rows[0].Delete();
return dataTable;
}
在下面的示例中,我在 OnHand 值周围添加了单引号,以告诉 SQL 它应该始终需要一个字符串。 您最好将SQL语句更改为使用"@Parameters"并内联分配值。
sql = " Update Inventory set OnHand = '" + inventoryItem[1] + "' WHERE Sku = '" + inventoryItem[0].ToString().Trim() + "'";
您可以使用 LINQ 读取 CSV
var data = (from line in File.ReadAllLines(fileName).AsParallel()
select line.Split(',')).ToList();
然后进行适当的铸造,更新。