使用扫描仪读取CSV()

cof*_*tor 45 java csv java.util.scanner

我的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
Run Code Online (Sandbox Code Playgroud)

运行我的应用程序后,任何带有空格(地址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();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我使用Scanner不正确吗?

Sch*_*tod 146

请停止编写有故障的CSV解析器!

我已经在网上看到了数百个CSV解析器和所谓的教程.

几乎每一个人都错了!

这不会是一件坏事,因为它不会影响我,但是那些试图编写CSV 阅读器并弄错的人往往也会编写CSV 编写器.也让他们错了.而这些我必须编写解析器.

请记住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. 甚至可以在未引用的值中包含引用的字符; 这一个没有逃脱

如果您认为这显然不是问题,那么请再想一想.我已经看到这些项目中的每一项都被错误地实施了.甚至在主要的软件包中.(例如Office-Suites,CRM Systems)

有好的和正确工作的开箱即用的CSV读者和作者:

如果你坚持自己编写,至少要阅读(非常简短的)RFC for CSV.

  • 在许多情况下,如果我们谈论的是 CSV 文件,我们可能会争论。 (2认同)

Pan*_*kaj 42

scanner.useDelimiter(",");
Run Code Online (Sandbox Code Playgroud)

这应该工作.

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

}
Run Code Online (Sandbox Code Playgroud)

对于CSV文件:

a,b,c d,e
1,2,3 4,5
X,Y,Z A,B
Run Code Online (Sandbox Code Playgroud)

输出是:

a|b|c d|e
1|2|3 4|5
X|Y|Z A|B|
Run Code Online (Sandbox Code Playgroud)

  • 我是否认为它没有划定换行符?即它将"e \n1"和"5 \nX"作为单个标记读取?据推测,需要更复杂的正则表达式来划分逗号和换行符.(当然,即使这样,它仍然无法将引用的字符串保持在一起,因此通常不适合CSV.) (17认同)
  • 我们可以使用Scanner.hasNextLine()和nextLine()方法获取单行数据,然后使用上面的程序处理它. (4认同)
  • 如果分隔符(,)是值的一部分,则此解决方案将不起作用.这个答案是对的. (4认同)
  • 这会很好地工作,直到你得到一个诸如““逗号也可以进入值!”之类的值。 (2认同)

hmj*_*mjd 9

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如前所述,建议使用CSV库.首先,这个(和useDelimiter(",")解决方案)将无法正确处理包含,字符的带引号的标识符.