Java中的CSV解析 - 工作示例..?[已关闭]

2022-09-02 11:37:01

我想为学校的java项目编写一个程序来解析一些我不知道的CSV。我知道每列的数据类型 - 尽管我不知道分隔符。

我甚至不知道如何解决的问题是解析日期甚至日期时间列。它们可以采用多种格式之一。

我找到了很多图书馆,但不知道哪个最适合我的需求:http://opencsv.sourceforge.net/ http://www.csvreader.com/java_csv.php http://supercsv.sourceforge.net/ http://flatpack.sourceforge.net/

问题是我是一个完全的java初学者。我担心没有这些库可以做我需要的事情,或者我无法说服他们这样做。

我敢打赌,这里有很多人都有代码示例,可以让我立即开始我需要的东西:

  • 在列中自动拆分(分隔符未知,列类型已知)
  • 转换为列类型(应处理 $、% 等)
  • 将日期转换为 Java 日期或日历对象

通过电子邮件获取尽可能多的代码示例会很好。

多谢!如


答案 1

你还有Apache Commons CSV库,也许它可以做你需要的。请参阅指南。2014-11 年更新至 1.1 版。

另外,对于万无一失的版本,我认为您需要自己编写代码...通过SimpleDateFormat,您可以选择格式,并指定各种类型,如果与任何预先考虑的类型不同,则它不是日期。Date


答案 2

使用时存在严重问题

String[] strArr=line.split(",");

为了解析CSV文件,这是因为数据值中可能存在逗号,在这种情况下,您必须引用它们,并忽略引号之间的逗号。

有一种非常非常简单的方法来解析它:

/**
* returns a row of values as a list
* returns null if you are past the end of the input stream
*/
public static List<String> parseLine(Reader r) throws Exception {
    int ch = r.read();
    while (ch == '\r') {
        //ignore linefeed chars wherever, particularly just before end of file
        ch = r.read();
    }
    if (ch<0) {
        return null;
    }
    Vector<String> store = new Vector<String>();
    StringBuffer curVal = new StringBuffer();
    boolean inquotes = false;
    boolean started = false;
    while (ch>=0) {
        if (inquotes) {
            started=true;
            if (ch == '\"') {
                inquotes = false;
            }
            else {
                curVal.append((char)ch);
            }
        }
        else {
            if (ch == '\"') {
                inquotes = true;
                if (started) {
                    // if this is the second quote in a value, add a quote
                    // this is for the double quote in the middle of a value
                    curVal.append('\"');
                }
            }
            else if (ch == ',') {
                store.add(curVal.toString());
                curVal = new StringBuffer();
                started = false;
            }
            else if (ch == '\r') {
                //ignore LF characters
            }
            else if (ch == '\n') {
                //end of a line, break out
                break;
            }
            else {
                curVal.append((char)ch);
            }
        }
        ch = r.read();
    }
    store.add(curVal.toString());
    return store;
}

这种方法有很多优点。请注意,每个字符只接触一次。没有提前读取,在缓冲区中推回等。无需在行尾搜索,然后在解析之前复制该行。此解析器完全从流中工作,并创建每个字符串值一次。它适用于标题行和数据行,您只需处理适合该行的返回列表即可。您为它提供了一个读取器,因此基础流已使用您选择的任何编码转换为字符。流可以来自任何来源:文件,HTTP帖子,HTTP获取,您可以直接解析流。这是一个静态方法,因此没有要创建和配置的对象,并且当它返回时,没有保留内存。

您可以在我关于以下主题的博客文章中找到有关此代码的完整讨论,以及为什么首选此方法:CSV文件所需的唯一类