Java:CSV 文件读写

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2982828/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:14:25  来源:igfitidea点击:

Java: CSV file read & write

javafilecsvjava.util.scanner

提问by nubme

I'm reading 2 csv files: store_inventory& new_acquisitions.
I want to be able to compare the store_inventorycsv file with new_acquisitions. 1) If the item names match just update the quantity in 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 个 csv 文件:store_inventory& new_acquisitions
我希望能够将store_inventorycsv 文件与new_acquisitions. 1) 如果商品名称匹配,只需更新 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.
Any advice or code to do the above tasks would be great! thanks.

这是我到目前为止所做的但不是很好。我在需要添加 taks 12 的地方添加了评论。
任何完成上述任务的建议或代码都会很棒!谢谢。

    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. =]

再次感谢任何帮助。=]

采纳答案by objects

Suggest you use one of the existing CSV parser such as Commons CSVor Super CSVinstead of reinventing the wheel. Should make your life a lot easier.

建议您使用现有的 CSV 解析器之一,例如Commons CSVSuper CSV,而不是重新发明轮子。应该会让你的生活轻松很多。

回答by akf

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.

在该过程结束时,不要忘记将更改保留到您的清单文件中。

回答by AgilePro

Your implementation makes the common mistake of breaking the line on commas by using 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 splitmethod can not do this -- I see this mistake a lot.

您的实现犯了一个常见的错误,即使用line.split(","). 这不起作用,因为值本身可能包含逗号。如果发生这种情况,则必须引用该值,并且您需要忽略引号内的逗号。该split方法无法做到这一点——我经常看到这个错误。

Here is the source of an implementation that does it correctly: http://agiletribe.wordpress.com/2012/11/23/the-only-class-you-need-for-csv-files/

这是正确执行的实现的来源:http: //agiletribe.wordpress.com/2012/11/23/the-only-class-you-need-for-csv-files/

回答by Adit Gupta

As Java doesn't support parsing of CSV files natively, we have to rely on third party library. Opencsvis one of the best library available for this purpose. It's open source and is shipped with Apache 2.0 licence which makes it possible for commercial use.

由于 Java 本身不支持解析 CSV 文件,因此我们必须依赖第三方库。Opencsv是可用于此目的的最佳库之一。它是开源的,并附带 Apache 2.0 许可证,这使得它可以用于商业用途。

Here, this linkshould help you and others in the situations!

在这里,此链接应该可以帮助您和其他人在这种情况下!

回答by xiaolei yu

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 和显着的性能。

回答by Nilesh Jadav

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();
            }
        }
    }

回答by Kevin Li

You can use Apache Commons CSV api. FYI this anwser : https://stackoverflow.com/a/42198895/6549532

您可以使用 Apache Commons CSV api。仅供参考:https://stackoverflow.com/a/42198895/6549532

Read / Write Example

读/写示例