尝试从 .csv 文件解析和转换文本时出错
Error when trying to Parse & Convert text from a .csv file
我目前一直在尝试使 .csv 文件中最后一列的输出正常工作。我需要将其转换为货币。我不确定我是否对整个专栏使用 (i == 6)(如果这甚至是可行的)或者我是否必须这样做 (i == 13 || i == 20 || i == 27) 等每个需要转换为货币的值。
我想要完成的事情:
单击加载库存按钮时,将读取库存记录
使用“打开文件对话框”控件从文本文件中读取,从文件中读取的行被标记为字段值、解析(根据需要),然后加载到列表框和 class 实例列表中。 ListBox(和 class 实例列表)除了包含输入文件中的所有字段值外,还应包含 QtyHand 和 Sales 列。 String.Format() 或 PadRight() 方法可用于设置列表框内容的格式,使列中的所有值都对齐,假设您使用的是等宽字体。
.csv 文件的前两行是:
Id,Item Name,StartingQty,QtyMinRestck,QtySold,QtyRStcked,UnitPrice
85-0521031,Shampoo,35,9,0,0,2.89
非常感谢任何帮助解决这个问题的人。
public partial class inventoryForm : Form
{
OpenFileDialog ipFile = new OpenFileDialog();
public inventoryForm()
{
InitializeComponent();
}
private void loadInvDataButton_Click(object sender, EventArgs e)
{
inventoryListBox.Items.Clear(); //clear listbox items
if (ipFile.ShowDialog() == DialogResult.OK) //show dialog box
{
string[] file = File.ReadAllLines(ipFile.FileName); //tokenize
foreach (string line in file) //for each line in the file ...
{
string[] inventory = line.Split(','); //tokens contain numbers from the .csv file
for (int i = 0; i < inventory.Length; i++) //loop goes through each item in the inventory
{
if (i == 6) //items in the csv file that require conversion
{
double price = double.Parse(inventory[i]); //convert the value to currency, then pad
inventory[i] = String.Format("{0:C2}", price).PadRight(20, ' ');
}
else
{
inventory[i] = inventory[i].PadRight(20, ' '); //just pad the string
}
}
string item = string.Join("", inventory);
inventoryListBox.Items.Add(item);
}
}
}
}
好吧,这是没有其他细节的快速解决方案,但简而言之,您需要存储新格式化项目的方法,我希望这对您来说已经足够清楚了。更新为格式更好的代码。
static void Main(string[] args)
{
List<string> outputList = new List<string>();
string[] list = new string[] { "85 - 0521031, Shampoo, 35, 9, 0, 0, 2.89", "86 - 0521031, Guitar, 35, 9, 0, 0, 9.89" };
for(var i=0; i<list.Length; i++)
{
var listItem = list[i].Split(',');
var outputListItem = "";
for (var j=0; j<listItem.Length; j++)
{
if(j == 6)
{
double price = double.Parse(listItem[j]);
listItem[j] = String.Format("{0:C2}", price).PadRight(20, ' '); ;
}
outputListItem = string.Join(" ", listItem);
}
Console.WriteLine(outputListItem);
outputList.Add(outputListItem);
}
Console.ReadLine();
}
我建议让这个面向对象,这看起来像 Inventory。所以第一步就是盘点class。在Inventory中class会有以字符串为文件名加载库存的方法(这个可能需要根据你的实际数据类型和错误处理要求修改)
public class Inventory
{
public string Id { get; set; }
public string ItemName { get; set; }
public int StartingQty { get; set; }
public int QtyMinRestck { get; set; }
public int QtySold { get; set; }
public int QtyRStcked { get; set; }
public decimal UnitPrice { get; set; }
public Inventory()
{
}
//this overrides the default .ToString() method to provide
//columnar output and formats the UnitPrice to currrency
//this requires the following: using System.Globalization;
public override string ToString()
{
return String.Format("{0}{1}{2}{3}{4}{5}{6}"
, Id.PadRight(15, ' ')
, ItemName.PadRight(30, ' ')
, StartingQty.ToString().PadLeft(10, ' ')
, QtyMinRestck.ToString().PadLeft(10, ' ')
, QtySold.ToString().PadLeft(10, ' ')
, QtyRStcked.ToString().PadLeft(10, ' ')
, UnitPrice.ToString("C", CultureInfo.CurrentCulture).PadLeft(10, ' '));
}
//this loads a collection of inventory objects from a file
//it would ignore any lines with errors
public IEnumerable<Inventory> Load(string InventoryFileName)
{
var inventories = new List<Inventory>();
using (var sr = new StreamReader(InventoryFileName))
{
sr.ReadLine(); //skip the first line
while (!sr.EndOfStream)
{
try
{
var fields = sr.ReadLine().Split(',');
inventories.Add(new Inventory
{
Id = fields[0]
,
ItemName = fields[1]
,
StartingQty = Int32.Parse(fields[2])
,
QtyMinRestck = Int32.Parse(fields[3])
,
QtySold = Int32.Parse(fields[4])
,
QtyRStcked = Int32.Parse(fields[5])
,
UnitPrice = Decimal.Parse(fields[6])
});
}
catch
{
//handle error here
}
}
}
return inventories;
}
}
现在我们有了 class,您可以轻松调用它并从文件中取回您的库存:
inventoryListBox.Items.Clear(); //清除列表框项目
if (ipFile.ShowDialog() == DialogResult.OK) //show dialog box
{
Inventory inventory = new Inventory();
var inventories = inventory.Load(ipFile.FileName);
//sets the datasource of the list box to the collection of inventory
//by default it calls the ToString() method which which overrode
//to provide columar output
inventoryListBox.DataSource = inventories;
}
这是一个非常基本的实现,但它应该会让以后的维护变得更容易。您还可以使用 "inventories" 作为列表框的数据源。
我目前一直在尝试使 .csv 文件中最后一列的输出正常工作。我需要将其转换为货币。我不确定我是否对整个专栏使用 (i == 6)(如果这甚至是可行的)或者我是否必须这样做 (i == 13 || i == 20 || i == 27) 等每个需要转换为货币的值。
我想要完成的事情:
单击加载库存按钮时,将读取库存记录 使用“打开文件对话框”控件从文本文件中读取,从文件中读取的行被标记为字段值、解析(根据需要),然后加载到列表框和 class 实例列表中。 ListBox(和 class 实例列表)除了包含输入文件中的所有字段值外,还应包含 QtyHand 和 Sales 列。 String.Format() 或 PadRight() 方法可用于设置列表框内容的格式,使列中的所有值都对齐,假设您使用的是等宽字体。
.csv 文件的前两行是:
Id,Item Name,StartingQty,QtyMinRestck,QtySold,QtyRStcked,UnitPrice
85-0521031,Shampoo,35,9,0,0,2.89
非常感谢任何帮助解决这个问题的人。
public partial class inventoryForm : Form
{
OpenFileDialog ipFile = new OpenFileDialog();
public inventoryForm()
{
InitializeComponent();
}
private void loadInvDataButton_Click(object sender, EventArgs e)
{
inventoryListBox.Items.Clear(); //clear listbox items
if (ipFile.ShowDialog() == DialogResult.OK) //show dialog box
{
string[] file = File.ReadAllLines(ipFile.FileName); //tokenize
foreach (string line in file) //for each line in the file ...
{
string[] inventory = line.Split(','); //tokens contain numbers from the .csv file
for (int i = 0; i < inventory.Length; i++) //loop goes through each item in the inventory
{
if (i == 6) //items in the csv file that require conversion
{
double price = double.Parse(inventory[i]); //convert the value to currency, then pad
inventory[i] = String.Format("{0:C2}", price).PadRight(20, ' ');
}
else
{
inventory[i] = inventory[i].PadRight(20, ' '); //just pad the string
}
}
string item = string.Join("", inventory);
inventoryListBox.Items.Add(item);
}
}
}
}
好吧,这是没有其他细节的快速解决方案,但简而言之,您需要存储新格式化项目的方法,我希望这对您来说已经足够清楚了。更新为格式更好的代码。
static void Main(string[] args)
{
List<string> outputList = new List<string>();
string[] list = new string[] { "85 - 0521031, Shampoo, 35, 9, 0, 0, 2.89", "86 - 0521031, Guitar, 35, 9, 0, 0, 9.89" };
for(var i=0; i<list.Length; i++)
{
var listItem = list[i].Split(',');
var outputListItem = "";
for (var j=0; j<listItem.Length; j++)
{
if(j == 6)
{
double price = double.Parse(listItem[j]);
listItem[j] = String.Format("{0:C2}", price).PadRight(20, ' '); ;
}
outputListItem = string.Join(" ", listItem);
}
Console.WriteLine(outputListItem);
outputList.Add(outputListItem);
}
Console.ReadLine();
}
我建议让这个面向对象,这看起来像 Inventory。所以第一步就是盘点class。在Inventory中class会有以字符串为文件名加载库存的方法(这个可能需要根据你的实际数据类型和错误处理要求修改)
public class Inventory
{
public string Id { get; set; }
public string ItemName { get; set; }
public int StartingQty { get; set; }
public int QtyMinRestck { get; set; }
public int QtySold { get; set; }
public int QtyRStcked { get; set; }
public decimal UnitPrice { get; set; }
public Inventory()
{
}
//this overrides the default .ToString() method to provide
//columnar output and formats the UnitPrice to currrency
//this requires the following: using System.Globalization;
public override string ToString()
{
return String.Format("{0}{1}{2}{3}{4}{5}{6}"
, Id.PadRight(15, ' ')
, ItemName.PadRight(30, ' ')
, StartingQty.ToString().PadLeft(10, ' ')
, QtyMinRestck.ToString().PadLeft(10, ' ')
, QtySold.ToString().PadLeft(10, ' ')
, QtyRStcked.ToString().PadLeft(10, ' ')
, UnitPrice.ToString("C", CultureInfo.CurrentCulture).PadLeft(10, ' '));
}
//this loads a collection of inventory objects from a file
//it would ignore any lines with errors
public IEnumerable<Inventory> Load(string InventoryFileName)
{
var inventories = new List<Inventory>();
using (var sr = new StreamReader(InventoryFileName))
{
sr.ReadLine(); //skip the first line
while (!sr.EndOfStream)
{
try
{
var fields = sr.ReadLine().Split(',');
inventories.Add(new Inventory
{
Id = fields[0]
,
ItemName = fields[1]
,
StartingQty = Int32.Parse(fields[2])
,
QtyMinRestck = Int32.Parse(fields[3])
,
QtySold = Int32.Parse(fields[4])
,
QtyRStcked = Int32.Parse(fields[5])
,
UnitPrice = Decimal.Parse(fields[6])
});
}
catch
{
//handle error here
}
}
}
return inventories;
}
}
现在我们有了 class,您可以轻松调用它并从文件中取回您的库存:
inventoryListBox.Items.Clear(); //清除列表框项目
if (ipFile.ShowDialog() == DialogResult.OK) //show dialog box
{
Inventory inventory = new Inventory();
var inventories = inventory.Load(ipFile.FileName);
//sets the datasource of the list box to the collection of inventory
//by default it calls the ToString() method which which overrode
//to provide columar output
inventoryListBox.DataSource = inventories;
}
这是一个非常基本的实现,但它应该会让以后的维护变得更容易。您还可以使用 "inventories" 作为列表框的数据源。