忽略在Java中读取CSV文件的空值

时间:2018-12-01 09:56:49

标签: java file filereader

我能够读取我的数据集(csv文件),但是当我运行主类时,它将显示所有行,包括具有空值的行。有什么办法可以忽略数据集中缺少值(即空值)的每一行? 我本来想在方法testNullValue()中进行检查,但我真的不知道要检查什么。

我的班级

public static BufferedReader exTractTraningData(File datafile, String ListOfCharacteristics) throws IOException {

    try {
        //create BufferedReader to read csv file
        BufferedReader reader = new BufferedReader(new FileReader(datafile));

        String strLine = "";
        StringTokenizer st = null;

        int lineNumber = 0, tokenNumber = 0;;


        while ((strLine = reader.readLine()) != null) {
            lineNumber++;
            //break comma separated line using ","
            st = new StringTokenizer(strLine, ",");

            while (st.hasMoreTokens()) {
                //display csv values
                tokenNumber++;
                System.out.println("Line # " + lineNumber
                        + ", Token : " + st.nextToken(",") );
            }
            //reset token number
            tokenNumber = 0;;
        }
    } catch (Exception e) {

        System.out.println("Exception while reading csv file: " + e);
    }
    return null;
}

public boolean testNullValue(String ListOfCharacteristics, String ListOfValues){
    return false;


}

最后,我不知道为什么控制台中的结果没有显示例如“ name”,“ 2”,“ TV”,“ As”,“ 40”,“ 10”之类的每一行在此处指定它为st = new StringTokenizer(strLine,“,”);

enter image description here

1 个答案:

答案 0 :(得分:1)

StringTokenizer会在遇到空值时忽略空值,并且除了让令牌化程序还提供定界符作为令牌并且当有两个定界符令牌时,实际上没有办法知道它们实际上存在于CSV分隔的字符串行中。另一个之后,显然会遇到一个空值:

st = new StringTokenizer(strLine, ",", true); 

这是在CSV文件数据行中检测空值的真正的 booger 方法,因为现在您必须提供代码来计数两个定界符一个接一个地落下,然后完全忽略定界符。这很可能是为什么没有太多人使用 StringTokenizer 来解析CSV文件并偏爱使用String#split()方法之类的东西或更好地使用{{{ 3}}。当然,这取决于实际需要执行的操作以及操作的范围。

实际上不鼓励在新代码中使用旧的 StringTokenizer 类,因为其方法不能区分标识符,数字和带引号的字符串。类方法甚至无法识别和跳过注释。

无论如何,如果您要检查任何CSV行中的任何空值,则无需重新读取文件。可以在您当前正在执行的同一遍读取中完成。这个概念非常简单,利用一种编码机制将CSV文件数据行中的所有读取内容分割成令牌,这些令牌还维护任何给定行中可能包含的空值,然后进行比较令牌计数与使用 StringTokenizer 计数解析的数据文件行完全相同。可以在对CSV数据行进行标记后直接执行此类操作,例如:

while ((strLine = reader.readLine()) != null) {
    // You might want to count lines only if they are valid!
    // If so then move this line below the IF statement code 
    // block.
    lineNumber++;    
    //break comma separated line using ","
    st = new StringTokenizer(strLine, ",");

    // Is this a blank line OR Is there possibly a null token
    // in the data line detected by the String#split() method?
    if (st.countTokens() == 0 || (st.countTokens() != strLine.split(",").length)) {
        System.out.println("The data line is blank OR there is a null value "
                         + "in the data line!");
        // Skip this data line from further processing 
        // within the WHILE loop.
        continue;    
    }

    while (st.hasMoreTokens()) {
        //display csv values
        tokenNumber++;
        System.out.println("Line # " + lineNumber
                    + ", Token : " + st.nextToken(",") );
    }
    //reset token number
    tokenNumber = 0;
}

我个人将只使用 String#split()方法,而不必完全使用 StringTokenizer 类,例如:

while ((strLine = reader.readLine()) != null) {
    // You might want to count lines only if they are valid!
    // If so then move this line below the IF statement code 
    // block.
    lineNumber++;    
    // Split comma separated line using ","
    String[] st = strLine.split(",");
    if (st.length == 0 || Arrays.asList(st).contains("")) {
        System.out.println("The data line (" + lineNumber + ") is blank OR "
                         + "there is a null value in the data line!");
        // Skip this data line from further processing 
        // within the WHILE loop.
        continue;
    }

    StringBuilder sb = new StringBuilder();
    sb.append("Line# ").append(lineNumber).append(": ");
    for (int i = 0; i < st.length; i++) {
        sb.append("Token : ").append(st[i]).
                // Ternary Operator used here to add commas
                append(i < (st.length-1) ? ", " : "");
    }
    System.out.println(sb.toString());      
}

当然,所有这些都假定CSV文件数据是用逗号分隔的,在任何分隔符之前或之后都没有空格。当人们发布有关数据文件处理的问题,并且没有提供示例而不是如何在该文件中格式化数据时,就会出现此问题。现在,这当然使我想到了第二个问题,即为什么事情没有按照您的意图显示:

  

最后,我不知道为什么控制台中的结果没有显示   每行这样的“名称”,“ 2”,“电视”,“作为”,“ 40”,“ 10”

谁不知道示例如何在文件中呈现数据以及确切地如何在屏幕上呈现数据。这个例子应该是什么样的,我个人并不理解。此外,不是"name", "gender", "2 " ... ?,我们当然可以猜测,我的猜测是,您在 StringTokenizer 方法中使用的分隔符是错误的,当然,以上所有示例均基于您在自己的代码中提供的定界符。