在解析csv檔案之前,先來看看什麼是csv檔案以及csv檔案的格式。
csv(Comma Separate Values)檔案即逗號分隔字元檔案,它是一種文字檔,可以直接以文本開啟,以逗號分隔。windows預設用excel開啟。它的格式包括以下幾點(它的格式最好就看excel是如何解析的。):
①每條記錄佔一行;
②以逗號為分隔字元;
③逗號前後的空格會被忽略;
④欄位中包含有逗號,該欄位必須用雙引號括起來;
⑤欄位中包含有分行符號,該欄位必須用雙引號括起來;
⑥欄位前後包含有空格,該欄位必須用雙引號括起來;
⑦欄位中的雙引號用兩個雙引號表示;
⑧欄位中如果有雙引號,該欄位必須用雙引號括起來;
⑨第一條記錄,可以是欄位名;
⑩以上提到的逗號和雙引號均為半形字元。
下面通過Regex和java解析csv檔案。
首先給出匹配csv檔案的一個最小單位元據的Regex(如:1,2,3是csv檔案的一行資料,則1,是該csv檔案的一個最小單位元據):
"(([^",\n ]*[,\n ])*([^",\n ]*"{2})*)*[^",\n ]*"[ ]*,[ ]*|[^",\n]*[ ]*,[ ]*|"(([^",\n ]*[,\n ])*([^",\n ]*"{2})*)*[^",\n ]*"[ ]*|[^",\n]*[ ]*
下面是解析檔案的java代碼:
package myutil;
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;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author panhf2003
* @version 2008/09/05,
*/
public class CsvFileUtil {
/**
* 構造,禁止執行個體化
*/
private CsvFileUtil() {
}
public static void main(String[] args) {
// test
try {
readCsvFile("e:\\test1.csv");
} catch (FileNotFoundException ex) {
Logger.getLogger(CsvFileUtil.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(CsvFileUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* csv檔案讀取<BR/>
* 讀取絕對路徑為argPath的csv檔案資料,並以List返回。
*
* @param argPath csv檔案絕對路徑
* @return csv檔案資料(List<String[]>)
* @throws FileNotFoundException
* @throws IOException
*/
public static List readCsvFile(String argPath) throws FileNotFoundException, IOException {
CsvFileUtil util = new CsvFileUtil();
File cvsFile = new File(argPath);
List list = new ArrayList();
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
fileReader = new FileReader(cvsFile);
bufferedReader = new BufferedReader(fileReader);
String regExp = util.getRegExp();
// test
System.out.println(regExp);
String strLine = "";
String str = "";
while ((strLine = bufferedReader.readLine()) != null) {
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(strLine);
List listTemp = new ArrayList();
while(matcher.find()) {
str = matcher.group();
str = str.trim();
if (str.endsWith(",")){
str = str.substring(0, str.length()-1);
str = str.trim();
}
if (str.startsWith("\"") && str.endsWith("\"")) {
str = str.substring(1, str.length()-1);
if (util.isExisted("\"\"", str)) {
str = str.replaceAll("\"\"", "\"");
}
}
if (!"".equals(str)) {
//test
System.out.print(str+" ");
listTemp.add(str);
}
}
//test
System.out.println();
list.add((String[]) listTemp.toArray(new String[listTemp.size()]));
}
} catch (FileNotFoundException e) {
throw e;
} catch (IOException e) {
throw e;
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
throw e;
}
}
return list;
}
/**
* csv檔案做成<BR/>
* 將argList寫入argPath路徑下的argFileName檔案裡。
*
* @param argList 要寫入csv檔案的資料(List<String[]>)
* @param argPath csv檔案路徑
* @param argFileName csv檔案名稱
* @param isNewFile 是否覆蓋原有檔案
* @throws IOException
* @throws Exception
*/
public static void writeCsvFile(List argList, String argPath, String argFileName, boolean isNewFile)
throws IOException, Exception {
CsvFileUtil util = new CsvFileUtil();
// 資料check
if (argList == null || argList.size() == 0) {
throw new Exception("沒有資料");
}
for (int i = 0; i < argList.size(); i++) {
if (!(argList.get(i) instanceof String[])) {
throw new Exception("資料格式不對");
}
}
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
String strFullFileName = argPath;
if (strFullFileName.lastIndexOf("\\") == (strFullFileName.length() - 1)) {
strFullFileName += argFileName;
} else {
strFullFileName += "\\" + argFileName;
}
File file = new File(strFullFileName);
// 檔案路徑check
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try {
if (isNewFile) {
// 覆蓋原有檔案
fileWriter = new FileWriter(file);
} else {
// 在原有檔案上追加資料
fileWriter = new FileWriter(file, true);
}
bufferedWriter = new BufferedWriter(fileWriter);
for (int i = 0; i < argList.size(); i++) {
String[] strTemp = (String[]) argList.get(i);
for (int j = 0; j < strTemp.length; j++) {
if (util.isExisted("\"",strTemp[j])) {
strTemp[j] = strTemp[j].replaceAll("\"", "\"\"");
bufferedWriter.write("\""+strTemp[j]+"\"");
} else if (util.isExisted(",",strTemp[j])
|| util.isExisted("\n",strTemp[j])
|| util.isExisted(" ",strTemp[j])
|| util.isExisted("��",strTemp[j])){
bufferedWriter.write("\""+strTemp[j]+"\"");
} else {
bufferedWriter.write(strTemp[j]);
}
if (j < strTemp.length - 1) {
bufferedWriter.write(",");
}
}
bufferedWriter.newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedWriter != null) {
bufferedWriter.close();
}
if (fileWriter != null) {
fileWriter.close();
}
} catch (IOException e) {
throw e;
}
}
}
/**
* @param argChar
* @param argStr
* @return
*/
private boolean isExisted(String argChar, String argStr) {
boolean blnReturnValue = false;
if ((argStr.indexOf(argChar) >= 0)
&& (argStr.indexOf(argChar) <= argStr.length())) {
blnReturnValue = true;
}
return blnReturnValue;
}
/**
* Regex。
* @return 匹配csv檔案裡最小單位的Regex。
*/
private String getRegExp() {
String strRegExp = "";
strRegExp =
"\"(("+ SPECIAL_CHAR_A + "*[,\\n ])*("+ SPECIAL_CHAR_A + "*\"{2})*)*"+ SPECIAL_CHAR_A + "*\"[ ]*,[ ]*"
+"|"+ SPECIAL_CHAR_B + "*[ ]*,[ ]*"
+ "|\"(("+ SPECIAL_CHAR_A + "*[,\\n ])*("+ SPECIAL_CHAR_A + "*\"{2})*)*"+ SPECIAL_CHAR_A + "*\"[ ]*"
+ "|"+ SPECIAL_CHAR_B + "*[ ]*";
return strRegExp;
}
private static final String SPECIAL_CHAR_A = "[^\",\\n ]";
private static final String SPECIAL_CHAR_B = "[^\",\\n]";
}
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/panhf2003/archive/2008/09/16/2937853.aspx