Иногда мне нужно объединить несколько строк данных в одну строку, и в этом случае, в частности, в виде значений через запятую в одной строке:
Регулярное выражение может не быть лучшее решение для этого.
Библиотека CSV
Существует несколько библиотек с разделителями-запятыми (CSV) , доступных для быстрой работы.
Библиотеки решат конкретную проблему, которую вы можете не заметить при написании собственного кода: некоторые из ваших строк ввода имеют знак , заключенный в одинарные кавычки, в своем содержимом . Такие случаи нужно избегать. Цитирование RF C 4180 раздел 2.7:
Если двойные кавычки используются для включения полей, то двойная кавычка, появляющаяся внутри поля, должна быть экранирована, если перед ней стоит еще одна двойная цитата. Например:
"aaa","b""bb","ccc"
Вот пример использования библиотеки Apache Commons CSV .
Мы используем лямбда-синтаксис с Scanner
, чтобы получить Iterable
строк текста из вашего ввода.
Мы указываем использование одиночной кавычки, как вам нужно, а не значение по умолчанию двойной цитата в стандартном CSV.
Мы используем синтаксис try-with-resources для автоматического закрытия объекта CSVPrinter
, независимо от того, выполняется наш код успешно или выдает исключение.
String input = "Rush\n" +
"IQ\n" +
"Saga\n" +
"Yes";
Iterable < String > iterable = ( ) -> new Scanner( input ).useDelimiter( "\n" ); // Lambda syntax to get a `Iterable` of lines from a `String`.
CSVFormat format =
CSVFormat
.RFC4180
.withQuoteMode( QuoteMode.ALL )
.withQuote( '\'' );
StringBuilder stringBuilder = new StringBuilder();
try (
CSVPrinter printer = new CSVPrinter( stringBuilder , format ) ;
)
{
printer.printRecord( iterable );
}
catch ( IOException e )
{
e.printStackTrace();
}
String output = stringBuilder.toString();
System.out.println( "output: " + output );
При запуске:
вывод: 'Ru sh', 'IQ', 'Saga', 'Yes'
Мы можем сократить этот код.
try (
CSVPrinter printer = new CSVPrinter( new StringBuilder() , CSVFormat.RFC4180.withQuoteMode( QuoteMode.ALL ).withQuote( '\'' ) ) ;
)
{
printer.printRecord( ( Iterable < String > ) ( ) -> new Scanner( input ).useDelimiter( "\n" ) );
System.out.println( printer.getOut().toString() ); // Or: `return printer.getOut()` returning an `Appendable` object.
}
catch ( IOException e )
{
e.printStackTrace();
}
Не то чтобы это было особенно укорочено. Лично я бы использовал более длинную версию, заключенную в метод в служебном классе. Вот так:
public String enquoteLines( String input ) {
String output = "";
Iterable < String > iterable = ( ) -> new Scanner( input ).useDelimiter( "\n" ); // Lambda syntax to get a `Iterable` of lines from a `String`.
CSVFormat format =
CSVFormat
.RFC4180
.withQuoteMode( QuoteMode.ALL )
.withQuote( '\'' );
StringBuilder stringBuilder = new StringBuilder();
try (
CSVPrinter printer = new CSVPrinter( stringBuilder , format ) ;
)
{
printer.printRecord( iterable );
output = printer.getOut().toString();
}
catch ( IOException e )
{
e.printStackTrace();
}
return output;
}
Называя его:
String input = "Rush\n" +
"IQ\n" +
"Saga\n" +
"Oui";
String output = this.enquoteLines( input );