如果包含多个例外分隔符,如何从CSV读取数据?

时间:2013-10-17 09:24:08

标签: java csv

我使用CsvJDBC来读取CSV中的数据。我从Web服务请求中获取CSV,因此不从文件加载。我调整了这些属性:

Properties props = new java.util.Properties();
props.put("separator", ";"); // separator is a semicolon
props.put("fileExtension", ".txt"); // file extension is .txt
props.put("charset", "UTF-8"); // UTF-8

我的sample1.txt包含以下数据:

code;description
c01;d01
c02;d02

我的sample2.txt包含以下数据:

code;description
c01;d01
c02;d0;;;;;2

我可以选择从CSV中删除标题。但对我来说不是可选的改变分号分隔符。

编辑:我对resultSet的查询:SELECT * FROM myCSV

我想阅读sample1.txt和sample2.txt中的code列:

resultSet.getString(1)

并阅读包含许多分号(description)的完整d0;;;;;2列。是否可以使用CsvJdbc驱动程序或需要更改驱动程序?

谢谢你的任何建议!

5 个答案:

答案 0 :(得分:3)

这是一个问题,当你有一个混乱的,无效的输入时,你需要尝试解释,这是由一个只处理干净输入的太高级别的包读取的。一个类似的例子是尝试使用XML解析器读取任意HTML - 关闭,但没有雪茄。

你可以猜到我要去的地方:你需要预先处理你的输入。

如果您可以对数据做出一些假设,那么预处理可能非常简单 - 例如,如果第一列中确保没有引用的分号。

答案 1 :(得分:3)

你可以试试supercsv。我们在项目中实施了这样的解决方案。有关详细信息,请参阅http://supercsv.sourceforge.net/Using CsvBeanReader to read a CSV file with a variable number of columns

答案 2 :(得分:3)

最后,在没有CSVJdbc或SuperCSV驱动程序的情况下解决了这个问题。这些驱动程序正常。 CSV文件和许多功能内容都有可能的查询数据。就我而言,我不需要CSV中的查询数据。不幸的是,有时描述栏内容是一个或多个分号,而它是我的分隔符。

首先,我检查@Maher Abuthraa的答案中的代码并修改为:

private String createDescriptionFromResult(ResultSet resultSet, int columnCount) throws SQLException {

        if (columnCount > 2) {
            StringBuilder data_list = new StringBuilder();

            for (int ii = 2; ii <= columnCount; ii++) {
                data_list.append(resultSet.getString(ii));
                if (ii != columnCount)
                    data_list.append(";");
            }
            // data_list has all data from all index you are looking for ..
            return data_list.toString();
        } else {
            // use standard way
            return resultSet.getString(2);
        }
    } 

循环从2开始,因为1列是代码,只有描述列内容很多分号。 CSVJdbc驱动程序按分隔符;拆分列,这些分号从列数据中消失。所以,除了最后一列,我明确地将半冒号添加到描述中,因为它与我的情况无关。

此代码工作正常。但没有解决我的所有问题。当我在CSV的标题中调整两列时,我得到行中的错误,其中包含两个以上的分号。因此,我尝试调整忽略标头或向标头添加许多列名称(或简单;)。在superCSV中忽略headers选项工作正常。

我的同事意见是:你不需要CSV驱动程序,因为如果分隔符有时是相关数据,请尝试加载不是CSV的CSV。

我认为我的同事是对的,我按照以下代码加载了CSV数据:

InputStream in = null;
try {
        in = new ByteArrayInputStream(csvData);

        List lines = IOUtils.readLines(in, "UTF-8");
        Iterator it = lines.iterator();
        String line = "";
        while (it.hasNext()) {
        line = (String) it.next();

        String description = null;
        String code = null;
        String[] columns = line.split(";");

        if (columns.length >= 2) {
            code = columns[0];
            String[] dest = new String[columns.length - 1];
            System.arraycopy(columns, 1, dest, 0, columns.length - 1);
            description = org.apache.commons.lang.StringUtils.join(dest, ";");
          (...) 

答案 3 :(得分:2)

好的..我的解决方案去读取所有字段,如果列数超过2 ...像:

int ccc = meta.getColumnCount();
    if (ccc > 2) {
        ArrayList<String> data_list = new ArrayList<String>();
        for (int ii = 1; ii < ccc; ii++) {
            data_list.add(resultSet.getString(i));
        }
        //data_list has all data from all index you are looking for ..
    } else {
        //use standard way 
        resultSet.getString(1);
    }

答案 4 :(得分:1)

如果表被定义为具有与源中的分号一样多的列,忽略初始列定义,那么数据库驱动程序将自动使用多余的分号。

它们出现在最后一列的最可能原因是因为解析器将行的余额返回到字段中的终止符。

只需增加表中的列数以匹配输入中的最大值,就可以避免在程序中进行自定义解析。尝试:

code;description;dummy1;dummy2;dummy3;dummy4;dummy5
c01;d01
c02;d0;;;;;2

然后,附加';'解析器将正确使用分隔符。