简体   繁体   English

Java:CSV 文件读写

[英]Java: CSV file read & write

I'm reading 2 csv files: store_inventory & new_acquisitions .我正在阅读 2 个 csv 文件: store_inventory & new_acquisitions
I want to be able to compare the store_inventory csv file with new_acquisitions .我希望能够将store_inventory csv 文件与new_acquisitions进行比较。 1) If the item names match just update the quantity in store_inventory. 1) 如果商品名称匹配,只需更新 store_inventory 中的数量。 2) If new_acquisitions has a new item that does not exist in store_inventory , then add it to the store_inventory . 2) 如果 new_acquisitions 有一个在store_inventory中不存在的新物品,那么将它添加到store_inventory

Here is what i have done so far but its not very good.这是我到目前为止所做的但不是很好。 I added comments where i need to add taks 1 & 2 .我在需要添加 taks 12 的地方添加了评论。
Any advice or code to do the above tasks would be great!任何完成上述任务的建议或代码都会很棒! thanks.谢谢。

    File new_acq = new File("/src/test/new_acquisitions.csv");
    Scanner acq_scan = null;
    try {
        acq_scan = new Scanner(new_acq);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(mainpage.class.getName()).log(Level.SEVERE, null, ex);
    }
    String itemName;
    int quantity;
    Double cost;
    Double price;

    File store_inv = new File("/src/test/store_inventory.csv");
    Scanner invscan = null;
    try {
        invscan = new Scanner(store_inv);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(mainpage.class.getName()).log(Level.SEVERE, null, ex);
    }
    String itemNameInv;
    int quantityInv;
    Double costInv;
    Double priceInv;


    while (acq_scan.hasNext()) {
        String line = acq_scan.nextLine();
        if (line.charAt(0) == '#') {
            continue;
        }
        String[] split = line.split(",");

        itemName = split[0];
        quantity = Integer.parseInt(split[1]);
        cost = Double.parseDouble(split[2]);
        price = Double.parseDouble(split[3]);


        while(invscan.hasNext()) {
            String line2 = invscan.nextLine();
            if (line2.charAt(0) == '#') {
                continue;
            }
            String[] split2 = line2.split(",");

            itemNameInv = split2[0];
            quantityInv = Integer.parseInt(split2[1]);
            costInv = Double.parseDouble(split2[2]);
            priceInv = Double.parseDouble(split2[3]);


            if(itemName == itemNameInv) {
                //update quantity

            }
        }
        //add new entry into csv file

     }

Thanks again for any help.再次感谢任何帮助。 =] =]

Suggest you use one of the existing CSV parser such as Commons CSV or Super CSV instead of reinventing the wheel.建议您使用现有的 CSV 解析器之一,例如Commons CSVSuper CSV,而不是重新发明轮子。 Should make your life a lot easier.应该会让你的生活轻松很多。

Your implementation makes the common mistake of breaking the line on commas by using line.split(",") .您的实现犯了使用line.split(",")在逗号上断行的常见错误。 This does not work because the values themselves might have commas in them.这不起作用,因为值本身可能包含逗号。 If that happens, the value must be quoted, and you need to ignore commas within the quotes.如果发生这种情况,则必须引用该值,并且您需要忽略引号内的逗号。 The split method can not do this -- I see this mistake a lot. split方法不能做到这一点——我经常看到这个错误。

Here is the source of an implementation that does it correctly: http://agiletribe.purplehillsbooks.com/2012/11/23/the-only-class-you-need-for-csv-files/这是正确执行的实现的来源: http : //agiletribe.purplehillsbooks.com/2012/11/23/the-only-class-you-need-for-csv-files/

With help of the open source library uniVocity-parsers , you could develop with pretty clean code as following:在开源库uniVocity-parsers 的帮助下,您可以使用非常干净的代码进行开发,如下所示:

