3
\$\begingroup\$

I'm working on an important project. We're an IT services provider and we have a project where we have to build a new system to process data from a specific client.

The problem is that usually we process their data, but they send us a pre-processed data that's easy to parse, but this time around, they're trying with a new format, which is extremely weird.

Anyways, there were two senior programmers that didn't want to mess with the project, and it's been on hold for one whole year. I'm a junior programmer and I managed to build a system that kind of works as intended but I want to improve on it. I don't like the way it ended up, even if it works.

The thing is, this format is for generating account statements for a local bank, and they're sending in RAW data. I managed to read and parse the data by using a configuration file that's able to read the data from it's position on the file, which can have up to 500 MB of text data. I built a loadInfo() method that uses reflection to fill in the data in the different classes.

The data comes grouped in Registers, which have many fields. Each Register holds specific information, like transactions, client info, balances and stuff. I created a superclass called Register, and then made the other corresponding types of register extend from this superclass. The thing is that there are 17 different kinds of registers, and a Register can have from 1 to more than 30 members.

I only use one loadInfo() from the Register superclass, and using reflection I can set the member variables for all the other registers.

I feel that my approach is kind of stupid, even if it works, and I'd like to improve it and make it more clean. Right now the whole system has like 25 different classes and I feel that my solution is too disorganized. Any advice on how to improve on my design?

I'm going to just include the code for the Registry that contains the information for the client. We are talking about bank data here, and this code is used to generate statement accounts. Please note that the class was designed this way because that's the way the customer documented it, and the way the data is arranged in the text file we receive:

This is FieldParser class:

package Parser;

public class FieldParser {
    public static String getStringValue(String rawData, int initPos, int length){
        String tmpStr = rawData.substring(initPos, initPos + length);
        return tmpStr.trim();
    }

    public static String getNumericValue(String rawData, int initPos, int length, int decimalPlaces){
        String tmpStr = rawData.substring(initPos, initPos + length);
        tmpStr = tmpStr.trim();

        // si el valor numerico incluye posiciones decimales
        if(decimalPlaces > 0){          
            // agregar el '.' en la posicion decimal correspondiente            
            tmpStr = addDecimalPlaces(tmpStr, decimalPlaces);
        }

        return tmpStr;
    }

    // funcion que inserta un punto decimal dependiendo de la cantidad de lugares decimales
    private static String addDecimalPlaces(String rawData, int decimalPlaces){

        // cadena temporal en la cual podemos llamar Insert
        StringBuilder tmpStr = new StringBuilder(rawData);

        // verifica si ya la cadena contiene el punto decimal
        if(!rawData.contains(".")){
            // obten el largo total de la cadena
            int len = rawData.length();

            // restar la cantidad de posiciones decimales de la longitud de la cadena
            // luego insertar el punto decimal en la posicion correspondiente
            if(tmpStr.length() > 0){                
                tmpStr.insert(len - decimalPlaces, ".");
            }           
        }

        return tmpStr.toString();
    }   
}

This is the Campo class:

import Parser.FieldParser;

public class Campo {    
    private String fieldValue;  
    private int initIdx;        // starting index of the field in the data
    private int endIdx;         // ending index of the field in the data
    private int decimalPlaces;  // decimal places if the field is numeric 

    public Campo(){
        fieldValue = "";
    }

    public Campo(String fieldValue){
        this.setFieldValue(fieldValue);
    }

    public Campo(int initIdx, int len, int decimalPlaces){      
        this.setInitIdx(initIdx);
        this.setEndIdx(len);
        this.setDecimalPlaces(decimalPlaces);
    }

    public static String getField(String fieldParams, String rawData){
        // separa el campo
        String[] fields = fieldParams.split("-");

        int fieldStart = Integer.parseInt(fields[0]);   // obtiene la posicion inicial del campo
        int fieldLen = Integer.parseInt(fields[1]); // obtiene longitud del campo

        // extrae la informacion de la data
        String fieldValue = FieldParser.getStringValue(rawData, fieldStart, fieldLen);

        return fieldValue;      
    }

    public static String getField(String fieldParams, String rawData, String expr){

        String fieldValue = null;
        // separa el campo
        String[] fields = fieldParams.split(expr);      

        int fieldStart = Integer.parseInt(fields[0]);   // obtiene la posicion inicial del campo
        int fieldLen = Integer.parseInt(fields[1]); // obtiene longitud del campo
        int decimalPlaces = Integer.parseInt(fields[2]);    // obtiene las posiciones decimales

        // si el campo indica posiciones decimales
        if(decimalPlaces > 0){
            // extra le informacion como un valor numerico
            fieldValue = FieldParser.getNumericValue(rawData, fieldStart, fieldLen, decimalPlaces);
        }else{
            // extrae la informacion como un valor regular
            fieldValue = FieldParser.getStringValue(rawData, fieldStart, fieldLen);
        }       

        return fieldValue;      
    }

