Transformation von TXT zu CSV und zu XML

+ andere TechDocs
+ XSL, XSLT, XSL-FO
+ XML
+ XSD (Schema)
+ JAXB (Binding)
+ DB zu CSV und HTML
+




Inhalt

  1. Transformation von Textdateien mit festen Feldlängen zu CSV und XML
    1. Textdateien mit festen Feldlängen
    2. Java-Tool zur Transformation von Textdateien mit festen Feldlängen zu CSV und XML
    3. Transformation zu einer einzigen CSV-Datei
    4. Transformation zu pro Blockgruppe jeweils einer CSV-Datei
    5. Transformation zu XML


Transformation von Textdateien mit festen Feldlängen zu CSV und XML

Textdateien mit festen Feldlängen

Viele Datenübertragungen verwenden noch immer einfache Textdateien mit festen Feldlängen und jeweils einer Zeile pro Datensatz. Eine einfache Adressenliste könnte zum Beispiel so aussehen:

Torsten Horn   Meinestr. 26   52072 Aachen
Heinz Hinz     Hafenstr. 42   21079 Hamburg
Karl Kunz      Königstr. 1    50676 Köln

Weiter ist es oft üblich, dass es am Anfang der Zeile einen oder mehrere Header-Blöcke gibt und anschließend beliebig viele Datenblöcke mit sich wiederholendem Format, zum Beispiel so (die Einteilungsleiste dient nur zur Erläuterung und gehört nicht zur übertragenen Datei):

|------- Header ------||----------------- Anschrift ----------------||-- 1. Bestellposten --||-- 2. Bestellposten --||-- 3. Bestellposten --|
Bestellung   2009-09-09Torsten Horn   Meinestr. 26   52072 Aachen    Java-Buch       33,33EURJava-XML-Buch   55,55EURXML-Buch        77,77EUR
Bestellung   2007-08-09Heinz Hinz     Hafenstr. 42   21079 Hamburg   Hotelführer    111,11EUR
Bestellung   2010-01-01Karl Kunz      Königstr. 1    50676 Köln      Kochbuch        12,34EUR

Der Teil von "Bestellung" bis inklusive des Orts hätte auch als ein einziger Header-Block definiert sein können, aber hier sollen "Bestellung" und Datum als erster Block für den Header gelten sowie Name, Straße und Ort als zweiter Block für die Anschrift. Anschließend folgen beliebig viele Bestellposten-Blöcke, jeweils bestehend aus Buchtitel, Preis und Währung. Im Beispiel enthält die erste Zeile drei Bestellposten und die folgenden nur jeweils einen.

Das folgende Java-Beispiel zeigt, wie sich solche Textformate wahlweise in CSV- oder XML-Dateien transformieren lassen (CSV = Comma separated Values, zu XML siehe java-xml.htm).

Java-Tool zur Transformation von Textdateien mit festen Feldlängen zu CSV und XML

