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.

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Sep 26, 2016 at 16:16
\$\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\$ Commented Sep 26, 2016 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\$ Commented Sep 26, 2016 at 16:48
  • 1
    \$\begingroup\$ It would have been a good idea to include a sample of the data. \$\endgroup\$ Commented Apr 10, 2017 at 22:12
  • \$\begingroup\$ @200_success fair enough, I added some sample data, please let me know if it helped \$\endgroup\$ Commented Apr 11, 2017 at 14:25

1 Answer 1

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 [email protected] 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
answered Apr 10, 2017 at 21:50
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.