使用扫描仪读取CSV()

我的csv正在读入System.out,但我注意到,任何带有空格的文本都会被移到下一行(作为返回\ n)

以下是我的csv开始的方式:

first,last,email,address 1, address 2 john,smith,blah@blah.com,123 St. Street, Jane,Smith,blech@blech.com,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(); } } } 

所以这里是控制台的结果:

第一,最后,电子邮件,地址 
 1,地址 
 2
约翰·史密斯,胡说@ blah.com,123 
圣 
街,
简·史密斯,BLECH @ blech.com,4455 
罗杰 
 CIR,容易 
 2

我是否正确使用扫描仪?

 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,cd,e 1,2,3 4,5 X,Y,ZA,B 

输出是:

 a|b|cd|e 1|2|3 4|5 X|Y|ZA|B| 

请停止编写错误的CSVparsing器!

我已经看到了数以百计的CSVparsing器和所谓的在线教程

几乎每个人都错了!

这不会是一件坏事,因为它不会影响我,但是试图编写CSV 阅读器并且出错的人也倾向于编写CSV 编写器 。 并让他们错了。 而这些我必须写parsing器。

请记住CSV(按照增加的顺序不那么明显):

  1. 可以引用值附近的字符
  2. 可以有其他的引用字符而不是“
  3. 甚至可以有其他引用字符比“和”
  4. 根本没有引号
  5. 甚至可以在某些值上引用字符而在其他值上不引用字符
  6. 可以有其他的分隔符,而且;
  7. 分隔符和(引用)值之间可以有空格
  8. 可以有其他的字符比ASCII
  9. 在每一行中应该具有相同数量的值,但并不总是如此
  10. 可以包含空的字段,或者引用: "foo","","bar"或不是: "foo",,"bar"
  11. 可以在值中包含换行符
  12. 如果它们没有分隔,则不能在值中包含换行符
  13. 值之间不能包含换行符
  14. 如果正确转义,可以在该值内具有分隔符
  15. 不使用反斜线来逃避分隔符,但…
  16. 使用引用字符本身来逃避它,例如Frodo's Ring将是'Frodo''s Ring'
  17. 可以在值的开始或结束处具有引号字符,或者甚至只有字符( "foo""", """bar", """"
  18. 甚至可以在没有引用的价值内具有引用的字符; 这一个没有逃脱

如果你认为这显然不是问题,那么再想一想。 我看到这些项目中的每一个都错误地实施了。 即使在主要的软件包。 (如办公室套件,客户关系pipe理系统)

有好的和正确的工作,现成的CSV阅读器和作家在那里:

  • opencsv
  • Ostermiller Java公用事业

如果你坚持写自己的,至less读CSV (非常短)的RFC 。

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

如前所述,build议使用CSV库。 首先,这个(和useDelimiter(",")解决scheme)将不能正确处理包含字符的带引号的标识符。

如果您绝对必须使用扫描仪,则必须通过其useDelimiter(...)方法设置其分隔符。 否则它将默认使用全部空格作为分隔符。 尽pipe如前所述,使用CSV库是一件好事,因为这是他们最擅长的。

例如,这个分隔符将会在包含或不包含空格的逗号分割:

 scanner.useDelimiter("\\s*,\\s*"); 

请查看java.util.Scanner API了解更多信息。

 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; } } 

那么,我在NetBeans 8.1中编写代码:

首先:创build一个新项目,selectJava应用程序并命名您的项目。

然后在public class之后修改你的代码,如下所示:

 /** * @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()+"|"); }} } }