Разбор плоского файла: когда некоторые поля содержат разделитель - PullRequest
0 голосов
/ 07 июня 2019

У меня есть приложение Spring-Batch, которое читает файл с этим считывателем:

<bean id="tradeItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
    <property name="resource">
        <bean class="org.springframework.core.io.FileSystemResource">
            <constructor-arg value="${input.file.path}/#{jobExecutionContext['trades']}" type="java.lang.String"/>
        </bean>
    </property>
    <property name="linesToSkip" value="1" />
    <property name="lineMapper">
        <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
            <!-- split it -->
            <property name="lineTokenizer">
                <bean
                    class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                    <beans:property name="strict" value="false" />
                    <beans:property name="includedFields" value="0,2,3,6" />
                    <property name="names"
                        value="field0,field2,field3,field6" />
                </bean>
            </property>
            <property name="fieldSetMapper">
                <bean
                    class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
                    <property name="prototypeBeanName" value="trade" />
                </bean>
            </property>
        </bean>
    </property>
</bean>

Поля разделены запятой ,, и вот подвох: некоторые поля выглядят как [LON, TGT] и строка заканчивается ошибочным анализом из-за запятой в квадратных скобках.

Пример:

Ввод: Global,,VERIFIED,[LON, TGT],ERerd,3456585,QTR,20190929,20231020

Желаемый вывод: Global,VERIFIED, [LON, TGT], QTR

Фактический результат: Global, VERIFIED, [LON, 3456585

Как мне этого добиться?У меня нет контроля над входным файлом.

РЕДАКТИРОВАТЬ

Это не дубликат, так как предлагаемое решение не будет работать:здесь у нас нет ни одного символа кавычки, но у нас есть 2 разных символа: открывающая и закрывающая.

1 Ответ

0 голосов
/ 13 июня 2019

Как объяснил Лука Бассо Риччи, мой ввод csv недействителен, но мне все еще приходится иметь дело с ним, потому что я не могу его контролировать.

Поэтому я написал свой собственный токенизатор строки с разделителями, который простоDelimitedLineTokenizer с переписанным методом isDelimiter(), и заменил его в файле conf:

  private boolean isDelimiter(char[] chars, int i, String token, int endIndexLastDelimiter) {
    boolean result = false;

    int openingBrackets = StringUtils.countOccurrencesOf(new String(Arrays.copyOfRange(chars, 0, i)),  "[");
    int closingBrackets = StringUtils.countOccurrencesOf(new String(Arrays.copyOfRange(chars, 0, i)),  "]");

    boolean inBrackets = (openingBrackets - closingBrackets > 0);

    if ((i - endIndexLastDelimiter >= this.delimiter.length()) && 
      (i >= token.length() - 1)) {
      String end = new String(chars, i - token.length() + 1, token.length());
      if (token.equals(end)) {
        if (inBrackets) {
          result = false;
        } else {
          result = true;
        }
      }
    }
    return result;
  }
...