Java: CSV file read & write

2020-02-05 11:08发布

I'm reading 2 csv files: store_inventory & new_acquisitions.
I want to be able to compare the store_inventory csv 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.

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.

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

7条回答
Deceive 欺骗
2楼-- · 2020-02-05 11:31

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

查看更多
forever°为你锁心
3楼-- · 2020-02-05 11:33

As Java doesn’t support parsing of CSV files natively, we have to rely on third party library. Opencsv is 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.

Here, this link should help you and others in the situations!

查看更多
淡お忘
4楼-- · 2020-02-05 11:36

For writing to 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();
            }
        }
    }
查看更多
在下西门庆
5楼-- · 2020-02-05 11:39

With help of the open source library uniVocity-parsers, you could develop with pretty clean code as following:

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.

查看更多
SAY GOODBYE
6楼-- · 2020-02-05 11:40

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.

At the end of the process, dont forget to persist the changes to your inventory file.

查看更多
欢心
7楼-- · 2020-02-05 11:40

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

Read / Write Example

查看更多
登录 后发表回答