[hbci4java] parseMT940() Heap-Probleme beseitigt

 
Benutzer
Avatar
Geschlecht: keine Angabe
Beiträge: 13
Dabei seit: 03 / 2008
Betreff:

[hbci4java] parseMT940() Heap-Probleme beseitigt

 · 
Gepostet: 05.03.2008 - 12:28 Uhr  ·  #1
Naja, Heap-Probleme beseitigt ist jetzt kein wahnsinnig aussagekräftiger Titel :)

Also beim abholen von größeren Mengen an Kontoumsätzen war mein Heap immer wieder schnell voll und entsprechend kam es dann zu nem "Out of Memory".

Ich hab mal geguckt ob ich bei der parseMT940() irgendwas anpassen kann und habs jetzt auch hinbekommen das ich jetzt alle meine Kontoauszüge abholen kann. Mein Buffer vor dem parsen ist ca 1,2 MB groß.

In der parseMT940() habe ich jetzt nicht allzu viel geändert, ich habe ein paar Strings rausgenommen die Redundant waren zB. beim extrahieren der Kontodaten. Und vorallem dem booked-String habe ich entfernt da er die ganze Zeit alle Daten hält genau wie der buffer. Ich verwende jetzt nur noch den Buffer entsprechend musste ich auch die Funktion org.kapott.hbci.swift.Swift.getOneBlock(String stream); anpassen.

Um das ganze unterscheiden zu können habe ich die neue Funktion in Swift cutNextBlock(StringBuffer buffer); genannt. Diese schneidet nun den benötigten Teil direkt aus dem Buffer raus und kürzt ihn auf die neue Länge.


Hier mal meine beiden neuen Funktionen:

org.kapott.hbci.swift.Swift.cutNextBlock(StringBuffer buffer);
Code
public static String cutNextBlock(StringBuffer buffer) {
  String ret = null;

  int endpos = buffer.indexOf("\r\n:20:", 1);

  if(endpos == -1)
    endpos = buffer.length();

  if(endpos>0) {
    ret = buffer.substring(0,endpos);
    buffer.delete(0, endpos);
    buffer.trimToSize();
  }

  return ret; 
}