private void processInventory() throws IOException {
    /**
     * ---------------------------------------------
     *  Read CSV rows into list of beans you defined
     * ---------------------------------------------
     */
    // 1st, config the CSV reader with row processor attaching the bean definition
    CsvParserSettings settings = new CsvParserSettings();
    settings.getFormat().setLineSeparator("\n");
    BeanListProcessor<Inventory> rowProcessor = new BeanListProcessor<Inventory>(Inventory.class);
    settings.setRowProcessor(rowProcessor);
    settings.setHeaderExtractionEnabled(true);

    // 2nd, parse all rows from the CSV file into the list of beans you defined
    CsvParser parser = new CsvParser(settings);
    parser.parse(new FileReader("/src/test/store_inventory.csv"));
    List<Inventory> storeInvList = rowProcessor.getBeans();
    Iterator<Inventory> storeInvIterator = storeInvList.iterator();

    parser.parse(new FileReader("/src/test/new_acquisitions.csv"));
    List<Inventory> newAcqList = rowProcessor.getBeans();
    Iterator<Inventory> newAcqIterator = newAcqList.iterator();

    // 3rd, process the beans with business logic
    while (newAcqIterator.hasNext()) {

        Inventory newAcq = newAcqIterator.next();
        boolean isItemIncluded = false;
        while (storeInvIterator.hasNext()) {
            Inventory storeInv = storeInvIterator.next();

            // 1) If the item names match just update the quantity in store_inventory
            if (storeInv.getItemName().equalsIgnoreCase(newAcq.getItemName())) {
                storeInv.setQuantity(newAcq.getQuantity());
                isItemIncluded = true;
            }
        }

        // 2) If new_acquisitions has a new item that does not exist in store_inventory,
        // then add it to the store_inventory.
        if (!isItemIncluded) {
            storeInvList.add(newAcq);
        }
    }
}

Just follow this code sample I worked out according to your requirements.只需按照我根据您的要求制定的代码示例即可。 Note that the library provided simplified API and significent performance for parsing CSV files.请注意,该库为解析 CSV 文件提供了简化的 API 和显着的性能。

As Java doesn't support parsing of CSV files natively, we have to rely on third party library.由于 Java 本身不支持解析 CSV 文件,因此我们必须依赖第三方库。 Opencsv is one of the best library available for this purpose. Opencsv是可用于此目的的最佳库之一。 It's open source and is shipped with Apache 2.0 licence which makes it possible for commercial use.它是开源的,并附带 Apache 2.0 许可证,这使得它可以用于商业用途。

Here, this link should help you and others in the situations!在这里,这个链接应该可以帮助你和其他人在这种情况下!

The operation you are performing will require that for each item in your new acquisitions, you will need to search each item in inventory for a match.您正在执行的操作将要求对于新购置中的每个项目,您需要在库存中的每个项目中搜索匹配项。 This is not only not efficient, but the scanner that you have set up for your inventory file would need to be reset after each item.这不仅效率不高,而且您为库存文件设置的扫描仪在每个项目后都需要重置。

I would suggest that you add your new acquisitions and your inventory to collections and then iterate over your new acquisitions and look up the new item in your inventory collection.我建议您将新收购和库存添加到集合中,然后迭代新收购并在库存集合中查找新项目。 If the item exists, update the item.如果该项目存在,则更新该项目。 If it doesnt, add it to the inventory collection.如果没有,请将其添加到清单集合中。 For this activity, it might be good to write a simple class to contain an inventory item.对于此活动,最好编写一个简单的类来包含库存项目。 It could be used for both the new acquisitions and for the inventory.它可以用于新的收购和库存。 For a fast lookup, I would suggest that you use HashSet or HashMap for your inventory collection.为了快速查找,我建议您使用 HashSet 或 HashMap 进行库存收集。

At the end of the process, dont forget to persist the changes to your inventory file.在该过程结束时,不要忘记将更改保留到您的清单文件中。

For writing to CSV用于写入 CSV

public void writeCSV() {

        // Delimiter used in CSV file
        private static final String NEW_LINE_SEPARATOR = "\n";

        // CSV file header
        private static final Object[] FILE_HEADER = { "Empoyee Name","Empoyee Code", "In Time", "Out Time", "Duration", "Is Working Day" };

        String fileName = "fileName.csv");
        List<Objects> objects = new ArrayList<Objects>();
        FileWriter fileWriter = null;
        CSVPrinter csvFilePrinter = null;

        // Create the CSVFormat object with "\n" as a record delimiter
        CSVFormat csvFileFormat = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR);

        try {
            fileWriter = new FileWriter(fileName);

            csvFilePrinter = new CSVPrinter(fileWriter, csvFileFormat);

            csvFilePrinter.printRecord(FILE_HEADER);

            // Write a new student object list to the CSV file
            for (Object object : objects) {
                List<String> record = new ArrayList<String>();

                record.add(object.getValue1().toString());
                record.add(object.getValue2().toString());
                record.add(object.getValue3().toString());

                csvFilePrinter.printRecord(record);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fileWriter.flush();
                fileWriter.close();
                csvFilePrinter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

You can use Apache Commons CSV api.您可以使用 Apache Commons CSV api。 FYI this anwser : https://stackoverflow.com/a/42198895/6549532仅供参考: https ://stackoverflow.com/a/42198895/6549532

Read / Write Example 读/写示例

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

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