1. 程式人生 > >CSV檔案的讀取

CSV檔案的讀取

下午接到專案,讀取一個csv檔案並寫入到資料庫中,把資料存入資料庫中比較簡單,可以參考市面上的寫法,或者用一個物件,存放讀取的資料,批量插入資料庫。

但是下午的資料容量較大,據說有2000W條日處理量,而且要求cpu儘量滿格。

好吧,又是一個坑爹又艱難的專案。言歸正傳,來搞一個csv檔案的讀取。

這裡參考了網上的一些寫法,進行了整合

方法1:

package csvtest;
import java.io.BufferedReader;  
import java.io.FileInputStream;  
import java.io.InputStreamReader;  
import java.util.ArrayList;  
  
public class CSVFileUtil {  
    // CSV檔案編碼  
    public static final String ENCODE = "GBK";  
  
    private FileInputStream fis = null;  
    private InputStreamReader isw = null;  
    private BufferedReader br = null;  
    
     
    public CSVFileUtil(String filename) throws Exception {  
        fis = new FileInputStream(filename);  
        isw = new InputStreamReader(fis, ENCODE);  
        br = new BufferedReader(isw);  
    }  
  
    // ==========以下是公開方法=============================  
    /** 
     * 從CSV檔案流中讀取一個CSV行。 
     * 
     * @throws Exception 
     */  
    public String readLine() throws Exception {  
  
        StringBuffer readLine = new StringBuffer();  
        boolean bReadNext = true;  
  
        while (bReadNext) {  
            //  
            if (readLine.length() > 0) {  
                readLine.append("\r\n");  
            }  
            // 一行  
            String strReadLine = br.readLine();  
  
            // readLine is Null  
            if (strReadLine == null) {  
                return null;  
            }  
            readLine.append(strReadLine);  
  
            // 如果雙引號是奇數的時候繼續讀取。考慮有換行的是情況。  
            if (countChar(readLine.toString(), '"', 0) % 2 == 1) {  
                bReadNext = true;  
            } else {  
                bReadNext = false;  
            }  
        }  
        return readLine.toString();  
    }  
  
    /** 
     *把CSV檔案的一行轉換成字串陣列。指定陣列長度,不夠長度的部分設定為null。 
     */  
    public static String[] fromCSVLine(String source, int size) {  
        ArrayList tmpArray = fromCSVLinetoArray(source);  
        if (size < tmpArray.size()) {  
            size = tmpArray.size();  
        }  
        String[] rtnArray = new String[size];  
        tmpArray.toArray(rtnArray);  
        return rtnArray;  
    }  
  
    /** 
     * 把CSV檔案的一行轉換成字串陣列。不指定陣列長度。 
     */  
    public static ArrayList fromCSVLinetoArray(String source) {  
        if (source == null || source.length() == 0) {  
            return new ArrayList();  
        }  
        int currentPosition = 0;  
        int maxPosition = source.length();  
        int nextComma = 0;  
        ArrayList rtnArray = new ArrayList();  
        while (currentPosition < maxPosition) {  
            nextComma = nextComma(source, currentPosition);  
            rtnArray.add(nextToken(source, currentPosition, nextComma));  
            currentPosition = nextComma + 1;  
            if (currentPosition == maxPosition) {  
                rtnArray.add("");  
            }  
        }  
        return rtnArray;  
    }  
  
  
    /** 
     * 把字串型別的陣列轉換成一個CSV行。(輸出CSV檔案的時候用) 
     */  
    public static String toCSVLine(String[] strArray) {  
        if (strArray == null) {  
            return "";  
        }  
        StringBuffer cvsLine = new StringBuffer();  
        for (int idx = 0; idx < strArray.length; idx++) {  
            String item = addQuote(strArray[idx]);  
            cvsLine.append(item);  
            if (strArray.length - 1 != idx) {  
                cvsLine.append(',');  
            }  
        }  
        return cvsLine.toString();  
    }  
  
    /** 
     * 字串型別的List轉換成一個CSV行。(輸出CSV檔案的時候用) 
     */  
    public static String toCSVLine(ArrayList strArrList) {  
        if (strArrList == null) {  
            return "";  
        }  
        String[] strArray = new String[strArrList.size()];  
        for (int idx = 0; idx < strArrList.size(); idx++) {  
            strArray[idx] = (String) strArrList.get(idx);  
        }  
        return toCSVLine(strArray);  
    }  
  
    // ==========以下是內部使用的方法=============================  
    /** 
     *計算指定文字的個數。 
     * 
     * @param str 文字列 
     * @param c 文字 
     * @param start  開始位置 
     * @return 個數 
     */  
    private int countChar(String str, char c, int start) {  
        int i = 0;  
        int index = str.indexOf(c, start);  
        return index == -1 ? i : countChar(str, c, index + 1) + 1;  
    }  
  
    /** 
     * 查詢下一個逗號的位置。 
     * 
     * @param source 文字列 
     * @param st  檢索開始位置 
     * @return 下一個逗號的位置。 
     */  
    private static int nextComma(String source, int st) {  
        int maxPosition = source.length();  
        boolean inquote = false;  
        while (st < maxPosition) {  
            char ch = source.charAt(st);  
            if (!inquote && ch == ',') {  
                break;  
            } else if ('"' == ch) {  
                inquote = !inquote;  
            }  
            st++;  
        }  
        return st;  
    }  
  
    /** 
     * 取得下一個字串 
     */  
    private static String nextToken(String source, int st, int nextComma) {  
        StringBuffer strb = new StringBuffer();  
        int next = st;  
        while (next < nextComma) {  
            char ch = source.charAt(next++);  
            if (ch == '"') {  
                if ((st + 1 < next && next < nextComma) && (source.charAt(next) == '"')) {  
                    strb.append(ch);  
                    next++;  
                }  
            } else {  
                strb.append(ch);  
            }  
        }  
        return strb.toString();  
    }  
  
    /** 
     * 在字串的外側加雙引號。如果該字串的內部有雙引號的話,把"轉換成""。 
     * 
     * @param item  字串 
     * @return 處理過的字串 
     */  
    private static String addQuote(String item) {  
        if (item == null || item.length() == 0) {  
            return "\"\"";  
        }  
        StringBuffer sb = new StringBuffer();  
        sb.append('"');  
        for (int idx = 0; idx < item.length(); idx++) {  
            char ch = item.charAt(idx);  
            if ('"' == ch) {  
                sb.append("\"\"");  
            } else {  
                sb.append(ch);  
            }  
        }  
        sb.append('"');  
        return sb.toString();  
    }  
} 
以上為csv的方法處理類下面以 讀取所有內容為例,進行測試
public static void main(String []args){
		List<stentity> stlist = new ArrayList<stentity>();
		try {CSVFileUtil csvutil = new CSVFileUtil("E:\\600600.csv");
			String a;
			while(((a=csvutil.readLine())!=null)){
				System.out.println(a);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

可以使用,沒毛病

方法二:

這裡採用的是使用專門的jar包,javacsv.jar,可以上網搜查,具體使用方法貼在下面

package test;
import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;
import java.io.BufferedReader; 
import java.io.BufferedWriter;
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileReader; 
import java.io.FileWriter;
import java.io.IOException; 

public class readandwrite {
    public static void main(String[] args) throws IOException { 
        String [] str = {"省","市","區","街","路","裡","幢","村","室","園","苑","巷","號"};
        String inString = "";
        String tmpString = "";
        File inFile = new File("C://in.csv"); // 讀取的CSV檔案
        File outFile = new File("C://outtest.csv");//輸出的CSV文
        try {
            BufferedReader reader = new BufferedReader(new FileReader(inFile));
            BufferedWriter writer = new BufferedWriter(new FileWriter(outFile));
            CsvReader creader = new CsvReader(reader, ',');
            CsvWriter cwriter = new CsvWriter(writer,',');
            while(creader.readRecord()){
                inString = creader.getRawRecord();//讀取一行資料
                for(int i = 0;i < str.length;i++){
                    tmpString = inString.replace(str[i], "," + str[i] + ",");
                    inString = tmpString;
                }
                //第一個引數表示要寫入的字串陣列,每一個元素佔一個單元格,第二個引數為true時表示寫完資料後自動換行
            cwriter.writeRecord(inString.split(","), true);
            //注意,此時再用cwriter.write(inString)方法寫入資料將會看到只往第一個單元格寫入了資料,“,”沒起到調到下一個單元格的作用
            //如果用cwriter.write(String str)方法來寫資料,則要用cwriter.endRecord()方法來實現換行
            //cwriter.endRecord();//換行
            cwriter.flush();//重新整理資料
            }  
            creader.close();
            cwriter.close();
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }
    }
}

該文章參考了http://lqcjdx.blog.163.com/blog/static/207489241201356111749932/ 以及另一篇文章有啥問題可以評論