B4A Library [B4X] CSVParser - CSV parser and generator

CSV - comma separated values format.

The various StringUtils libraries include methods for loading and saving CSV files.

However these methods have a few drawbacks:

- They work with files instead of strings. This is especially problematic if the input is not UTF8 encoded.
- As they are implemented inside a native library it is not possible to modify their behavior. Some CSV files are not 100% valid and will not work with these methods.

CSVParser is a class that allows parsing and generating CSV strings:
B4X:
Dim parser As CSVParser
parser.Initialize
Dim table As List = parser.Parse(File.ReadString(File.DirAssets, "1.csv"), ",", False)
For Each row() As String In table
   'work with row
Next
Dim s As String = parser.GenerateString(table, ",")
File.WriteString(File.DirApp, "1.csv", s)
 

Attachments

  • CSVParser.bas
    2.6 KB · Views: 1,931
Last edited by a moderator:

walt61

Well-Known Member
Licensed User
Longtime User
I've added a couple of methods in the attached version:
B4X:
' Returns a list with the headers found in the first line.
' If lowerCase is true, all values are shifted to lowercase.
Public Sub GetHeaders(Input As String, SeparatorChar As String, lowerCase As Boolean) As List ' Added by WM
    Dim i As Int
    SeparatorChar = SeparatorChar.CharAt(0)
    Dim Result As List
    Result.Initialize
    If Input = "" Then Return Result
    CurrentIndex = 0
    Dim count As Int = ReadLine(Input, Null, True, SeparatorChar)
    CurrentIndex = 0
    Dim row(count) As String
    ReadLine(Input, row, False, SeparatorChar)
    For i = 0 To (row.Length - 1)
        If lowerCase Then
            Result.Add(row(i).ToLowerCase)
        Else
            Result.Add(row(i))
        End If
    Next
    Return Result
End Sub

' Assumes the first row contains headers.
' Returns a list of maps. Each map contains, for all headers: key=header, value=value found in the data row.
' If lowerCase is true, all keys in the maps are shifted to lowercase.
Public Sub ParseToMaps(Input As String, SeparatorChar As String, lowerCase As Boolean) As List ' Added by WM

    Dim headers As List = GetHeaders(Input, SeparatorChar, lowerCase)
    Dim i As Int

    SeparatorChar = SeparatorChar.CharAt(0)
    Dim Result As List
    Result.Initialize
    If Input = "" Then Return Result
    CurrentIndex = 0
    Dim count As Int = ReadLine(Input, Null, True, SeparatorChar)
    Do While CurrentIndex < Input.Length
        Dim row(count) As String
        ReadLine(Input, row, False, SeparatorChar)
        Dim m As Map
        m.Initialize
        For i = 0 To (row.Length - 1)
            m.Put(headers.Get(i).As(String), row(i))
        Next
        Result.Add(m)
    Loop
    Return Result
End Sub
 

Attachments

  • wmCSVParser.bas
    4.4 KB · Views: 37
Top