org.kapott.hbci.GV_Result.parseMT940();
Code
private void parseMT940() {
  HBCIUtils.log("now parsing MT940 data", HBCIUtils.LOG_DEBUG);
  parsed = true;

  try {

    // split into "buchungstage"
    while (buffer.length()!=0) {
      int next = 0;
      String cd = "";
      String st_tag = Swift.cutNextBlock(buffer);
      if(st_tag==null) break;

      GVRKUms.BTag btag = new GVRKUms.BTag();

      // extract konto data
      String konto_info = Swift.getTagValue(st_tag, "25", 0);
      int pos = konto_info.indexOf("/");

      btag.my = new Konto();
      if (pos!=-1) {
        btag.my.blz = konto_info.substring(0,pos);
        btag.my.number = konto_info.substring(pos+1);
        btag.my.curr = null;

        for(pos = btag.my.number.length()-1; pos>=0; pos--) {
          char ch = btag.my.number.charAt(pos);
          if(ch>='0' && ch<='9') break;
        }

        if(pos<btag.my.number.length()) {
          btag.my.curr  = btag.my.number.substring(pos);
          btag.my.number  = btag.my.number.substring(0,pos);
        }
      }
      else {
        btag.my.blz = "";
        btag.my.number = konto_info;
        btag.my.curr = "";
      }
      getPassport().fillAccountInfo(btag.my);

      // extract "auszugsnummer"
      btag.counter = Swift.getTagValue(st_tag, "28C", 0);


      // extract "anfangssaldo"
      String st_start = "";
      btag.start = new Saldo();

      // StartTyp F
      if(st_tag.indexOf(":60F:")>=0) {
        btag.starttype = 'F';
        st_start = Swift.getTagValue(st_tag, "60F", 0);
      }
      // StartTyp M
      else {
        btag.starttype = 'M';
        st_start = Swift.getTagValue(st_tag, "60M", 0);
      }
      cd = st_start.substring(0, 1);

      next = 0;
      if(st_start.charAt(2)>'9') {
        btag.start.timestamp=null;
        next = 2;
      }
      else {
        btag.start.timestamp = dateFormat.parse(st_start.substring(1,7));
        next = 7;
      }

      // hier aus dem CD-Indikator und dem absoluten Saldo-Betrag
      // einen String für den Saldo-Betrag zusamennbauen
      btag.start.value =
        new Value( (cd.equals("D") ? "-" : "") +
              st_start.substring(next+3).replace(',', '.'),
              st_start.substring(next, next+3) );


      // looping to get all "umsaetze"
      long saldo = Math.round(btag.start.value.getLongValue());
      int  ums_counter = 0;
      cd = st_tag.substring(0, 1);

      while(true) {
        String st_ums = Swift.getTagValue(st_tag,"61",ums_counter);
        if(st_ums==null) break;

        GVRKUms.UmsLine line = new GVRKUms.UmsLine();

        // extract valuta
        line.valuta = dateFormat.parse(st_ums.substring(0,6));

        // extract bdate
        next = 0;
        if(st_ums.charAt(6)>'9') {
          line.bdate = line.valuta;
          next = 6;
        }
        else {
          line.bdate = dateFormat.parse(st_ums.substring(0,2) + st_ums.substring(6,10));

          // wenn bdate und valuta um mehr als einen monat voneinander
          // abweichen, dann ist das jahr des bdate falsch (1.1.2005 vs. 31.12.2004)
          // korrektur des bdate-jahres in die richtige richtung notwendig
          if(Math.abs(line.bdate.getTime()-line.valuta.getTime()) > 30L*24*3600*1000) {
            int diff = 0;

            if(line.bdate.before(line.valuta)) diff = +1;
            else diff = -1;

            Calendar cal = Calendar.getInstance();
            cal.setTime(line.bdate);
            cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + diff);
            line.bdate = cal.getTime();
          }

          next=10;
        }

        // extract credit/debit
        if(st_ums.charAt(next)=='C' || st_ums.charAt(next)=='D') {
          line.isStorno = false;
          cd = st_ums.substring(next, next+1);
          next++;
        }
        else {
          line.isStorno = true;
          cd = st_ums.substring(next+1, next+2);
          next += 2;
        }

        // skip part of currency
        char currpart = st_ums.charAt(next);
        if(currpart>'9') next++;

        line.value = new Value();
        line.value.setCurr(btag.start.value.getCurr());

        // extract value and skip code
        int npos = st_ums.indexOf("N", next);

        // welcher Code (C/D) zeigt einen negativen Buchungsbetrag
        // an? Bei einer "normalen" Buchung ist das D(ebit). Bei
        // einer Storno-Buchung ist der Betrag allerdings negativ,
        // wenn eine ehemalige Gutschrift (Credit) storniert wird,
        // in dem Fall wäre als "C" der Indikator für den negativen
        // Buchungsbetrag
        String negValueIndikator = line.isStorno ? "C" : "D";
        line.value.setValue(HBCIUtilsInternal.string2Long( (cd.equals(negValueIndikator) ? "-" : "") + st_ums.substring(next, npos).replace(',','.'), 100));
        next = npos + 4;

        // update saldo
        saldo += line.value.getLongValue();
        line.saldo = new Saldo();
        line.saldo.timestamp = line.bdate;
        line.saldo.value = new Value(saldo, btag.start.value.getCurr());

        // extract customerref
        npos = st_ums.indexOf("//", next);
        if(npos==-1) npos = st_ums.indexOf("\r\n", next);
        if(npos==-1) npos = st_ums.length();
        line.customerref = st_ums.substring(next, npos);
        next = npos;

        // check for instref
        if(next<st_ums.length() && st_ums.substring(next, next+2).equals("//")) {
          // extract instref
          next += 2;
          npos = st_ums.indexOf("\r\n", next);
          if(npos==-1) npos = st_ums.length();
          line.instref = st_ums.substring(next, npos);
          next = npos+2;
        }
        if(line.instref==null) line.instref = "";

        // check for additional information
        if(next < st_ums.length() && st_ums.charAt(next)=='\r') {
          next+=2;

          // extract orig Value
          pos = st_ums.indexOf("/OCMT/", next);
          if(pos!=-1) {
            int slashpos = st_ums.indexOf("/", pos+9);
            if(slashpos==-1) slashpos = st_ums.length();

            line.orig_value = new Value(st_ums.substring(pos+9, slashpos).replace(',','.'), st_ums.substring(pos+6, pos+9));
          }

          // extract charge Value
          pos = st_ums.indexOf("/CHGS/", next);
          if(pos!=-1) {
            int slashpos = st_ums.indexOf("/", pos+9);
            if(slashpos==-1) slashpos = st_ums.length();

            line.charge_value = new Value(st_ums.substring(pos+9, slashpos).replace(',','.'), st_ums.substring(pos+6, pos+9));
          }
        }

        String st_multi = Swift.getTagValue(st_tag, "86", ums_counter);
        if(st_multi!=null) {
          line.gvcode = st_multi.substring(0,3);
          st_multi = Swift.packMulti(st_multi.substring(3));

          if(!line.gvcode.equals("999")) {
            line.text = Swift.getMultiTagValue(st_multi, "00");
            line.primanota = Swift.getMultiTagValue(st_multi, "10");
            for(int i=0; i<10; i++)
              line.addUsage(Swift.getMultiTagValue(st_multi,Integer.toString(20+i)));

            Konto acc = new Konto();
            acc.blz    = Swift.getMultiTagValue(st_multi, "30");
            acc.number  = Swift.getMultiTagValue(st_multi, "31");
            acc.name  = Swift.getMultiTagValue(st_multi, "32");
            acc.name2  = Swift.getMultiTagValue(st_multi, "33");

            if (acc.blz!=null || acc.number!=null || acc.name!=null || acc.name2!=null) {
              if(acc.blz==null)    acc.blz    = "";
              if(acc.number==null)  acc.number  = "";
              if(acc.name==null)    acc.name  = "";
              line.other = acc;
            }

            line.addkey = Swift.getMultiTagValue(st_multi, "34");
            for(int i=0; i<4; i++)
              line.addUsage(Swift.getMultiTagValue(st_multi,Integer.toString(60+i)));
          }
          else line.additional=st_multi;
        }

        btag.addLine(line);
        ums_counter++;
      }

      // extract "schlusssaldo"
      String st_end = "";
      btag.end = new Saldo();

      // StartTyp F
      if(st_tag.indexOf(":62F:")>=0) {
        btag.endtype = 'F';
        st_end = Swift.getTagValue(st_tag, "62F", 0);
      }
      // StartTyp M
      else {
        btag.endtype = 'M';
        st_end = Swift.getTagValue(st_tag, "62M", 0);
      }
      cd = st_end.substring(0,1);

      next = 0;
      if(st_end.charAt(2)>'9') {
        btag.end.timestamp = null;
        next = 2;
      }
      else {
        btag.end.timestamp=dateFormat.parse(st_end.substring(1,7));
        next=7;
      }


      // set default values for optional non-given bdates
      if(btag.start.timestamp==null)
        btag.start.timestamp = btag.end.timestamp;

      for(UmsLine line: btag.lines)
        if(line.bdate == null)
          line.bdate = btag.end.timestamp;


      btag.end.value = new Value((cd.equals("D")?"-":"") + st_end.substring(next+3).replace(',', '.'), st_end.substring(next, next+3));
      addTag(btag);
    }

    // remove this debugging output
    HBCIUtils.log("Parsing of MT940 ok until now; unparsed data: " + buffer, HBCIUtils.LOG_DEBUG2);
  }
  catch (Exception e) {
    HBCIUtils.log("There is unparsed MT940 data - an exception occured while parsing", HBCIUtils.LOG_ERR);
    HBCIUtils.log("current MT940 buffer: " + buffer, HBCIUtils.LOG_DEBUG2);
    throw new HBCI_Exception(e);
  }
  finally {
    rest = buffer.toString();
  }
}
Benutzer
Avatar
Geschlecht: keine Angabe
Herkunft: Leipzig
Homepage: willuhn.de/
Beiträge: 10130
Dabei seit: 03 / 2005
Betreff:

Re: [hbci4java] parseMT940() Heap-Probleme beseitigt

 · 
Gepostet: 05.03.2008 - 13:37 Uhr  ·  #2
Benutzer
Avatar
Geschlecht: keine Angabe
Beiträge: 13
Dabei seit: 03 / 2008
Betreff:

Re: [hbci4java] parseMT940() Heap-Probleme beseitigt

 · 
Gepostet: 05.03.2008 - 14:55 Uhr  ·  #3
Ah, ok THx.
Hatte bloß von der hbci4java-Homepage den Link hier her gefunden und dachte dann dass dieses Forum als Plattform dafür dient :)
Gewählte Zitate für Mehrfachzitierung:   0