【问题标题】:Parsing a csv file to populate database解析 csv 文件以填充数据库
【发布时间】:2016-08-23 13:50:15
【问题描述】:

鉴于我有一个这样的 csv 文件

str_name,int_points,int_bonus
joe,2,5
Moe,10,15
Carlos,25,60

我可以拥有 x 列和 y 行数的 csv 文件,因此我正在尝试开发一种通用方法来解析它并将数据填充到 dynamodb 表中。

为了填充 dynamodb 表,我会做这样的事情

String line = "";
    String cvsSplitBy = ",";

    try (BufferedReader br = new BufferedReader(
                                new InputStreamReader(objectData, "UTF-8"));

        while ((line = br.readLine()) != null) {

            // use comma as separator
            String[] elements = line.split(cvsSplitBy);

            try {
                table.putItem(new Item()
                    .withPrimaryKey("name", elements[0])
                    .withInt("points", elements[1])
                    .withInt("bonus", elements[2])
                    .....);

                System.out.println("PutItem succeeded: " + elements[0]);

            } catch (Exception e) {
                System.err.println("Unable to add user: " + elements);
                System.err.println(e.getMessage());
                break;
            }

        }

    } catch (IOException e) {
        e.printStackTrace();
    }

但是我并不总是知道我是插入一个 int 还是一个字符串,它依赖于 csv 文件,所以我有点迷失如何创建一个通用函数来读取我的 csv 文件的第一行并获取前缀的优点,它指示特定列是 int 还是 string。

【问题讨论】:

  • 您不能指定 CSV 文件的格式吗?
  • 我会使用类似于 opencsv 的 API。当您解析 CSV 文件时,您将获得 String[] 的 String[],这将在这种情况下帮助您。
  • @dsp_user 我的 csv 文件将与我在上面发布的示例完全相同..除了它会有更多的列和行..
  • 解析 csv 文件时,文件中的每一行都会有一个 String[]。如果您知道 int 和 strings 的位置,将这些值保存到 DB 应该很简单。我在这里错过了什么吗?
  • @dsp_user 我了解,但是如果您查看我的 table.putItem ,我将如何将其用于插入数据的方法,以及随后的所有内容都必须根据列数和类型进行更改是。如果你能举例说明你将如何做到这一点,我会很高兴的,也许我错过了一些东西。

标签: java amazon-web-services amazon-dynamodb aws-lambda


【解决方案1】:

只需存储标签(第一行),然后在迭代行值时,根据标签决定调用什么方法。如果您不反对引入一些外部依赖项,我建议您使用一些外部 csv 阅读器,例如 SuperCsv 使用这个库,您可以例如将每一行读取为 Map(label->val) 然后迭代条目并根据标签前缀使用正确的方法更新您的数据库。或者只是读取标题,然后将每一行作为列表读取。

例子:

这当然非常粗糙,我可能会以某种方式对其进行重构(例如,为每列提供一个处理器列表,而不是丑陋的开关) 但它向你展示了这个想法

        List<String> labels = new ArrayList<>();//store first row here
        List<String> elements = new ArrayList<>();//currently processed line here
        Item item = new Item();
        for (int i = 0; i < elements.size(); i++) {
            String label = labels.get(i);
            switch (getTypePrefix(label)){
                case "int":
                    item = item.withInt(getName(label),elements.get(i));
                    break;
                case "str":
                    item = item.withString(getName(label),elements.get(i));
                    break;
                default:
                    //sth
                    break;
            }
        }
        table.putItem(item);

【讨论】:

  • 问题不在于读取行,而在于读取行和列后如何插入数据.. 一个例子将不胜感激。
  • 添加了简单的例子
【解决方案2】:

好的,我不能将此作为评论发布,所以我写了一个简单的示例。请注意,我不熟悉您正在使用的 Amazon API,但您应该知道我将如何处理它(我基本上重写了您的代码)

        String line = "";
        String cvsSplitBy = ",";

        try (BufferedReader br = new BufferedReader(
                            new InputStreamReader(objectData, "UTF-8"));

     String[]  colNames = br.readLine().split(cvsSplitBy);      //first line just to get the column names
     while ((line = br.readLine()) != null) {
        String currColumnName = colNames.get(i);
        // use comma as separator
        String[] elements = line.split(cvsSplitBy);
        boolean isInt ;
        for (int i = 0; i < elements.length;i++){

        try {
            try{
            int iVal = new Integer(elements[i]);
            isInt = true;
            }catch(NumberFormatException e){
            //process exception
            isInt = false;
            }
            if(isInt){
            table.putItem.(new Item().withInt(currColumnName,iVal));
            }else{
            table.putItem.(new Item().withString(currColumnName),elements[i])); //don't even know whether there is a withString method
            }

            System.out.println("PutItem succeeded: " + elements[i]);

        } catch (Exception e) {
            System.err.println("Unable to add user: " + elements);
            System.err.println(e.getMessage());
            break;
        }
        }

    }

} catch (IOException e) {
    e.printStackTrace();
}

此示例假定您的第一行包含存储在数据库中的列名。无论是 int 还是 String,你都不必在任何地方写,因为程序中有一个检查(当然这不是最有效的方法,你可能会写得更好,也许是 Molok 建议的)

【讨论】:

    猜你喜欢
    • 2011-02-22
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    相关资源
    最近更新 更多