German Windows CSV einlesen ?

Hubert Brandel

Active Member
Licensed User
Hallo,

ich muss CSV Dateien von Windows (ANSI) einlesen und auch wieder exportieren. Ich versuche das mit den StringUtils.

B4X:
Dim sFirma, Headers, sFiID As List
...
sFiID  = su.LoadCSV(sStartDir, sFName, ";")
Log(sFiID)            
sFirma = su.LoadCSV2(sStartDir, sFName, ";", Headers)
Log(headers)
Log(sFirma)
...

und erhalte folgende LOG Meldungen:

(ArrayList) [[Ljava.lang.String;@40585388, [Ljava.lang.String;@40585408]
(ArrayList) [Firm1, Firm2]
(ArrayList) [[Ljava.lang.String;@40535680]

Firm1, Firm2 ist die erste Zeile in der CSV Datei, mit dem Rest kann ich nichts anfangen.
Ich vermute, dass es an den chr(13)+chr(10) der Windows-CSV liegt, bin mir aber nicht sicher.

Wie macht Ihr das oder habt Ihr nur Linux CSV Dateien ?

Das gleiche Problem wird mich beim Export treffen, da benötige ich ANSI Windows CSV Dateien ...
 

Hubert Brandel

Active Member
Licensed User
Hi,

es liegt NICHT an dem Windows Zeilenformat. Ich hatte ein grundsätzliches Missverständnis mit LoadCSV.
Ich erwartete ein zwei dimensionales Array auf das man direkt zugreifen kann.
Hier muss man aber die einzelnen Objekte der LIST (Rückgabe) zunächst zeilenweise in ein Stringarray umkopieren und auf dieses dann zugreifen.

B4X:
Dim su As StringUtils
Dim HL(), DL() As String
sData = su.LoadCSV(sStartDir, sFName, ";")
Log("sData:size=" & sData.Size)
HL = sData.Get(0)
For x = 1 To sData.Size-1
   DL = sData.Get(x)
   ... Datenzeile in DL()
Next
 

Hubert Brandel

Active Member
Licensed User
Leider muss ich auch mit CSV Dateien zurecht kommen, die nicht richtig aufgebaut sind (Teilweise fehlt das letzte ';' wenn das letzte Feld leer ist).
So habe ich meinen eigenen Code für CSV Dateien geschrieben, falls jemand interesse hat, bitte melden.
 
Last edited:

Hubert Brandel

Active Member
Licensed User
Hallo,

anbei die Funktionen, die SQL sind abgewandelte DBUTILS und die CSV bedient immer nur eine CSV Datei zur gleichen Zeit !

Hier ein Anwendungsbeispiel (gekürzt) :

B4X:
Dim m As Map
Dim i, nNr As Int

SQL1.BeginTransaction ' global
         
Try

   If HBCSV.OpenAnsiCSV(sCSVdirSD, sCSVfiles.LG, " " , True, ";" ) Then ' ... wenn es hier ein Fehler gibt dann gleich schließen
      
      If HBCSV.sHeaderLine.EqualsIgnoreCase("Nr;.... hier folgt das Muster der CSV Feldbeschreibung ...") Then 
         ' Struktur stimmt, nun die TYPEN festlegen  *** so sorge ich dafür, dass ich weiß was wo steht und was was ist.
         ' 0  1       2   3   4   5
         ' Nr;Strasse;PLZ;Ort;Bem;Datum    
         '
         ' N  S       S   S   S   D
         '
         For i = 0 To HBCSV.nFieldCount-1 ' Setze den Datentyp der in der CSV Datei gelesen werden soll
             Select i
             Case 0:
                HBCSV.sType(i) = "N"
             Case 5:
                HBCSV.sType(i) = "D"
             Case Else :
                HBCSV.sType(i) = "S"
             End Select
         Next
         
         Do While True ' der erste Datensatz wurde schon eingelesen, also direkt speichern
            m = HBCSV.getMap() ' eventuell um zusätzliche berechnete Felder erweitern.
            nNr = m.get("Nr")  ' dummerweise case sensitive ! besser ermitteln oder über Nummer
            Try
               HBSQL.InsertRecord(SQL1, "LG", m ) ' table LG
            Catch
               Dim Bedingung As Map
               Bedingung.Initialize
               Bedingung.Put("Nr", nNr )
               HBSQL.UpdateRecord(SQL1, "LG", m, Bedingung )
            End Try
            If HBCSV.ReadNextLine() = False Then
               Exit
            End If
         loop
         
         HBCSV.CloseCSV()
       
      Else
         SQL1.EndTransaction
         Msgbox("Die Struktur der Datei ist fehlerhaft.","CSV-Daten einlesen")
         Return False
      End If

   Else   

      SQL1.EndTransaction
      Msgbox("Die Datei konnte nicht geöffnet werden.","CSV-Daten einlesen")
      Return False

   End If

' Einlesefehler kommen zu catch
Catch

   SQL1.EndTransaction      
   Return False

End Try
   
' wenn vorher kein Abbruch erfolgt ist, dann OK melden
      
SQL1.TransactionSuccessful
SQL1.EndTransaction
Return True

Ich habe oben m.get("Feldname") verwendet, dieser Name ist der aus der CSV und leider case sensitive. Falls in der SQL Tabelle der Name anders lautet (bei mir nicht ;-) ) muss man das ändern. Auch ist die Abfrage nach dem Feldnamen hier fehlerträchtig, falls die CSV nicht auf die Groß-/Kleinschreibung achtet. Besser wäre also die Abfrage nach dem 1. Feld.
 

Attachments

  • HBCSV.bas
    6.1 KB · Views: 183
  • HBSQL.bas
    3.2 KB · Views: 157
Top