проблема с точкой с запятой в Java csv

#java #regex #csv #separator

#java #регулярное выражение #csv #разделитель

Вопрос:

Я должен изменить программу. Эта программа создает файл csv со столбцами в базе данных, подобными этому :

     csvBuilder.initCsvFile();
    csvBuilder.createRow(headers.toArray(new String[headers.size()]));
while (resultSet.next()) {
        String[] row = new String[resultSetColumnCount];
        int columnIndex = 1;
        while (columnIndex <= resultSetColumnCount) {
            Object object = resultSet.getObject(columnIndex);
            if (object == null) {
                row[columnIndex - 1] = "";
            } else {
                row[columnIndex - 1] = object.toString();
            }
            columnIndex  ;
        }
        csvBuilder.createRow(row);
    }
  

Метод initCsvFile:

 public void initCsvFile() {
    try {
        writer = new CSVWriter(new FileWriter(filePath), ';', CSVWriter.NO_QUOTE_CHARACTER);
    } catch (IOException e) {
        logger.error("CsvBuilder : error when creating {}", filePath, e);
        throw new CsvException("Error when creating the file : "   filePath, e);
    }
}
  

Метод createRow:

 public void createRow(String[] row) {
    writer.writeNext(row);
}
  

Проблема в том, что у меня есть некоторые данные, которые включают разделитель ‘;’, как показано ниже,

 id col1     col2   
1   US     United;States
  

К сожалению, файл CSV разделяет Соединенные Штаты на две части . Как я могу проверить содержимое результирующего набора и избежать разделителя без изменения всей программы, чтобы получить Объединенные состояния в одной строке?

Спасибо за вашу помощь

Комментарии:

1. Я бы использовал replace() для замены «;», если потеря его из исходных данных не является проблемой.

Ответ №1:

В этих случаях вам понадобится некоторый символ кавычки, иначе возникнет двусмысленность; в вашем случае вы указываете ему не использовать кавычки, и в результате у него нет способа обработать эти случаи.

Попробуйте явно определить символ кавычки:

 public void initCsvFile() {
    try {
        writer = new CSVWriter(new FileWriter(filePath), ';', '"');
    } catch (IOException e) {
        logger.error("CsvBuilder : error when creating {}", filePath, e);
        throw new CsvException("Error when creating the file : "   filePath, e);
    }
}
  

Имейте в виду, что в этом случае любые данные, которые могут вызвать двусмысленность, будут заключены в кавычки:

 1;US;"United;States"
  

Это допустимый CSV, и большинство анализаторов CSV автоматически удаляют кавычки при чтении.

Комментарии:

1. Это правильно, но я получаю в файле CSV ‘ » ‘, окружающем каждый элемент… Полагаю, у меня нет выбора. спасибо 🙂

Ответ №2:

вы могли бы заменить «;» перед созданием CSV-строк, подобных этой

 while (resultSet.next()) {
        String[] row = new String[resultSetColumnCount];
        int columnIndex = 1;
        while (columnIndex <= resultSetColumnCount) {
            Object object = resultSet.getObject(columnIndex);
            if (object == null) {
                row[columnIndex - 1] = "";
            } else {
                // replace ";" by ""
                row[columnIndex - 1] = object.toString().replace(";", "");
            }
            columnIndex  ;
        }
        csvBuilder.createRow(row);
    }
  

Комментарии:

1. Пока потеря этих точек с запятой не является проблемой, это может быть хорошим решением.

2. К сожалению, я не могу потерять точки с запятой, но все же спасибо

Ответ №3:

Я только что столкнулся с аналогичной проблемой. По-видимому, строка должна быть экранирована двойными кавычками, чтобы предотвратить такие проблемы. Итак, я создал escapeCSVDatum() функцию:

 private static String escapeCSVDatum(String s){
    return """ s.replace(""", """").replace("n", " ") """;
}
  

Итак, в вашем случае это было бы применимо здесь

 } else {
    row[columnIndex - 1] = escapeCSVDatum(object.toString());
}
  

Однако, как указано Haroldo_OK, ваше использование CSVWriter.NO_QUOTE_CHARACTER делает невозможным надлежащее рассмотрение таких случаев. Невозможно иметь точку с запятой в datum с этим атрибутом.

Таким образом, вы можете захотеть изменить свой код, чтобы заменить точки с запятой пробелами, например

 } else {
    row[columnIndex - 1] = object.toString().replace(";"," ");
}
  

Наконец, если вы хотите возиться с людьми, замените точки с запятой греческими вопросительными знаками.

Комментарии:

1. На данный момент я не могу заменить точки с запятой, но спасибо 🙂