【问题标题】:write a header so that segment default name is also printed on the basis of max occurrence写一个标题,以便段默认名称也根据最大出现次数打印
【发布时间】:2019-07-30 05:34:56
【问题描述】:

现在,我可以写标题,但不能打印段内的标题名称,有什么办法吗?

输入文件-

1john dew BA xxx  
1sam hart MA yyy

它没有在段内打印默认名称。
输出文件-

Record,FirstName,LastName,Title,Filler  
1,john,dew,22,85,22,85,22,85,BA,xxx  
1,sam,hart,78,45,78,45,78,45,MA,yyy

Java:

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");


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

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

        out.write("headers",null);
        Object record;

        while ((record=br.read())!=null) {


            out.write(record);

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

        }

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

}

BeanIO-
<?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="a" minOccurs="0" maxOccurs="unbounded"
            class="com.Employee">
            <field name="record" length="3" literal="AAA" rid="true" />
            <field name="firstName" length="5" />
            <field name="lastName" length="5" />
            <segment name="error" collection="list" minOccurs="0"
                maxOccurs="3" class="com.Error">
                <field name="origin_of_error" length="2" />
                <field name="fld_name" length="2" />

            </segment>
            <field name="title" length="5" />
            <field name="filler" length="5" />
        </record>

    </stream>


    <stream name="EmployeeInfoCSV" format="csv">
        <record name="headers" minOccurs="1" maxOccurs="1">
            <field name="recordColumn" default="Record" />
            <field name="firstNameColumn" default="FirstName" />
            <field name="lastNameColumn" default="LastName" />
            <segment name="error" collection="list" minOccurs="0"
                maxOccurs="5" class="com.Error">
                <field name="origin_of_error" default="origin_of_error" />
                <field name="fld_name" default="fld_name" />

            </segment>
            <field name="titleColumn" default="Title" />
            <field name="fillerColumn" default="Filler" />
        </record>
        <record name="a" minOccurs="0" maxOccurs="unbounded"
            class="com.Employee">
            <field name="record" length="3" literal="AAA" rid="true" />
            <field name="firstName" length="5" />
            <field name="lastName" length="5" />
            <segment name="error" collection="list" minOccurs="0"
                maxOccurs="3" class="com.Error">
                <field name="origin_of_error" length="2" />
                <field name="fld_name" length="2" />

            </segment>
            <field name="title" length="5" />
            <field name="filler" length="5" />
        </record>
    </stream>
</beanio>

预期输出-

记录,名字,姓氏,origin_of_error,fld_name,origin_of_error,fld_name,origin_of_error,fld_name,Title,Filler
1,约翰,露水,22,85,22,85,22,85,BA,xxx
1,sam,hart,78,45,78,45,78,45,MA,yyy

【问题讨论】:

  • 打印 CSV 文件中的列标题时,段是否总是重复 3 次,还是取决于错误列表的大小(记录数)?
  • 如果段的最大出现次数是 3 次,它将打印记录 3 次

标签: java bean-io


【解决方案1】:

要使列标题动态化,我们需要将列标题移动到它们自己的类中。

添加一个HeaderColumnsErrorColumns 类以包含不同列的名称。

public class HeaderColumns {

  private String recordColumn = "Record";
  private String firstNameColumn = "FirstName";
  private String lastNameColumn = "LastName";
  private String titleColumn = "Title";
  private String fillerColumn = "Filler";
  private List<ErrorColumns> errorColumns;

  public void addErrorColumns(final ErrorColumns errorColumn) {
    if (errorColumns == null) {
      errorColumns = new ArrayList<>();
    }
    errorColumns.add(errorColumn);
  }
  // getter/setters removed
}

注意addErrorColumns 方法。

public class ErrorColumns {

  private String originOfErrorColumn = "origin_of_error";
  private String fldNameColumn = "fld_name";
  // getter/setters removed
}

我们需要向Employee 类添加一个方法来返回读取的错误计数。

public class Employee {

  private String record;
  private String firstName;
  private String lastName;
  private String title;
  private String filler;
  private int errorCount;
  private List<Error> error;

  public int getErrorCount() {
    return error != null ? error.size() : 0;
  }
  // getter/setters removed
}

映射文件中列的记录定义headers 现在看起来很像数据a 的实际记录定义。

<stream name="EmployeeInfoCSV" format="csv">
  <record name="headers" minOccurs="1" maxOccurs="1" 
          class="com.HeaderColumns">
    <field name="recordColumn" rid="true" literal="Record"/>
    <field name="firstNameColumn"/>
    <field name="lastNameColumn"/>
    <segment name="errorColumns" collection="list" minOccurs="0" maxOccurs="unbounded" 
             class="com.ErrorColumns">
      <field name="originOfErrorColumn"/>
      <field name="fldNameColumn"/>
    </segment>
    <field name="titleColumn"/>
    <field name="fillerColumn"/>
  </record>
  <record name="a" minOccurs="0" maxOccurs="unbounded" 
          class="com.Employee">
    <field name="record" length="1"/>
    <field name="firstName" maxLength="5"/>
    <field name="lastName" maxLength="5"/>
    <segment name="error" collection="list" minOccurs="0" maxOccurs="unbounded" 
             class="com.Error">
      <field name="origin_of_error" maxLength="2"/>
      <field name="fld_name" maxLength="2"/>
    </segment>
    <field name="title" maxLength="5"/>
    <field name="filler" maxLength="5"/>
  </record>
</stream>

现在我们需要确保errorColumns 列表填充的对象数量与我们为第一条Employee 记录读取的对象数量相同。

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");

    BeanReader br = factory.createReader("EmployeeInfo",new File("C:\\Temp\\Soc\\textInput.txt"));
    BeanWriter out = factory.createWriter("EmployeeInfoCSV", new File("C:\\Temp\\Soc\\output.csv"));

    boolean columnHeadersWritten = false;
    Object record;
    while ((record=br.read())!=null) {

      if (!columnHeadersWritten) {
        final Employee employee = (Employee) record;
        final HeaderColumns headerColumns = new HeaderColumns();
        for (int i = 0; i < employee.getErrorCount(); i++) {
          headerColumns.addErrorColumns(new ErrorColumns());
        }
        out.write(headerColumns);
        columnHeadersWritten = true;
      }

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

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

现在我们有了基于从第一条员工记录中读取的实际错误数量的动态列标题。

【讨论】:

  • 我可以做到,但如果发生的最大值是我要做的 100 倍,那只是问题
  • 更新了我的答案,让它变得更加“动态”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 2017-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多