Das folgende Beispiel ist kein produktionstaugliches Tool, sondern nur ein Prinzipbeispiel. Zum Beispiel fehlt eine weitergehende Fehlerbehandlung.

  1. Legen Sie beispielsweise folgende Projektstruktur an (oder ein entsprechendes Eclipse-Projekt):

    [\MeinWorkspace\XmlUndCsvAusTxt]
     |- [bin]
     |- [input]
     |- [output]
     '- [src]
         '- [transformation]
    
  2. Speichern Sie im src/transformation-Verzeichnis:
    TransformationTxtZuCsvUndXml.java

    package transformation;
    
    import java.io.*;
    import java.util.*;
    
    public class TransformationTxtZuCsvUndXml
    {
       public static void main( String[] args ) throws IOException
       {
          System.out.println(
                "\n1. Parameter: CSV-Datei (mit Startspalte;Endspalte;;;Spaltenname)" +
                "\n2. Parameter: Pfad (mit max. einem '*'-Joker) zu Daten-TXT-Dateien" +
                "\n3. Parameter: Verzeichnis fuer Ergebnis-CSV-Dateien" +
                "\n4. Parameter: 1CSV = 1 CSV-Datei, BloeckeCSV = pro Blockgruppe CSV-Datei, XML = XML" +
                "\n5. Parameter: Encoding (z.B. UTF-8 oder ISO-8859-1)" +
                "\n6. Parameter: true = mit Leerzeichen-Trim\n" );
          if( args.length < 4 ) return;
    
          String  encoding        = ( args.length >  4 ) ? args[4] : "ISO-8859-1";
          boolean leerzeichenTrim = ( args.length <= 5 || !args[5].toLowerCase().equals( "false" ) );
          String ergebnisDateiFormat = args[3].toLowerCase();
          if( ergebnisDateiFormat.equals( "1csv" ) ) {
             transformiereTxtZuEinerCsvDatei( args[0], args[1], args[2], encoding, leerzeichenTrim );
          }
          else if( ergebnisDateiFormat.equals( "bloeckecsv" ) ) {
             transformiereTxtZuProBlockCsvDateien( args[0], args[1], args[2], encoding, leerzeichenTrim );
          }
          else if( ergebnisDateiFormat.equals( "xml" ) ) {
             transformiereTxtZuXML( args[0], args[1], args[2], encoding, leerzeichenTrim );
          }
          else {
             System.out.println( "Fehler: Ergebnis-Dateiformat muss 1CSV, BloeckeCSV oder XML lauten.\n" );
          }
       }
    
       // Transformiere TXT-Datei in eine einzige CSV-Datei:
       public static void transformiereTxtZuEinerCsvDatei( String propsCsvFile, String txtFilePathAndNamesWithJoker,
             String outDir, String encoding, boolean leerzeichenTrim ) throws IOException
       {
          List<List<TrafoPropsAttr>> trafoPropsBloecke = erstelleListeDerTrafoPropsBloecke( propsCsvFile, encoding );
          List<File>                 files = erstelleListeDerFiles( txtFilePathAndNamesWithJoker );
          for( File file : files ) {
             int anzahlAttrProZeileMin = Integer.MAX_VALUE, anzahlAttrProZeileMax = 0;
             int anzahlBloeckeMin = Integer.MAX_VALUE, anzahlBloeckeMax = 0;
             int anzahlZeilen = 0;
             String line;
             List<List<String>> attrAll = new ArrayList<List<String>>();
             System.out.print( "Inputdatei '" + file.getName() + "': " );
             BufferedReader in = new BufferedReader( new InputStreamReader( new FileInputStream( file ), encoding ) );
             try {
                while( (line = in.readLine()) != null ) {
                   List<String> attrZeile = new ArrayList<String>();
                   int anzahlBloecke = transformiereEinzelneZeileInEineEinzigeListe(
                         line, leerzeichenTrim, trafoPropsBloecke, attrZeile );
                   if( attrZeile.size() == 0 ) {
                      continue;
                   }
                   anzahlZeilen++;
                   if( anzahlAttrProZeileMin > attrZeile.size() ) anzahlAttrProZeileMin = attrZeile.size();
                   if( anzahlAttrProZeileMax < attrZeile.size() ) anzahlAttrProZeileMax = attrZeile.size();
                   if( anzahlBloeckeMin > anzahlBloecke ) anzahlBloeckeMin = anzahlBloecke;
                   if( anzahlBloeckeMax < anzahlBloecke ) anzahlBloeckeMax = anzahlBloecke;
                   attrAll.add( attrZeile );
                }
             } finally {
                in.close();
             }
             String s1 = (anzahlAttrProZeileMin == anzahlAttrProZeileMax) ? "" : "..." + anzahlAttrProZeileMax;
             String s2 = (anzahlBloeckeMin == anzahlBloeckeMax) ? "" : "..." + anzahlBloeckeMax;
             System.out.println( anzahlZeilen + " Zeilen, pro Zeile: " + anzahlAttrProZeileMin + s1 +
                                 " Attribute und " + anzahlBloeckeMin + s2 + " Bloecke" );
             attrAll.add( 0, erstelleNamenListe( trafoPropsBloecke, anzahlBloeckeMax, false ) );
             schreibeCsvDatei( attrAll, outDir, file.getName() + ".csv", encoding );
          }
       }
    
       // Transformiere TXT-Datei in pro Blockgruppe jeweils eine CSV-Datei:
       public static void transformiereTxtZuProBlockCsvDateien( String propsCsvFile,
             String txtFilePathAndNamesWithJoker, String outDir, String encoding, boolean leerzeichenTrim ) throws IOException
       {
          List<List<TrafoPropsAttr>> trafoPropsBloecke = erstelleListeDerTrafoPropsBloecke( propsCsvFile, encoding );
          List<File>                 files = erstelleListeDerFiles( txtFilePathAndNamesWithJoker );
          for( File file : files ) {
             System.out.println( "Inputdatei '" + file.getName() + "':" );
             BufferedReader in = new BufferedReader( new InputStreamReader( new FileInputStream( file ), encoding ) );
             try {
                int zeilennummer = 0;
                String line;
                while( (line = in.readLine()) != null ) {
                   zeilennummer++;
                   List<List<List<String>>> attrVerschiedeneBloecke = transformiereEinzelneZeileInProBlockEineListe(
                         line, leerzeichenTrim, trafoPropsBloecke );
                   if( attrVerschiedeneBloecke == null || attrVerschiedeneBloecke.size() == 0 ) {
                      continue;
                   }
                   int blocknummer = 0;
                   for( int i = 0; i < attrVerschiedeneBloecke.size() && i < trafoPropsBloecke.size(); i++ ) {
                      List<List<String>> attrMehrereGleicheBloecke = attrVerschiedeneBloecke.get( i );
                      attrMehrereGleicheBloecke.add( 0, erstelleNamenListe( trafoPropsBloecke.get( i ), false ) );
                      String outfilename = file.getName() + "-Zeile" + zeilennummer + "-Block" + ++blocknummer + ".csv";
                      System.out.println( "   CSV-Datei '" + outfilename + "': " +
                            ((attrMehrereGleicheBloecke.size() == 2)
                             ? "1 Block" : (attrMehrereGleicheBloecke.size() - 1) + " Bloecke") );
                      schreibeCsvDatei( attrMehrereGleicheBloecke, outDir, outfilename, encoding );
                   }
                }
             } finally {
                in.close();
             }
          }
       }
    
       // Transformiere TXT-Datei in XML-Datei:
       public static void transformiereTxtZuXML( String propsCsvFile, String txtFilePathAndNamesWithJoker,
             String outDir, String encoding, boolean leerzeichenTrim ) throws IOException
       {
          List<List<TrafoPropsAttr>> trafoPropsBloecke = erstelleListeDerTrafoPropsBloecke( propsCsvFile, encoding );
          List<File>                 files = erstelleListeDerFiles( txtFilePathAndNamesWithJoker );
          for( File file : files ) {
             System.out.println( "Inputdatei '" + file.getName() + "':" );
             BufferedReader in = new BufferedReader( new InputStreamReader( new FileInputStream( file ), encoding ) );
             try {
                int zeilennummer = 0;
                String line;
                while( (line = in.readLine()) != null ) {
                   zeilennummer++;
                   List<List<List<String>>> attrVerschiedeneBloecke = transformiereEinzelneZeileInProBlockEineListe(
                         line, leerzeichenTrim, trafoPropsBloecke );
                   if( attrVerschiedeneBloecke == null || attrVerschiedeneBloecke.size() == 0 ) {
                      continue;
                   }
                   String outfilename = file.getName() + "-Zeile" + zeilennummer + ".xml";
                   System.out.println( "   XML-Datei '" + outfilename );
                   outfilename = concatDirFilename( outDir, outfilename );
                   BufferedWriter out = new BufferedWriter( new OutputStreamWriter(
                                        new FileOutputStream( outfilename.trim() ), encoding ) );
                   try {
                      out.write( "<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n<TxtZuXML>\n" );
                      int blocknummer = 0;
                      for( int i = 0; i < attrVerschiedeneBloecke.size() && i < trafoPropsBloecke.size(); i++ ) {
                         List<List<String>> attrMehrereGleicheBloecke = attrVerschiedeneBloecke.get( i );
                         attrMehrereGleicheBloecke.add( 0, erstelleNamenListe( trafoPropsBloecke.get( i ), true ) );
                         out.write( erzeugeXmlAttribute( "Block" + ++blocknummer, attrMehrereGleicheBloecke ) );
                      }
                      out.write( "</TxtZuXML>\n" );
                   } finally {
                      out.close();
                   }
                }
             } finally {
                in.close();
             }
          }
       }
    
       // Transformiere einzelne Zeile in eine einzige Liste:
       static int transformiereEinzelneZeileInEineEinzigeListe( String line, boolean leerzeichenTrim,
             List<List<TrafoPropsAttr>> trafoPropsBloecke, List<String> attrZeile )
       {
          int anzahlBloecke = 0;
          int startIdx = 0;
          for( List<TrafoPropsAttr> trafoPropsBlock : trafoPropsBloecke ) {
             startIdx = transformiereEinzelnenBlock( line, startIdx, leerzeichenTrim, trafoPropsBlock, attrZeile );
             anzahlBloecke++;
          }
          while( startIdx < line.length() ) {
             int startIdxAlt = startIdx;
             startIdx = transformiereEinzelnenBlock( line, startIdx, leerzeichenTrim,
                   trafoPropsBloecke.get(trafoPropsBloecke.size() - 1), attrZeile );
             if( startIdx != Integer.MAX_VALUE || !line.substring( startIdxAlt, line.length() ).equals( "@" ) ) {
                anzahlBloecke++;
             }
          }
          return anzahlBloecke;
       }
    
       // Transformiere einzelne Zeile in pro Blockgruppe eine Liste:
       static List<List<List<String>>> transformiereEinzelneZeileInProBlockEineListe(
             String line, boolean leerzeichenTrim, List<List<TrafoPropsAttr>> trafoPropsBloecke )
       {
          List<List<List<String>>> attrVerschiedeneBloecke = new ArrayList<List<List<String>>>();
          int startIdx = 0;
          for( int i = 0; i < trafoPropsBloecke.size() - 1; i++ ) {
             List<List<String>> attrMehrereGleicheBloecke = new ArrayList<List<String>>();
             List<String> attrEinBlock = new ArrayList<String>();
             startIdx = transformiereEinzelnenBlock(
                   line, startIdx, leerzeichenTrim, trafoPropsBloecke.get( i ), attrEinBlock );
             attrMehrereGleicheBloecke.add( attrEinBlock );
             attrVerschiedeneBloecke.add( attrMehrereGleicheBloecke );
          }
          List<List<String>> attrMehrereGleicheBloecke = new ArrayList<List<String>>();
          while( startIdx < line.length() ) {
             List<String> attrEinBlock = new ArrayList<String>();
             startIdx = transformiereEinzelnenBlock( line, startIdx, leerzeichenTrim,
                   trafoPropsBloecke.get( trafoPropsBloecke.size() - 1 ), attrEinBlock );
             if( attrEinBlock.size() > 0 ) {
                attrMehrereGleicheBloecke.add( attrEinBlock );
             }
          }
          if( attrMehrereGleicheBloecke.size() > 0) {
             attrVerschiedeneBloecke.add( attrMehrereGleicheBloecke );
          }
          return attrVerschiedeneBloecke;
       }
    
       static int transformiereEinzelnenBlock( String line, int startIdx, boolean leerzeichenTrim,
             List<TrafoPropsAttr> trafoPropsBlock, List<String> attrZeile )
       {
          int letzterEndIdx = 0;
          for( TrafoPropsAttr trafoPropsAttr : trafoPropsBlock ) {
             int n1 = startIdx + trafoPropsAttr.startSpalte;
             int n2 = startIdx + trafoPropsAttr.endSpalte;
             if( line.length() < n1 ) {
                return Integer.MAX_VALUE;
             }
             int n = Math.min( n2, line.length() );
             String s = line.substring( n1 - 1, n );
             if( n < n2 && s.equals( "@" ) ) {
                return Integer.MAX_VALUE;
             }
             if( leerzeichenTrim ) {
                s = s.trim();
             }
             attrZeile.add( s );
             letzterEndIdx = n2;
          }
          return letzterEndIdx;
       }
    
       static List<String> erstelleNamenListe(
             List<List<TrafoPropsAttr>> trafoPropsBloecke, int anzahlBloecke, boolean konvXmlName )
       {
          int blockNummer = 0;
          List<String> titel = new ArrayList<String>();
          for( List<TrafoPropsAttr> trafoPropsBlock : trafoPropsBloecke ) {
             blockNummer++;
             titel.addAll( erstelleNamenListe( trafoPropsBlock, konvXmlName ) );
          }
          while( blockNummer++ < anzahlBloecke ) {
             titel.addAll( erstelleNamenListe( trafoPropsBloecke.get( trafoPropsBloecke.size() - 1 ), konvXmlName ) );
          }
          return titel;
       }
    
       static List<String> erstelleNamenListe( List<TrafoPropsAttr> trafoPropsBlock, boolean konvXmlName )
       {
          List<String> titel = new ArrayList<String>();
          if( konvXmlName ) {
             for( TrafoPropsAttr trafoPropsAttr : trafoPropsBlock ) {
                titel.add( trafoPropsAttr.nameXml );
             }
          } else {
             for( TrafoPropsAttr trafoPropsAttr : trafoPropsBlock ) {
                titel.add( trafoPropsAttr.nameOrig );
             }
          }
          return titel;
       }
    
       // Erstelle Liste der Trafo-Props-Bloecke:
       static List<List<TrafoPropsAttr>> erstelleListeDerTrafoPropsBloecke( String propsCsvFile, String encoding ) throws IOException
       {
          List<List<TrafoPropsAttr>> trafoPropsBloecke = new ArrayList<List<TrafoPropsAttr>>();
          List<TrafoPropsAttr> trafoPropsBlock = null;
    
          BufferedReader in = new BufferedReader( new InputStreamReader( new FileInputStream( propsCsvFile ), encoding ) );
          try {
             String line;
             int letzteEndSpalte = 0;
             while((line = in.readLine()) != null) {
                line = line.trim();
                if (line.length() == 0 || line.startsWith( "#" )) {
                   continue;
                }
                String[] ss = line.split( ";" );
                if( ss.length < 3 ) {
                   continue;
                }
                int n = Math.min( 5, ss.length );
                TrafoPropsAttr tp = new TrafoPropsAttr();
                tp.startSpalte = Integer.parseInt( ss[0].trim() );
                tp.endSpalte   = Integer.parseInt( ss[1].trim() );
                tp.nameOrig    = ss[n - 1].trim();
                tp.nameXml     = konvertiereZuGueltigemXmlNamen( tp.nameOrig );
    
                if( trafoPropsBlock == null || letzteEndSpalte > tp.startSpalte ) {
                   if( trafoPropsBlock != null ) {
                      trafoPropsBloecke.add( trafoPropsBlock );
                   }
                   trafoPropsBlock = new ArrayList<TrafoPropsAttr>();
                }
                letzteEndSpalte = tp.endSpalte;
                trafoPropsBlock.add( tp );
             }
             if( trafoPropsBlock != null ) {
                trafoPropsBloecke.add( trafoPropsBlock );
             }
          } finally {
             in.close();
          }
    
          return trafoPropsBloecke;
       }
    
       // Erstelle Liste der Files, maximal ein '*'-Joker ist möglich:
       public static List<File> erstelleListeDerFiles( String filePathAndNamesWithJoker )
       {
          List<File> resultFiles = new ArrayList<File>();
          if(filePathAndNamesWithJoker == null || filePathAndNamesWithJoker.trim().length() <= 0) {
             return resultFiles;
          }
          int n1 = filePathAndNamesWithJoker.lastIndexOf('\\');
          int n2 = filePathAndNamesWithJoker.lastIndexOf('/');
          int nm = Math.max(n1, n2);
          if(nm < 1 || nm > filePathAndNamesWithJoker.length() - 2) {
             return resultFiles;
          }
          filePathAndNamesWithJoker = filePathAndNamesWithJoker.trim();
          String pathWithoutFilename = filePathAndNamesWithJoker.substring(0, nm);
          String filenameWithoutPath = filePathAndNamesWithJoker.substring(++nm);
          nm = filenameWithoutPath.indexOf('*');
          String filenameStart = (nm >= 0) ? filenameWithoutPath.substring(0, nm) : filenameWithoutPath;
          String filenameEnd   = (nm >= 0) ? filenameWithoutPath.substring(++nm)  : filenameWithoutPath;
          File[] files = (new File(pathWithoutFilename)).listFiles();
          if(files == null || files.length <= 0) {
             return resultFiles;
          }
    
          for (int k = 0; k < files.length; k++) {
             if(files[k].isDirectory()) {
                continue;
             }
             String filename = files[k].getName();
             if(filename == null || !filename.startsWith(filenameStart) || !filename.endsWith(filenameEnd)) {
                continue;
             }
             resultFiles.add( files[k] );
          }
    
          return resultFiles;
       }
    
       public static void schreibeCsvDatei( List<List<String>> strListen, String dir, String filename, String encoding ) throws IOException
       {
          filename = concatDirFilename( dir, filename );
          if( strListen == null || strListen.size() == 0 || strListen.get(0) == null || strListen.get(0).size() == 0
                || filename == null || filename.trim().length() == 0 ) {
             return;
          }
          BufferedWriter out = new BufferedWriter( new OutputStreamWriter(
                               new FileOutputStream( filename.trim() ), encoding ) );
          try {
             for( List<String> ss : strListen ) {
                StringBuffer sb = new StringBuffer();
                for( String s : ss ) {
                   sb.append( s.replace(';', ',') ).append( ";" );
                }
                if( sb.length() > 0 ) {
                   sb.deleteCharAt( sb.length() - 1 );
                   out.write( sb.toString() );
                   out.newLine();
                }
             }
          } finally {
             out.close();
          }
       }
    
       static String concatDirFilename( String dir, String filename )
       {
          if( filename == null || filename.trim().length() == 0 ) {
             return null;
          }
          filename = filename.trim();
          if( dir != null ) {
             dir = dir.trim();
             if( dir.length() > 0 ) {
                if( !dir.endsWith( File.separator ) ) dir += File.separator;
                filename = dir + filename;
             }
          }
          return filename;
       }
    
       static String erzeugeXmlAttribute( String blockXmlElementName, List<List<String>> strListen )
       {
          if( strListen == null || strListen.size() < 2 ) {
             return null;
          }
          List<String> namen = strListen.get( 0 );
          StringBuffer sb = new StringBuffer();
          for( int i = 1; i < strListen.size(); i++ ) {
             List<String> ss = strListen.get( i );
             if( ss == null || ss.size() == 0 ) {
                continue;
             }
             sb.append( "   <" ).append( blockXmlElementName ).append(
                   (strListen.size() == 2) ? "" : "-" + i ).append( "\n" );
             for( int j = 0; j < ss.size() && j < namen.size(); j++ ) {
                sb.append( "      " ).append( namen.get( j ) ).append( "=\"" ).append( ss.get( j ) ).append( "\"\n" );
             }
             sb.append( "   />\n" );
          }
          return sb.toString();
       }
    
       public static String konvertiereZuGueltigemXmlNamen( String s )
       {
          String[] sonderzeichen = { "ä", "ae", "ö", "oe", "ü", "ue",
                                     "Ä", "AE", "Ö", "OE", "Ü", "UE",
                                     "ß", "ss", "§", "Paragraph", "\u20AC", "Euro" };
          s = s.trim();
          for( int i = 0; i < sonderzeichen.length; i+=2 ) {
             s = s.replace( sonderzeichen[i], sonderzeichen[i+1] );
          }
          for( int i = 0; i < s.length(); i++ ) {
             char c = s.charAt( i );
             if( !(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')
                   && c != '-' && c != '.' && c != '_' ) {
                s = s.substring( 0, i ) + "_" + s.substring( i + 1 );
             }
          }
          if( !Character.isLetter( s.charAt( 0 ) ) ) {
             s = "_" + s;
          }
          return s;
       }
    }
    
    class TrafoPropsAttr
    {
       int    startSpalte;
       int    endSpalte;
       String nameOrig;
       String nameXml;
    }
    
  3. Speichern Sie im input-Verzeichnis:
    BestellungAbcXyz.txt

    Bestellung   2009-09-09Torsten Horn   Meinestr. 26   52072 Aachen    Java-Buch       33,33EURJava-XML-Buch   55,55EURXML-Buch        77,77EUR
    Bestellung   2007-08-09Heinz Hinz     Hafenstr. 42   21079 Hamburg   Hotelführer    111,11EUR
    Bestellung   2010-01-01Karl Kunz      Königstr. 1    50676 Köln      Kochbuch        12,34EUR
    

    Falls wie im Beispiel Sonderzeichen und Umlaute ('ö', 'ü') verwendet werden, muss darauf geachtet werden, dass diese Datei in dem angegebenen Encoding gespeichert wird (z.B. ISO-8859-1 oder UTF-8).

  4. Speichern Sie im input-Verzeichnis:
    Bestellung-Felddefinitionen.csv

    # Header
      1; 13; Vorgang
     14; 23; Datum
    # Name und Adresse
      1; 15; Name
     16; 30; Straße
     31; 46; Ort
    # Bestellposten (beliebig viele)
      1; 13; Titel
     14; 21; Preis
     22; 24; Währung
    

    In dieser Datei wird das Format der Textdateien mit den festen Feldlängen definiert. Hier wurden zwei Header-Blöcke und sich anschließend beliebig oft wiederholende Bestellposten-Blöcke definiert. Pro Datenfeld definiert der erste Wert die Startspalte, der zweite die Endspalte und der dritte Teil ist der Feldname. Der Beginn eines neuen Blocks ergibt sich dadurch, dass der Startspaltenwert kleiner als der letzte Endspaltenwert ist. Falls wie im Beispiel Sonderzeichen ('ß') und Umlaute ('ä') verwendet werden, muss darauf geachtet werden, dass diese Datei in dem angegebenen Encoding gespeichert wird (z.B. ISO-8859-1 oder UTF-8).

  5. Ihr Projektverzeichnis sieht jetzt so aus (überprüfen Sie es mit tree /F):

    [\MeinWorkspace\XmlUndCsvAusTxt]
     |- [bin]
     |- [input]
     |   |- BestellungAbcXyz.txt
     |   '- Bestellung-Felddefinitionen.csv
     |- [output]
     '- [src]
         '- [transformation]
             '- TransformationTxtZuCsvUndXml.java
    

Transformation zu einer einzigen CSV-Datei

  1. Öffnen Sie ein Kommandozeilenfenster ('Windows-Taste' + 'R', 'cmd'), wechseln Sie in Ihr Projektverzeichnis und kompilieren Sie TransformationTxtZuCsvUndXml.java:

    cd \MeinWorkspace\XmlUndCsvAusTxt

    javac -d bin src/transformation/TransformationTxtZuCsvUndXml.java

    Rufen Sie die Transformation auf (mit dem 4. Parameter "1CSV" für eine einzige CSV-Datei) und sehen Sie sich das Ergebnis entweder in einem Texteditor oder bequemer in Excel an:

    java -cp .;bin transformation.TransformationTxtZuCsvUndXml input/Bestellung-Felddefinitionen.csv input/Bestellung*.txt output 1CSV

    start output\BestellungAbcXyz.txt.csv

     ABCDEFGHIJKLMN
    1VorgangDatumNameStraßeOrtTitelPreisWährungTitelPreisWährungTitelPreisWährung
    2Bestellung2009-09-09Torsten HornMeinestr. 2652072 AachenJava-Buch33,33EURJava-XML-Buch55,55EURXML-Buch77,77EUR
    3Bestellung2007-08-09Heinz HinzHafenstr. 4221079 HamburgHotelführer111,11EUR   
    4Bestellung2010-01-01Karl KunzKönigstr. 150676 KölnKochbuch12,34EUR   

Transformation zu pro Blockgruppe jeweils einer CSV-Datei

  1. Rufen Sie die Transformation auf, diesmal mit dem 4. Parameter "BloeckeCSV", damit pro Blockgruppe jeweils eine CSV-Datei erzeugt wird. Sehen Sie sich die CSV-Dateien an. Die sich wiederholenden Bestellposten ab dem dritten Block in der ersten Zeile finden Sie zum Beispiel in BestellungAbcXyz.txt-Zeile1-Block3.csv:

    java -cp .;bin transformation.TransformationTxtZuCsvUndXml input/Bestellung-Felddefinitionen.csv input/Bestellung*.txt output BloeckeCSV

    start output\BestellungAbcXyz.txt-Zeile1-Block3.csv

     ABC
    1TitelPreisWährung
    2Java-Buch33,33EUR
    3Java-XML-Buch55,55EUR
    4XML-Buch77,77EUR

Transformation zu XML

  1. Rufen Sie die Transformation diesmal mit dem 4. Parameter "XML" auf. Sie erhalten pro Zeile eine XML-Datei:

    java -cp .;bin transformation.TransformationTxtZuCsvUndXml input/Bestellung-Felddefinitionen.csv input/Bestellung*.txt output XML

    start output\BestellungAbcXyz.txt-Zeile1.xml

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <TxtZuXML>
       <Block1   Vorgang="Bestellung"  Datum="2009-09-09" />
       <Block2   Name="Torsten Horn"   Strasse="Meinestr. 26" Ort="52072 Aachen" />
       <Block3-1 Titel="Java-Buch"     Preis="33,33" Waehrung="EUR" />
       <Block3-2 Titel="Java-XML-Buch" Preis="55,55" Waehrung="EUR" />
       <Block3-3 Titel="XML-Buch"      Preis="77,77" Waehrung="EUR" />
    </TxtZuXML>
    

    Die erzeugten XML-Dateien sind sehr rudimentär. Sie können aber leicht zum Beispiel per XSLT in ein anderes gefordertes Format transformiert werden.





Weitere Themen: andere TechDocs | XML | XSD (Schema) | JAXB (Binding) | XSL, XSLT, XSL-FO | DB zu CSV und HTML
© 2009-2010 Torsten Horn, Aachen