讀取 CSV 文件一些缺失的列
我正在嘗試使用以下程式碼將 CSV 文件讀入我的 VB.net 應用程序:
While Not EOF(1) Input(1, dummy) Input(1, phone_number) Input(1, username) Input(1, product_name) Input(1, wholesale_cost) Input(1, dummy) Input(1, dummy) End While我的 CSV 文件(作為文本)如下所示:
Customer Name,Phone Number,Username,Product,Wholesale Cost,Sales Price,Gross Profit, Customer Reference ,00000000000,00000000000,Product Name,25.00,35.00,10.00, ,00000000000,00000000000,Product Name,1.00,1.40,0.40,如您所見,並非總是包含所有欄位,因此在讀取文件時會顯示錯誤,因為它無法到達行尾。
我該如何處理這種類型的文件?
有時欄位會出現在某些線上,而另一些則不會。
更新
我已經嘗試過Zenacity提供的答案,但是當嘗試
sArray(1)在循環內讀取時,它會返回指數數組的邊界之外
您應該掌握的一件事是,這些
Filexxxx方法幾乎已被正式和正式棄用。使用它們時,Intellisense 會彈出:…與 FileOpen 相比,我的功能在文件 I/O 操作中為您提供更好的生產力和性能。有關詳細資訊,請參閱 Microsoft.VisualBasic.FileIO.FileSystem。
他們在談論,
My.Computer.FileSystem但還有一些更有用的 NET 方法。該文章沒有透露數據將如何儲存,但如果它是任何類型和/或結構的數組,那麼如果不是過時的話,這些至少是次優的。這會將它儲存在一個類中,以便可以將數字數據儲存為數字,並且
List將使用 a 代替數組。我用一些隨機數據製作了一個類似於你的快速文件
{"CustName", "Phone", "UserName", "Product", "Cost", "Price", "Profit", "SaleDate", "RefCode"}:
- CustName 有 70% 的時間存在
- 使用者名永遠不存在
- RefCode 存在 30% 的時間
- 我添加了一個SaleDate來說明數據轉換
Ziggy Aurantium,132-5562,,貓糧,8.26,9.95,1.69,08/04/2016,
Catrina Caison,899-8599,,磨刀器,4.95,6.68,1.73,10/12/2016,X-873- W3
,784-4182,,蒸汽壓縮機,11.02,12.53,1.51,09/12/2016,
解析 CSV 的程式碼
注意:這是解析 CSV 的不好方法。這樣做會出現很多問題;加上它需要更多的程式碼。之所以提出它,是因為它是一種不必處理缺失欄位的簡單方法。看到正確的方式
' form/class level var: Private SalesItems As List(Of SaleItem)
SaleItem是一個簡單的類來儲存你關心的元素。SalesItems是一個只能儲存對象SaleItem的集合。該類中的屬性允許將價格和成本儲存為Decimal,並將日期儲存為DateTime.' temp var Dim item As SaleItem ' create the collection SalesItems = New List(Of SaleItem) ' load the data....all of it Dim data = File.ReadAllLines("C:\Temp\custdata.csv") ' parse data lines ' Start at 1 to skip a Header For n As Int32 = 0 To data.Length - 1 Dim split = data(n).Split(","c) ' check if it is a good line If split.Length = 9 Then ' create a new item item = New SaleItem ' store SOME data to it item.CustName = split(0) item.Phone = split(1) ' dont care anout user name (2) item.Product = split(3) ' convert numbers item.Price = Convert.ToDecimal(split(4)) item.Cost = Convert.ToDecimal(split(5)) ' dont use the PROFIT, calculate it in the class (6) ' convert date item.SaleDate = Convert.ToDateTime(split(7)) ' ignore nonexistant RefCode (8) ' add new item to collection ' a List sizes itself as needed! SalesItems.Add(item) Else ' To Do: make note of a bad line format End If Next ' show in DGV for approval/debugging dgvMem.DataSource = SalesItems注意
儲存可以簡單計算的東西通常是個壞主意。所以
Profit屬性是:Public ReadOnly Property Profit As Decimal Get Return (Cost - Price) End Get End Property如果更新成本或價格,它永遠不會“過時”。
如圖所示,使用生成的集合可以很容易地向使用者顯示。給定 a
DataSource,DataGridView將創建列並填充行。正確的方式
String.Split(c)是一個非常糟糕的主意,因為如果產品是:"Hose, Small Green"它會將其切碎並將其視為 2 個欄位。有許多工具可以為您完成幾乎所有的工作:
- 讀取文件
- 解析行
- 將 CSV 數據映射到類
- 將文本轉換為正確的數據類型
- 創造一個經濟的收藏品
除了課程之外,以上所有內容都可以使用**CSVHelper**只需幾行即可完成:
Private CustData As List(Of SaleItem) ... Using sr As New StreamReader("C:\Temp\custdata.csv", False), csv = New CsvReader(sr) csv.Configuration.HasHeaderRecord = True CustData = csv.GetRecords(Of SaleItem)().ToList() End Using兩三行程式碼來讀取、解析和創建 250 個項目的集合。
即使您出於某種原因想要手動執行此操作,CSVHelper 也可以提供幫助。
List(Of SaleItem)您可以使用它來讀取和解析數據,而不是為您創建一個:... like above csv.Configuration.HasHeaderRecord = True Do Until csv.Read() = False For n As Int32 = 0 To csv.Parser.FieldCount - 1 DoSomethingWith(csv.GetField(n)) Next Loop這會將欄位一一返回給您。它不會轉換任何日期或價格,但也不會因失去的數據元素而窒息。
資源
