读取带有双引号且带有逗号的csv

时间:2020-03-21 16:30:29

标签: java csv

更新:以下发布的解决方案

我正在尝试处理一个csv文件,并用逗号对其进行分割。但是,有几个带有引号的地方都嵌入了逗号。

示例:“#29.正确识别,存储和使用有毒物质”

每个带有逗号的引号都用“”引起来,是否有办法检测到双引号并解决逗号?

谢谢!

原始代码:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileWriter;
import java.io.PrintWriter;

public class csvFileReader {
    public static void main(String[] args) {
        String csvFile = "/Users/zzmle/Desktop/data.csv";
        BufferedReader br = null;
        String line = "";
        String cvsSplitBy = ",";
        int count=0;       

        try {
            br = new BufferedReader(new FileReader(csvFile));
            String firstline = br.readLine();
            String[] header = firstline.split(",");
            while ((line = br.readLine()) != null && count<10) {
                //comma is the separator
                String[] Restaurant = line.split(cvsSplitBy);
                for (int i=0; i<header.length; i++) {
                    System.out.println(header[i]+": "+Restaurant[i]+" ");
                }
                System.out.println("-------------------");
                count++;
            }

        }   catch (FileNotFoundException e) {
            e.printStackTrace();
        }   catch (IOException e) {
            e.printStackTrace();
        }   finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

工作解决方案:

// @author Zhiming Zhao
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileWriter;
import java.io.PrintWriter;

public class csvFileReader {
    public static void main(String[] args) {
        String csvFile = "data.csv"; 
        BufferedReader br = null; 
        String line = ""; 
        String cvsSplitBy = ",";
        int count=0;       

        try {
            br = new BufferedReader(new FileReader(csvFile));
            String firstline = br.readLine();
            String[] header = firstline.split(cvsSplitBy);
            while ((line = br.readLine()) != null && count<10) { //count<10 is for testing purposes                
                String[] Restaurant = line.split(cvsSplitBy); //comma is the separator
                process(Restaurant); //this is to deal with the commas within quotation marks (which split the elements and shifts them into the wrong places)

                //this part prints the header + restaurant for the first ten lines
                for (int i=0; i<header.length; i++) {
                    System.out.println(header[i]+": "+Restaurant[i]+" ");
                }
                System.out.println("-------------------");
                count++;
            }

        }   catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("The file cannot be found, check if the file is under root directory");
        }   catch (IOException e) {
            e.printStackTrace();
            System.out.println("Input & Output operations error");
        }   finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // @brief This function specifically deal with the issue of commas within the quotation marks
    // @detail it gets the index number of the 2 elements containing the quotation marks, then concats them all. It works with multiple quotation marks on the same line
    public static void process(String[] data) {
        int index1 = -1; //initialize the index of the first ", -1 for empty
        int index2 = 0;  //initialize the index of the second ", 0 for empty
        for (int i=0; i<data.length; i++) {
            if (String.valueOf(data[i].charAt(0)).equals("\"") && index1 == -1) { //if index1 is not empty and the first char of current element is "
                index1 = i; //set index1 to current index number
            }
            if (String.valueOf(data[i].charAt(data[i].length()-1)).equals("\"") && index1 != -1) { //if index1 is not empty and the last char of current element is "
                index2 = i; //set index2 to current index number
                multiconcat(index1, index2, data); //concat the elements between index1 and index2 
                data = multidelet(index1+1, index2, data); //delete the elements that were copied (index1+1:index2)
                i -= (index2-index1); //this is to reset the cursor back to index1 (could be replaced with i = index1)
                index1 = -1; //set index1 to empty

            }
        }    
    }

    // @brief Copy all elements between index1 and index2 to index1, doesn't return anything
    public static void multiconcat(int index1, int index2, String[] data) {
        for (int i=index1+1; i<=index2; i++) {
            data[index1] += data[i];
        }
    }

    // @brief Deletes the elements between index1+1 and index2 
    public static String[] multidelet(int index1, int index2, String[] data) {
        String[] newarr = new String[data.length-(index2-index1+1)];
        int n = 0;
        for (int i=0; i<data.length; i++) {
            if (index1 <= i && i <= index2) continue;
            newarr[n] = data[i];
            n++;
        }
        return newarr;

    }
}

The csv file

输出(带引号和逗号的行之一),虽然不是很完美(被引号引起的逗号被吃掉了),但这是一个小问题,我懒得修复它:

serial_number: DA08R0TCU 
activity_date: 03/30/2018 12:00:00 AM 
facility_name: KRUANG TEDD 
violation_code: F035 
violation_description: "# 35. Equipment/Utensils - approved; installed; clean; good repair capacity" 
violation_status:  capacity" 
points: OUT OF COMPLIANCE 
grade: 1 
facility_address: A 
facility_city: 5151 HOLLYWOOD BLVD 
facility_id: LOS ANGELES 
facility_state: FA0064949 
facility_zip: CA 
employee_id: 90027 
owner_id: EE0000857 
owner_name: OW0001034 
pe_description: 5151 HOLLYWOOD LLC 
program_element_pe: RESTAURANT (31-60) SEATS HIGH RISK 
program_name: 1635 
program_status: KRUANG TEDD 
record_id: ACTIVE 
score: PR0031205 
service_code: 92 
service_description: 1 
row_id: ROUTINE INSPECTION ```

2 个答案:

答案 0 :(得分:0)

我自己的解决方案: 读取每个元素的第一个字符,如果第一个字符是双引号,则将其与后一个(并需要使用递归)进行合并,直到有一个元素将双引号作为最后一个字符。

这比JGFMK建议的逐字符读取要快得多。 而且不允许我为此项目使用外部库。

仍然可以执行此操作,如果可以的话我会进行更新

编辑:工作解决方案发布在原始帖子中

答案 1 :(得分:0)