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/ 以及另一篇文章有啥问题可以评论


版权声明:本文为gengyazhou123原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。