繁体   English   中英

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

[英]Ignoring null values reading a CSV file in Java

我能够读取我的数据集(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,“,”);

在此处输入图片说明

StringTokenizer会在遇到空值时忽略空值,除了让令牌化程序还提供定界符作为令牌并且当有两个定界符令牌(一个接一个,另一个然后为空)时,遇到真正的CSV分隔字符串行时,它实际上不知道它们是否存在。显然遇到了价值:

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

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

实际上不建议在新代码中使用旧的遗留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”,“ TV”,“作为”,“ 40”,“ 10”

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM