Search code examples
bean-io

how to write fixedlength file to CSV file with bean io with all values come in diffent columns of a record


This code is able to write data to csv file but the only problem is the data is getting written in single column only.

I want the data to come in different column. I am new to bean io and not able to figure it out.

I have tried below given code and not able get output in proper format:

public class XlsWriter {

public static void main(String[] args) throws Exception {

StreamFactory factory = StreamFactory.newInstance();




  factory.load("C:\\Users\\PV5057094\\Demo_workspace\\XlsxMapper\\src\\main\\resources\\Employee.xml");

          Field[] fields = Employee.class.getDeclaredFields();

          System.out.println("fileds" + fields.length);
          List<Object> list = new ArrayList<Object>();
          for (Field field : fields) {

                 list.add(field.getName());

          }


          BeanReader in = factory.createReader("EmployeeInfo", new File("C:\\Temp\\Soc\\textInput.txt"));




          BeanWriter out = factory.createWriter("EmployeeInfo", new File("C:\\Temp\\Soc\\output.csv"));

          Object record;

          while ((record = in.read()) != null) {
                 System.out.println(record.toString().length());


                 out.write(record);

                 System.out.println("Record Written:" + record.toString());

          }

          in.close();
          out.flush();
          out.close();
   }


}

textInput.txt
AAAAABBBBBCCCCC
AAAAABBBBBCCCCC
AAAAABBBBBCCCCC
AAAAABBBBBCCCCC
AAAAABBBBBCCCCC



<?xml version="1.0" encoding="UTF-8"?>
<beanio xmlns="http://www.beanio.org/2012/03"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">

   <stream name="EmployeeInfo" format="fixedlength">

          <record name="employee"
                 class="com.aexp.gmnt.imc.record.submission.Employee" minOccurs="0"
                 maxOccurs="unbounded" order="1">
                 <field name="firstName" length="5" padding="0" justify="right" />
                 <field name="lastName"  length="5" padding="0" justify="right"/>
                 <field name="title" length="5" padding="0" justify="right"/>

          </record>
   </stream>

I want every record value in different column of a CSV file, but currently it is comming in a single column only, please help.


Solution

  • You need to have a different stream definition in your mapping file for writing to the CSV file. The EmployeeInfo stream can only deal with fixed length content because that is how it is configured.

    You need to add a second <stream> definition to handle the CSV file you want to generate and your BeanWriter need to reference the new CSV stream instead of the fixed length one.

    Add a new <stream> definition to your existing mapping.xml file:

    <stream name="EmployeeInfoCSV" format="csv">
      <record name="employee" class="com.aexp.gmnt.imc.record.submission.Employee" minOccurs="0" maxOccurs="unbounded">
        <field name="firstName" />
        <field name="lastName" />
        <field name="title" />
      </record>
    </stream>
    

    Note the change in the name of the <stream> and the format set to csv. In this <stream> definition you can then also change the order in which the data is written to the csv file if you want to without affecting your BeanReader's order in which it expects to read the data. The length,padding and justify attributes are not required for a csv file.

    Now you only need to change how you configure your BeanWriter from:

    BeanWriter out = factory.createWriter("EmployeeInfo", new File("C:\\Temp\\Soc\\output.csv"));
    

    to

    BeanWriter out = factory.createWriter("EmployeeInfoCSV", new File("C:\\Temp\\Soc\\output.csv"));
    

    Note the change to use the csv stream name in the createWriter method parameters.


    Edit to answer this question from the comments:

    just a added question of I need to add the as first line with header values as field values without writing them as header record type in bean io then is it possible through reflection or something?

    No need for reflection or jumping through hoops to get it done. You can create a Writer that you can use to write out the header (column) names to the file first before passing the writer to the BeanWriter for appending the rest of the output.

    Instead of using the BeanWriter like above:

    BeanWriter out = factory.createWriter("EmployeeInfoCSV", new File("C:\\Temp\\Soc\\output.csv"));
    

    You would now do something like:

    BufferedWriter writer = new BufferedWriter(new FileWriter(new File("C:\\Temp\\Soc\\output.csv")));
    writer.write("First Name,Last Name,Title");
    writer.newLine();
    
    BeanWriter out = factory.createWriter("EmployeeInfoCSV", writer);
    

    BeanIO would then carry on writing its output to the writer which will append the data to the existing file. Remember to close() the writer as well when you are done.