尝试从 .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" 作为列表框的数据源。