    public void setFieldValue(String value){        
        this.fieldValue = value;
    }

    @Override
    public String toString(){
        return this.fieldValue.toString();
    }

    public int getInitIdx(){
        return this.initIdx;
    }

    public int getEndIdx(){
        return this.endIdx;
    }

    public int getDecimalPlaces(){
        return this.decimalPlaces;
    }

    public String getFieldValue(){
        return this.fieldValue;
    }

    private void setInitIdx(int initIdx){
        this.initIdx = initIdx;
    }

    private void setEndIdx(int len){
        this.endIdx = this.initIdx + len;
    }

    private void setDecimalPlaces(int decimalPlaces){
        this.decimalPlaces = decimalPlaces;
    }
}

This is the Register base class:

import java.lang.reflect.Field;

public abstract class Registro {
    // informacion de posicion de inicio, longitud y posiciones decimales de todos los 
    // campos que forman parte del registro
    private String dataReg; 
    private String idReg;  // identificador del registro

    public Registro(){
        this.idReg = "";
    }

    public Registro(String dataReg){
        this();
        this.setDataRegistro(dataReg);
    }

    public void loadInfo(String rawData){
        //System.out.println("Dentro de " + this.getClass().getSimpleName());
        String data = this.getDataRegistro();
        //System.out.println(rawData);

        // separa cada uno de los campos del registro
        String[] campos = data.split("\\|");                

        // obten todos los campos privados del registro que invoco este metodo
        Field[] allFields = this.getClass().getDeclaredFields();        

        for(int i = 0; i < allFields.length; i++){
            //Campo field;
            try {
                //field = (Campo) allFields[i].getType().getConstructor().newInstance();

                // separa los valores que se encuentran alojados en cada campo:
                // posicion de inicio, longitud y lugares decimales, asi obtiene el valor
                // que se encuentra alojado en la linea de datos del archivo de estados
                // y lo guarda en la variable fieldValue
                String fieldValue = Campo.getField(campos[i], rawData, "_");

                // permite el acceso a los campos privados de la instancia de tipo Registro
                // que invoco este metodo
                allFields[i].setAccessible(true);

                // asigna el valor extraido a cada uno de los campos privados de la instancia 
                //  de tipo Registro que invoco este metodo, 
                allFields[i].set(this, new Campo(fieldValue));
                //System.out.println("Field Value: " + fieldValue);
            } catch (IllegalAccessException | IllegalArgumentException
                    | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        this.callSetters();
    }

    public abstract void callSetters();

    protected abstract String buildString();

    public void setDataRegistro(String dataReg){
        this.dataReg = dataReg;
    }

    public void setIdRegistro(String idReg){
        this.idReg = idReg;
    }

    public String getDataRegistro(){
        return this.dataReg;
    }

    public String getIdRegistro(){
        return this.idReg;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return this.buildString();
    }


}

This is the Register for Client Info:

public class RegistroCL extends Registro{

    private Campo nombre;  // nombre de cliente
    private Campo apellido1;  // primer apellido del cliente
    private Campo apellido2;  // segundo apellido del cliente
    private Campo formaEnvio;  // forma de envio del extracto
    private Campo email;  // email del cliente
    private Campo codPais;  // codigo pais
    private Campo nomPais;  // nombre pais
    private Campo codRegion;  // codigo region
    private Campo desRegion;  // nombre region
    private Campo codProv;  // codigo provincia
    private Campo desProv;  // nombre provincia
    private Campo ciudad;  // codigo ciudad
    private Campo desCiudad;  // nombre ciudad
    private Campo codMunicip;  // codigo municipio
    private Campo municipio;  // municipio
    private Campo codSector;  // codigo sector
    private Campo sector;  // sector
    private Campo codBarrio;  // codigo barrio
    private Campo barrio;  // barrio
    private Campo tipVia;  // tipo de via
    private Campo nomVia;  // codigo via
    private Campo descNomVia;  // nombre de la via
    private Campo numVia;  // numero del domicilio
    private Campo escalera;  // escalera
    private Campo piso;  // piso
    private Campo puerta;  // puerta
    private Campo manzana;  // manzana
    private Campo edificio;  // edificio
    private Campo kilometro;  // kilometro
    private Campo codPostal;  // zona postal
    private Campo aptdoCorreos;  // apartado de correos
    private Campo entreCalles1;
    private Campo desEntreCalles1;  // entre que calles vive 1
    private Campo entreCalles2;
    private Campo desEntreCalles2;  // entre que calles vive 2
    private Campo restoDir;  // resto de direccion

    public RegistroCL(String dataReg){
        super(dataReg);
    }

    public void setCodigoProvincia(String value){

        /*
         * Removes leading zeroes
         */
        if(!value.isEmpty()){
            value = Integer.valueOf(value).toString();
            this.codProv.setFieldValue(value);
        }

    }

    public String getNombre() {
        return this.nombre.getFieldValue();
    }

    public String getApellido1() {
        return this.apellido1.getFieldValue();
    }

    public String getApellido2() {
        return this.apellido2.getFieldValue();
    }


    public String getFormaEnvio() {
        String result = "";  

        if(this.formaEnvio.getFieldValue().equals("EM")){
            result = "ENVIAR A " + this.getEmail();
        }else if(this.formaEnvio.getFieldValue().equals("CO")){
            result = this.getDesEntreCalles1() + " " + this.getManzana() + " " + 
                     " " + this.getDescNomVia() + " " + this.getNumVia() + " " + 
                    this.getEdificio() + " " + this.getPiso() + " " + this.getPuerta();
        }

        return result;
    }

    public String getDireccion(){
        String str = "";

        String calle = this.getDescNomVia() + (this.getDescNomVia().isEmpty() ? "" : " ");
        String numero = this.getNumVia() + (this.getNumVia().isEmpty() ? "" : " ");
        String manzana = this.getManzana() + (this.getManzana().isEmpty() ? "" : " ");
        String edif = this.getEdificio() + (this.getEdificio().isEmpty() ? "" : " ");
        String piso = this.getPiso() + (this.getPiso().isEmpty() ? "" : " ");
        String apto = this.getPuerta() + (this.getPuerta().isEmpty() ? "" : " ");
        String calle1 = (this.getDesEntreCalles1().isEmpty() ? "" : " Entre ") + this.getDesEntreCalles1();
        String calle2 = (this.getDesEntreCalles2().isEmpty() ? "" : " y ") + this.getDesEntreCalles2();

        str = calle + numero + this.getDesEntreCalles1() + " " + manzana + " " + 
              " " + edif 
              + " " + piso + " " + apto + calle1 + calle2;

        return str;
    }

    public String getEmail() {
        return this.email.getFieldValue();
    }

    public String getCodPais() {
        return this.codPais.getFieldValue();
    }

    public String getNomPais() {
        return this.nomPais.getFieldValue();
    }

    public String getCodRegion() {
        return this.codRegion.getFieldValue();
    }

    public String getDesRegion() {
        return this.desRegion.getFieldValue();
    }

    public String getCodProv() {
        return this.codProv.getFieldValue();
    }

    public String getDesProv() {
        return this.desProv.getFieldValue();
    }

    public String getCiudad() {
        return this.ciudad.getFieldValue();
    }

    public String getDesCiudad() {
        return this.desCiudad.getFieldValue();
    }

    public String getCodMunicip() {
        return this.codMunicip.getFieldValue();
    }

    public String getMunicipio() {
        return this.municipio.getFieldValue();
    }

    public String getCodSector() {
        return this.codSector.getFieldValue();
    }

    public String getSector() {
        return this.sector.getFieldValue();
    }

    public String getCodBarrio() {
        return this.codBarrio.getFieldValue();
    }

    public String getBarrio() {
        return this.barrio.getFieldValue();
    }

    public String getTipVia() {
        return this.tipVia.getFieldValue();
    }

    public String getNomVia() {
        return this.nomVia.getFieldValue();
    }

    public String getDescNomVia() {
        return this.descNomVia.getFieldValue();
    }

    public String getNumVia() {
        return this.numVia.getFieldValue();
    }

    public String getEscalera() {
        return this.escalera.getFieldValue();
    }

    public String getPiso() {
        return this.piso.getFieldValue();
    }

    public String getPuerta() {
        return this.puerta.getFieldValue();
    }

    public String getManzana() {
        return this.manzana.getFieldValue();
    }

    public String getEdificio() {
        return this.edificio.getFieldValue();
    }

    public String getKilometro() {
        return this.kilometro.getFieldValue();
    }

    public String getCodPostal() {
        return this.codPostal.getFieldValue();
    }

    public String getAptdoCorreos() {
        return this.aptdoCorreos.getFieldValue();
    }

    public String getEntreCalles1() {
        return this.entreCalles1.getFieldValue();
    }

    public String getDesEntreCalles1() {
        return this.desEntreCalles1.getFieldValue();
    }

    public String getEntreCalles2() {
        return this.entreCalles2.getFieldValue();
    }

    public String getDesEntreCalles2() {
        return this.desEntreCalles2.getFieldValue();
    }

    public String getRestoDir() {
        return this.restoDir.getFieldValue();
    }   

    @Override
    public void callSetters() {
        this.setCodigoProvincia(this.getCodProv());     
    }

    @Override
    protected String buildString() {
        String output = this.getNombre();
        output = output.concat(" " + this.getApellido1());
        output = output.concat(" " + this.getApellido2() + "\n");
        output = output.concat(this.getFormaEnvio());

        return output;
    }   
}

What should I do if I want to refactor this class? I've been thinking of treating it as just a simple data structure instead of like a class, since all the RegistroCL does in the file is hold data about the client, but I'm not pretty sure of what to do here. There are 17 Registro classes, and each one holds a different number of Campo members, which stand for "fields." I'm also thinking of eliminating the extra Campo class, since I feel it does nothing to improve the design. My intention at first was to have different kinds of "fields" like MonetaryField, DateField and so on.

\$\endgroup\$
4
  • \$\begingroup\$ Welcome to code review, I'd say very nice first question, but I'm worried about the banks copyright. You may have licensing issues with what you are doing here, Stack Exchange has their own license which may not fit with your employers. Please look at this page meta.stackexchange.com/questions/12527/…. \$\endgroup\$ – pacmaninbw Sep 26 '16 at 16:26
  • \$\begingroup\$ Well...I'm not specifying which bank it is, and I don't have access to their internal data. I created the code posted above and is not even the full code. Please, if there's any mention of the bank's name on my code point it out so I can edit it and remove it. Thanks in advance, and thanks for the concern, I was worried about the same thing too, but I'm kind of desperate and I don't have no one I can rely on this.... \$\endgroup\$ – Anubis Lockward Sep 26 '16 at 16:48
  • 1
    \$\begingroup\$ It would have been a good idea to include a sample of the data. \$\endgroup\$ – 200_success Apr 10 '17 at 22:12
  • \$\begingroup\$ @200_success fair enough, I added some sample data, please let me know if it helped \$\endgroup\$ – Anubis Lockward Apr 11 '17 at 14:25
2
\$\begingroup\$

It's been a while since I asked this question and I'm still working on this project, so far, these are the refactorings that I've been able to make so far.

First, I changed the way all Registers are created, and then modified the parent Registry class like this:

import java.util.ArrayList;
import java.util.List;

public abstract class Registro {
    // dataReg holds information about the starting position, length and decimal places
    // for all the fields that make up the Registry
    private String dataReg; 
    private String idReg;  // registry ID
    private String[] fields;
    protected List<Campo> fieldValues;

    public Registro(){      
    }

    public Registro(String dataReg){
        this();
        this.setDataRegistro(dataReg);
    }   

    public void setDataRegistro(String dataReg){
        this.fields= dataReg.split("\\|");      
    }

    public void loadInfo(String rawData) {
        this.setListaValores(rawData);

        callSetters();
    }

    public void setListaValores(String rawData) {
        this.fieldValues= new ArrayList<Campo>();

        for(String valor : getCampos()) {
            this.fieldValues.add(new Campo(Campo.getField(valor, rawData, "_")));
        }
    }

    public String[] getCampos() {
        return this.fields;
    }

    public abstract void callSetters();

    public void setIdRegistro(String idReg){
        this.idReg = idReg;
    }

    public List<Campo> getListaValores() {
        return this.fieldValues;
    }

    public String getDataRegistro(){
        return this.dataReg;
    }

    public String getIdRegistro(){
        return this.idReg;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return this.buildString();
    }

    protected abstract String buildString();
}

In my first implementation, I couldn't control very well the way that the Registry's childs were created since I used reflection to access all private members of each Registry sub-class and created them by using Campo's constructors, which didn't give me much control on their creation.

Here's the modified RegistroCL that holds the client's information:

public class RegistroCL extends Registro{

    private ClientInfo _person;

    public RegistroCL(String dataReg){
        super(dataReg);
        setIdRegistro("CL");
    }

    public String getFullName() {
        return _person.getFullName();
    }

    public String getName() {
        return _person.getName();
    }

    public String getFirstLastName() {
        return _person.getFirstLastName();
    }

    public String getSecondLastName() {
        return _person.getSecondLastName();
    }

    public String getPhysicalAddress(){
        return _person.getPhysicalAddress();
    }

    public String getEmail() {
        return _person.getEmail();
    }

    public String getDesProv() {
        return _person.getProvincia();
    }

    public String getMunicipio() {
        return _person.getMunicipio();
    }

    public String getSector() {
        return _person.getSector();
    }

    public String getStreet() {     
        return _person.getStreet();
    }

    public String getBuildingNumber() {
        return _person.getBuildingNumber();
    }

    public String getFloorNumber() {
        return _person.getFloorNumber();
    }

    public String getApartmentNumber() {
        return _person.getApartmentNumber();
    }

    public String getBlock() {      
        return _person.getBlock();
    }

    public String getBuildingName() {
        return _person.getBuildingName();
    }

    public String getDesEntreCalles1() {
        return _person.getDesEntreCalles1();
    }

    public String getDesEntreCalles2() {
        return _person.getDesEntreCalles2();
    }

    @Override
    public void callSetters() {
        _person = new ClientInfo(this.getListaValores());
    }

    @Override
    protected String buildString() {
        String output = this.getName();
        output = output.concat(" " + this.getFirstLastName());
        output = output.concat(" " + this.getSecondLastName() + "\n");

        return output;
    }
}

Here's the new ClientInfo class:

import java.util.List;

public class ClientInfo {
    private List<Campo> _dataSource;
    private String _name;
    private String _firstLastName;
    private String _secondLastName;
    private PhysicalAddress _physicalAddress;   
    private String _email;  

    public ClientInfo(List<Campo> dataSource) {
        _dataSource = dataSource;
        create();
    }

    public void create() {      
        _name = _dataSource.get(0).getFieldValue();
        _firstLastName = _dataSource.get(1).getFieldValue();
        _secondLastName = _dataSource.get(2).getFieldValue();
        _email = _dataSource.get(4).getFieldValue().trim().toUpperCase();
        _physicalAddress = new PhysicalAddress(_dataSource);
    }

    public String getFullName() {
        return getName() + getFirstLastName() + getSecondLastName();
    }

    public String getName() {
        return String.format("%1$-40s", _name);
    }

    public String getFirstLastName() {
        return String.format("%1$-36s", 
                appendCharacterToOriginalStringIfNotEmpty(_firstLastName, ' '));
    }

    private String appendCharacterToOriginalStringIfNotEmpty(String str, char appendWhat) {
        return !str.isEmpty() ? appendWhat + str : "";
    }

    public String getSecondLastName() {
        return String.format("%1$-36s", 
                appendCharacterToOriginalStringIfNotEmpty(_secondLastName, ' '));
    }

    public String getEmail() {              
        return (_email.isEmpty() ? "--" : "EMAIL: " + _email);
    }

    public String getPhysicalAddress() {
        return _physicalAddress.getDireccion();
    }

    public String getProvincia() {
        return _physicalAddress.getProvincia();
    }

    public String getMunicipio() {
        return _physicalAddress.getMunicipio();
    }

    public String getSector() {
        return _physicalAddress.getSector();
    }

    public String getStreet() {     
        return _physicalAddress.getStreet();
    }

    public String getBuildingNumber() {
        return _physicalAddress.getBuildingNumber();
    }

    public String getFloorNumber() {
        return _physicalAddress.getFloorNumber();
    }

    public String getApartmentNumber() {
        return _physicalAddress.getApartmentNumber();
    }

    public String getBlock() {      
        return _physicalAddress.getBlock();
    }

    public String getBuildingName() {
        return _physicalAddress.getBuildingName();
    }

    public String getDesEntreCalles1() {
        return _physicalAddress.getDesEntreCalles1();
    }

    public String getDesEntreCalles2() {
        return _physicalAddress.getDesEntreCalles2();
    }
}

And here's the new PhysicalAddress class:

import java.util.List;

public class PhysicalAddress {
    private List<Campo> _clientData;
    private String _street;
    private String _buildingNumber;
    private String _block;
    private String _buildingName;
    private String _floorNumber;
    private String _apartmentNumber;
    private String _entreCalle1;
    private String _entreCalle2;
    private String _municipio;
    private String _sector;
    private String _provincia;

    public PhysicalAddress(List<Campo> clientData){
        _clientData = clientData;
        create();
    }

    public void create() {
        _provincia = _clientData.get(10).getFieldValue();
        _sector = _clientData.get(16).getFieldValue();      
        _street = _clientData.get(21).getFieldValue();
        _buildingNumber = _clientData.get(22).getFieldValue();
        _floorNumber = _clientData.get(24).getFieldValue();
        _apartmentNumber = _clientData.get(25).getFieldValue();
        _block = _clientData.get(26).getFieldValue();
        _buildingName = _clientData.get(27).getFieldValue();
        _entreCalle1 = _clientData.get(32).getFieldValue();
        _entreCalle2 = _clientData.get(34).getFieldValue();
        setMunicipio();
    }

    public void setMunicipio() {
        _municipio = String.format("\n    %s, %s", getSector(), getProvincia());
    }

    public String getSector() {
        return _sector;
    }

    public String getProvincia() {
        return _provincia;
    }

    public String getDireccion(){
        return getStreet() + getBuildingNumber() + getBlock() + getBuildingName() + 
                getFloorNumber() + getApartmentNumber() + getDesEntreCalles1() +
                getDesEntreCalles2() + getMunicipio();
    }

    public String getStreet() {     
        return (_street.isEmpty() ? "" : "C/ " + _street + " ");
    }

    public String getBuildingNumber() {             
        return (_buildingNumber.isEmpty() ? "" : "#" + _buildingNumber + " ");
    }

    public String getBlock() {
        return (_block.isEmpty() ? "" : "MANZ. " + _block + " ");
    }

    public String getBuildingName() {
        return (_buildingName.isEmpty() ? "" : "EDIF. " + _buildingName + " ");
    }

    public String getFloorNumber() {
        return (_floorNumber.isEmpty() ? "" : "PISO: " + _floorNumber + " ");
    }

    public String getApartmentNumber() {
        return (_apartmentNumber.isEmpty() ? "" : "APTO. " + _apartmentNumber + " " );
    }

    public String getDesEntreCalles1() {
        return (_entreCalle1.isEmpty() ? "\n    --" : "\n    ENTRE ") + _entreCalle1;
    }

    public String getDesEntreCalles2() {
        return (_entreCalle2.isEmpty() ? "\n    --" : "\n    Y ") + _entreCalle2;
    }

    public String getMunicipio() {
        return _municipio;
    }

    public PhysicalAddress getPhysicalAddress(){
        return this;
    }
}

I have refactored a bunch of other stuff too, but I guess I'm on the right track with what I'm doing right now. Back when I posted this question I was just starting to work as a programmer for the first time and I had no experienced and they threw me face first with this project and I panicked. Let me know what do you think about my modifications and if you have any other suggestions I'm all ears, please remember that this is still a work in progress and that I'm still learning so I think that there will be many more modifications to my code. Thanks a lot to those who tried to help me.

By the way, here's a sample of the code, overly simplified of course, but the whole thing is a big big mess.

Here's the data for RegistroCL, please note that I removed some info, the '9's stand for numeric type fields, and the 'A's stand for alphanumeric type fields:

CL999999999999AAAAA AAAAAAAA                          AAAAAAAA AAAA                                                           AAAAAAAAAAA@BBBBB.CCC.DD                                                                              999AAA. AAAAAAAAAA     9  AAAAAA AAA AAAA     99AAAA AAA            99   AAAAAAAA AAAAAAAA                  999  AAAA  AAA                               9999 AA AAAAAAAAA                            99999AA AAAAAA                               AA9999999 AA AAAAAAA                                                                                       999                             9999999                                                                                                                                                                                                                                      AAAAAAA / AAAAAAA AAAAA AAAAAAA AAAAAAAA                                                                       

And here's a line from the config file that I created, which contains the positions and lengths of the fields:

128-12,140-22,CL,176_40_0|216_36_0|252_36_0|288_2_0|290_100_0|390_3_0|393_20_0|413_3_0|416_20_0|436_2_0|438_20_0|458_5_0|463_35_0|498_5_0|503_40_0|543_5_0|548_40_0|588_5_0|593_40_0|633_2_0|635_5_0|640_100_0|740_6_0|746_4_0|750_4_0|754_4_0|758_10_0|768_4_0|772_7_0|779_10_0|789_10_0|799_5_0|804_100_0|904_5_0|909_100_0|1009_40_0
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.