Чтение CSV со сканером()
Мой csv читается в System.out, но я заметил, что любой текст с пробелом перемещается в следующую строку (как return\n)
Вот как начинается мой csv:
first,last,email,address 1, address 2
john,smith,[email protected],123 St. Street,
Jane,Smith,[email protected],4455 Roger Cir,apt 2
После запуска моего приложения любая ячейка с пробелом (адрес 1), попадает в следующую строку.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class main {
public static void main(String[] args) {
// -define .csv file in app
String fileNameDefined = "uploadedcsv/employees.csv";
// -File class needed to turn stringName to actual file
File file = new File(fileNameDefined);
try{
// -read from filePooped with Scanner class
Scanner inputStream = new Scanner(file);
// hashNext() loops line-by-line
while(inputStream.hasNext()){
//read single line, put in string
String data = inputStream.next();
System.out.println(data + "***");
}
// after loop, close scanner
inputStream.close();
}catch (FileNotFoundException e){
e.printStackTrace();
}
}
}
Итак, вот результат в консоли:
first,last,email,address
1,address
2
john,smith,[email protected],123
St.
Street,
Jane,Smith,[email protected],4455
Roger
Cir,apt
2
Я неправильно использую сканер?
Ответы
Ответ 1
scanner.useDelimiter(",");
Это должно работать.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class TestScanner {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("/Users/pankaj/abc.csv"));
scanner.useDelimiter(",");
while(scanner.hasNext()){
System.out.print(scanner.next()+"|");
}
scanner.close();
}
}
Для файла CSV:
a,b,c d,e
1,2,3 4,5
X,Y,Z A,B
Выход:
a|b|c d|e
1|2|3 4|5
X|Y|Z A|B|
Ответ 2
Пожалуйста, прекратите писать ошибочные парсеров CSV!
Я видел сотни парсеров CSV и так называемые обучающие программы для них в Интернете.
Почти каждый из них ошибается!
Это было бы не так уж плохо, поскольку это не повлияло на меня, но люди, которые пытаются писать читатели CSV и ошибаются, склонны писать записи CSV. И ошибайтесь. И этим я должен написать парсеров для.
Пожалуйста, имейте в виду, что CSV (в порядке увеличения не столь очевидности):
- может содержать символы вокруг значений
- могут иметь другие цитирующие символы, чем
- могут даже иметь другие символы цитирования, чем "и"
- может вообще не содержать кавычек
- может даже указывать символы на некоторые значения, а другие - на других
- могут иметь другие разделители, чем, и;
- может иметь пробелы между разделителями и (кавычками) значениями
- может иметь другие кодировки, чем ascii
- должно иметь одинаковое количество значений в каждой строке, но не всегда
- может содержать пустые поля, либо процитированные:
"foo","","bar"
, либо нет: "foo",,"bar"
- может содержать символы новой строки в значениях
- не может содержать символы новой строки в значениях, если они не ограничены
- не может содержать символы новой строки между значениями
- может иметь разделительный символ внутри значения, если он экранирован надлежащим образом
- не использует обратную косую черту для исключения разделителей, но...
- использует сам символ цитирования, чтобы избежать его, например.
Frodo Ring
будет 'Frodo' Ring'
- может иметь символ цитирования в начале или конце значения или даже как только символ (
"foo""", """bar", """"
)
- может даже иметь цитируемый символ в пределах не котируемого значения; это не ускользнуло
Если вы считаете, что это явно не проблема, подумайте еще раз. Я видел, как каждый из этих элементов реализован неправильно. Даже в основных пакетах программного обеспечения. (например, Office-Suites, CRM Systems)
Есть хорошие и правильно работающие готовые читатели и писатели CSV:
Если вы настаиваете на написании своего, по крайней мере, прочитайте (очень короткий) RFC для CSV.
Ответ 3
Scanner.next()
не читает новую строку, но читает следующий токен, помеченный пробелом (по умолчанию, если useDelimiter()
не использовался для изменения шаблона разделителя). Для чтения строки используйте Scanner.nextLine()
.
Как только вы прочтете одну строку, вы можете использовать String.split(",")
для разделения строки на поля. Это позволяет идентифицировать строки, которые не состоят из необходимого количества полей. Использование useDelimiter(",");
игнорирует линейную структуру файла (каждая строка состоит из списка полей, разделенных запятой). Например:
while (inputStream.hasNextLine())
{
String line = inputStream.nextLine();
String[] fields = line.split(",");
if (fields.length >= 4) // At least one address specified.
{
for (String field: fields) System.out.print(field + "|");
System.out.println();
}
else
{
System.err.println("Invalid record: " + line);
}
}
Как уже упоминалось, рекомендуется использовать библиотеку CSV. Во-первых, это (и useDelimiter(",")
решение) неправильно обрабатывает цитируемые идентификаторы, содержащие символы ,
.
Ответ 4
Если вы абсолютно должны использовать Scanner, вы должны установить его разделитель с помощью метода useDelimiter(...)
. Иначе он по умолчанию будет использовать все пробелы в качестве разделителя. Лучше, хотя, как уже было сказано, используйте библиотеку CSV, так как это то, что они делают лучше всего.
Например, этот разделитель будет разделен запятыми с окружающим пробелом или без него:
scanner.useDelimiter("\\s*,\\s*");
Подробнее об этом можно узнать в java.util.Scanner API.
Ответ 5
package take;
public class DateUtil {
// List of all date formats that we want to parse.
// Add your own format here.
private static List<SimpleDateFormat>
dateFormats = new ArrayList<SimpleDateFormat>() {
private static final long serialVersionUID = 1L;
{
add(new SimpleDateFormat("M/dd/yyyy"));
add(new SimpleDateFormat("dd.M.yyyy"));
add(new SimpleDateFormat("M/dd/yyyy hh:mm:ss a"));
add(new SimpleDateFormat("dd.M.yyyy hh:mm:ss a"));
add(new SimpleDateFormat("dd.MMM.yyyy"));
add(new SimpleDateFormat("dd-MMM-yyyy"));
}
};
/**
* Convert String with various formats into java.util.Date
*
* @param input
* Date as a string
* @return java.util.Date object if input string is parsed
* successfully else returns null
*/
public static Date convertToDate(String input) {
Date date = null;
if(null == input) {
return null;
}
for (SimpleDateFormat format : dateFormats) {
try {
format.setLenient(false);
date = format.parse(input);
} catch (ParseException e) {
//Shhh.. try other formats
}
if (date != null) {
break;
}
}
return date;
}
}
Ответ 6
Ну, я делаю свое кодирование в NetBeans 8.1:
Сначала: создайте новый проект, выберите приложение Java и назовите свой проект.
Затем измените свой код после открытого класса, чтобы выглядеть следующим образом:
/**
* @param args the command line arguments
* @throws java.io.FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
try (Scanner scanner = new Scanner(new File("C:\\Users\\YourName\\Folder\\file.csv"))) {
scanner.useDelimiter(",");
while(scanner.hasNext()){
System.out.print(scanner.next()+"|");
}}
}
}