日韩天天综合网_野战两个奶头被亲到高潮_亚洲日韩欧美精品综合_av女人天堂污污污_视频一区**字幕无弹窗_国产亚洲欧美小视频_国内性爱精品在线免费视频_国产一级电影在线播放_日韩欧美内地福利_亚洲一二三不卡片区

談CSV文件的生成與分析_JSP教程

編輯Tag賺U幣
教程Tag:暫無Tag,歡迎添加,賺取U幣!

推薦:解析用spring發(fā)郵件驗(yàn)證失敗問題
用spring發(fā)郵件驗(yàn)證失敗問題 [See nested exception: org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is javax.mail.AuthenticationFailedException] 按照下述步驟,即可消除此異常信息 屬性設(shè)置如下: !--

CSV文件是指Excel可以識別的后綴名為CSV的文件,網(wǎng)站系統(tǒng)后臺用來存儲分析數(shù)據(jù)的時(shí)候有可能會用到它。其實(shí)CSV文件的讀取和做成比較簡單,主要的技術(shù)點(diǎn)是文件的讀寫。不過CSV文件的分析和生成有一定的代表性,可以通過對CSV文件的生成和分析的實(shí)現(xiàn),來了解后臺處理批量數(shù)據(jù)的簡單思路。

打開Excel,新建一個(gè)文件,在里面隨便輸入一些數(shù)據(jù),然后另存為一個(gè)CSV文件,再次用Excel打開的時(shí)候,發(fā)現(xiàn)只有一個(gè)sheet。用一個(gè)記事本打開這個(gè)文件,可以看到類似如下的數(shù)據(jù)。
aaa,bbb,ccc,ddd
aaa2,bbb2,,ddd2
aaa3,bbb3,ccc3,
aaa4,bbb4,ccc4,ddd4

仔細(xì)觀察數(shù)據(jù),可以確定以下幾點(diǎn):

  1. CSV文件是文本型文件(非二進(jìn)制)
  2. 文件中的一行在Excel中顯示的一行
  3. 同一行中的數(shù)據(jù)用半角逗號分隔

發(fā)現(xiàn)以上的規(guī)律,我們可以自己也生成一個(gè)CSV文件。也可以簡單的分析CSV文件。
現(xiàn)在給CSV文件的生成和分析寫個(gè)簡單的例子。(如果對文件處理類不熟悉,可以看一下java的文件處理,或者看一下JDK中關(guān)于java.io.File類的幫助信息)
生成CSV文件。(HelloCsvCreater.java)

package com.vogoal.test;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author SinNeR
*
* create a CSV file
*/
public class HelloCsvCreater {
public static void main(String[] args) {
try {
FileWriter fw = new FileWriter("C:\\helloCsv.csv");
fw.write("aaa,bbb,ccc,ddd,eee,fff,ggg,hhh\r\n");
fw.write("aa1,bb1,cc1,dd1,ee1,ff1,gg1,hh1\r\n");
fw.write("aaa\r\n");
fw.write("aa2,bb2,cc2,dd2,ee2,ff2,gg2,hh2\r\n");
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

這個(gè)類編譯后運(yùn)行,可以看到在C盤根目錄下生成了一個(gè)名字為helloCsv.csv的CSV文件,雙擊打開,如下的樣子。

分析CSV文件

package com.vogoal.test;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author SinNeR
*
* analysis a CSV file
*/
public class HelloCSVAnalysis {
public static void main(String[] args) {
InputStreamReader fr = null;
BufferedReader br = null;
try {
fr = new InputStreamReader(new FileInputStream(
"C:\\helloCsv.csv"));
br = new BufferedReader(fr);
String rec = null;
String[] argsArr = null;
while ((rec = br.readLine()) != null) {
System.out.println(rec);
argsArr = rec.split(",");
for (int i = 0; i < argsArr.length; i++) {
System.out.println("num " + (i + 1) + ":" + argsArr[i]);
}
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try{
if ( fr != null )
fr.close();
if ( br != null )
br.close();
}catch(IOException ex){
ex.printStackTrace();
}
}
}
}

這里將剛才生成的csv文件讀取并分析。編譯后運(yùn)行,正常情況下,可以看到剛才生成的CSV文件的內(nèi)容。

至此,CSV文件的生成與分析其實(shí)已經(jīng)完成。如果要寫適合自己需要的CSV文件分析類,完全可以根據(jù)自己的業(yè)務(wù)邏輯和需要來自己實(shí)現(xiàn)。因?yàn)镃SV文件的分析確實(shí)很簡單。

不過上面的程序還是存在一些問題的。這些問題在開發(fā)的過程中應(yīng)當(dāng)注意,不然可能出現(xiàn)致命的錯(cuò)誤。

  1. 比較2個(gè)類中對資源的釋放問題。CSV生成類中FileWriter對象的關(guān)閉(close()方法)是在try中執(zhí)行的。而CSV分析類中InputStreamReader,BufferedReader對象的關(guān)閉(close()方法)是在finally中執(zhí)行的。CSV生成類是錯(cuò)誤的。因?yàn)樵谖募土鞯纳蛇^程中,是有可能產(chǎn)生IO異常的,如果在對象close前發(fā)生IO異常,那么close方法永遠(yuǎn)不會被調(diào)用,這樣資源不會及時(shí)釋放,會產(chǎn)生致命錯(cuò)誤的。而在finally中的程序,是一定會被執(zhí)行的語句,所以即使操作中途發(fā)生問題,也會在最后執(zhí)行close方法。(try-catch-finally是java語法中基本而重要的部分,不熟悉的可查閱相關(guān)資料。)
  2. 在CSV文件的操作過程中,我們是按照半角逗號來分隔數(shù)據(jù)的,如果某個(gè)數(shù)據(jù)中正好有半角逗號,那么數(shù)據(jù)不是出錯(cuò)了?
  3. 如果分析的數(shù)據(jù)有全角字符,是否能夠正確分析。(亂碼問題)
    以上的第二個(gè)問題時(shí)必須考慮的。在寫一個(gè)類的時(shí)候,不要相信這個(gè)類要操作的數(shù)據(jù)或者得到的數(shù)據(jù)是好數(shù)據(jù)(完全符合要求的正確的數(shù)據(jù)),寫好的一個(gè)類用完全正確的數(shù)據(jù)測試完,很有可能一個(gè)小小的數(shù)據(jù)錯(cuò)誤的問題,就有可能導(dǎo)致程序處理崩潰。所以,細(xì)節(jié)問題要充分考慮并對應(yīng)到,使自己編寫的類具有一定的健壯性。

對于2的問題的討論:

如果我們用Excel文件生成CSV文件,其中數(shù)據(jù)有半角逗號,Excel會怎么處理呢?試一下,可以看到類似如下的數(shù)據(jù)。
aaa,bbb,ccc,ddd
aaa2,bbb2,,ddd2
aaa3,bbb3,ccc3,
aaa4,"bb,b4",ccc4,ddd4
bb,b4被用雙引號包圍了,這樣,我們自己在生成CSV文件的時(shí)候,可以模仿EXCEL的操作,把所有的數(shù)據(jù)都用雙引號包圍。這時(shí)候又出現(xiàn)一個(gè)問題,如果數(shù)據(jù)中有雙引號,會怎么樣?再次嘗試一下。這次輸入的數(shù)據(jù)是bb,b"4",結(jié)果是:
aaa,bbb,ccc,ddd
aaa2,bbb2,,ddd2
aaa3,bbb3,ccc3,
aaa4,"bb,b""4""",ccc4,ddd4
雙引號被用2個(gè)雙引號替換了。Excel是這么處理的,我們在生成Excel文件的時(shí)候可以模仿處理。這樣分析數(shù)據(jù)的時(shí)候,就要有一個(gè)嚴(yán)格的算法來進(jìn)行分析。
由于做的這個(gè)類是給web開發(fā)用的,我們可以考慮用web常用的轉(zhuǎn)意,將"這個(gè)字符轉(zhuǎn)換成"來避免這樣的沖突,這樣處理的好處是分析字符串的時(shí)候,處理簡單化了。但是這又引發(fā)了別的問題,就是如果數(shù)據(jù)中原來就有"這樣的字符,在將"反轉(zhuǎn)義為"的時(shí)候,容易把這些原有的字符也轉(zhuǎn)化了。所以&符號也需要轉(zhuǎn)義。
現(xiàn)在將2個(gè)方法折衷,即CSV數(shù)據(jù)以半角逗號分隔,以"包圍。數(shù)據(jù)中的&,"符號進(jìn)行轉(zhuǎn)義。
這樣的處理,將分析數(shù)據(jù)的算法難度降低,同時(shí)也解決了數(shù)據(jù)中含有半角逗號,引號的問題。

經(jīng)過以上的分析,我們可以寫CSV生成分析文件的類了。
首先,寫出簡單的轉(zhuǎn)意靜態(tài)方法。

public static String CSVEncode(String in){
if ( in == null )
return "";
in.replaceAll("&","&amp;");
in.replaceAll("\"","&quot;");
return in;
}

public static String CSVDecode(String in){
if ( in == null )
return "";
in.replaceAll("&quot;","\"");
in.replaceAll("&amp;","&");
return in;
}

CSV文件生成類:

package com.vogoal.util.csv;
import java.io.FileOutputStream;
import java.io.IOException;
import com.vogoal.util.UtilCla;
/**
* @author SinNeR
* http://bbs.blueidea.com
*
* CSVCreater
*/
public class CSVCreater {
private FileOutputStream fos = null;
private StringBuffer sb = null;
private boolean convertFlag = false;
public static final String DEL_CHAR = ",";
public static final String AV_CHAR = "\"";
public CSVCreater(String arg) throws IOException {
fos = new FileOutputStream(arg, false);
sb = new StringBuffer();
}
public void setData(String data) {
if (convertFlag)
data = UtilCla.CSVEncode(data);
sb.append(AV_CHAR);
sb.append(data);
sb.append(AV_CHAR);
sb.append(DEL_CHAR);
}
public void setConvertFlag(boolean b) {
convertFlag = b;
}
public void writeLine() {
if (sb.charAt(sb.length() - 1) == ',')
sb.delete(sb.length() - 1, sb.length());
sb.append("\r\n");
}
public void writeDataByLine(String[] args) {
for (int i = 0; i < args.length; i++)
setData(args[i]);
writeLine();
}
public void close() throws IOException {
try {
fos.write(sb.toString().getBytes());
} catch (IOException e) {
throw e;
} finally {
fos.close();
}
}
public static void main(String[] args) {
try {
CSVCreater csvCre = new CSVCreater("C:\\test.csv");
csvCre.setConvertFlag(true);
csvCre.setData("aaa");
csvCre.setData("aa,a");
csvCre.writeLine();
csvCre.setData("aa\"a");
csvCre.setData("aa,a");
csvCre.setData("aa,a");
csvCre.writeLine();
csvCre.setData("aa\"a");
csvCre.setData("aa,\"a");
csvCre.setData("aa,\"a");
csvCre.setData("aa,\"a");
csvCre.setData("aa,\"a");
csvCre.writeLine();
csvCre.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

CSV文件分析類:

package com.vogoal.util.csv;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import com.vogoal.util.UtilCla;
/**
* @author SinNeR
* http://bbs.blueidea.com
*
* CSVAnalysis
*/
public class CSVAnalysis {
private InputStreamReader fr = null;
private boolean convertFlag = false;
private ArrayList dataContainer = new ArrayList();
public static final String DEL_CHAR = ",";
public static final String AV_CHAR = "\"";
public CSVAnalysis(String f) throws IOException {
fr = new InputStreamReader(new FileInputStream(f));
}
public void setConvertFlag(boolean b) {
convertFlag = b;
}
public ArrayList analysis() throws IOException {
BufferedReader br = new BufferedReader(fr);
String rec = null;
try {
while ((rec = br.readLine()) != null) {
ArrayList alLine = analysisLine(rec);
dataContainer.add(alLine);
}
} catch (IOException e) {
throw e;
} finally {
br.close();
}
return dataContainer;
}
private ArrayList analysisLine(String strLine) {
System.out.println(strLine);
ArrayList al = new ArrayList();
String[] dataArr = strLine.split(AV_CHAR);
for (int i = 1; i < dataArr.length; i = i + 2) {
if (convertFlag)
al.add(UtilCla.CSVDecode(dataArr[i]));
else
al.add(dataArr[i]);
}
return al;
}
public void close() throws IOException {
fr.close();
}
public static void main(String[] args) {
try {
CSVAnalysis csvAna = new CSVAnalysis("C:\\test.csv");
csvAna.setConvertFlag(true);
ArrayList al = csvAna.analysis();
for (int i = 0; i < al.size(); i++) {
ArrayList al1 = (ArrayList) al.get(i);
for (int j = 0; j < al1.size(); j++) {
System.out.println(al1.get(j));
}
}
csvAna.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

寫好這些類之后,就可以開始著手測試了。
寫一個(gè)測試CSV文件生成的jsp文件。如:

<%@ page contentType="text/html" import="com.vogoal.util.*,com.vogoal.util.csv.*,java.io.IOException" %>
create a csv file
<%
try {
CSVCreater csvCre = new CSVCreater("C:\\test.csv");
csvCre.setConvertFlag(true);
csvCre.setData("aaa");
csvCre.setData("aa,a");
csvCre.writeLine();
csvCre.setData("aa\"a");
csvCre.setData("aa,a");
csvCre.setData("aa,a");
csvCre.writeLine();
csvCre.setData("aa\"a");
csvCre.setData("aa,\"a");
csvCre.setData("aa,\"a");
csvCre.setData("aa,\"a");
csvCre.setData("aa,\"a");
csvCre.writeLine();
csvCre.close();
} catch (IOException e) {
e.printStackTrace();
}
%>

寫一個(gè)測試CSV文件分析的jsp文件。如:

<%@ page contentType="text/html" import="com.vogoal.util.*,com.vogoal.util.csv.*,java.io.IOException,
java.util.ArrayList" %>
analysis a csv file<br>
<%
try {
CSVAnalysis csvAna = new CSVAnalysis("C:\\test.csv");
csvAna.setConvertFlag(true);
ArrayList al = csvAna.analysis();
for (int i = 0; i < al.size(); i++) {
out.println( (i + 1) + " line start<br>");
ArrayList al1 = (ArrayList) al.get(i);
for (int j = 0; j < al1.size(); j++) {
out.println(al1.get(j));
out.println("<br>");
}
out.println( (i + 1) + " line end<br>");
}
csvAna.close();
} catch (IOException e) {
e.printStackTrace();
}
%>

將編譯后的class拷貝到TOMCAT自己的應(yīng)用的WEB-INF下。將jsp文件放到自己的應(yīng)用下。
然后啟動TOMCAT,訪問jsp文件,當(dāng)訪問creCSV.jsp的時(shí)候,正常情況下可以看到C盤根目錄下生成了一個(gè)test.csv文件。然后訪問anaCSV.jsp文件,可以看到分析后的數(shù)據(jù)被打印出來。

至此,csv生成,分析類做成。

使用幫助

CSVCreater.java類,用來生成CSV文件的類。
構(gòu)造函數(shù)public CSVCreater(String arg) throws IOException
參數(shù):arg 要生成的csv文件的絕對路徑
使用例CSVCreater csvCre = new CSVCreater("C:\\test.csv");

public void setConvertFlag(boolean b)
是否轉(zhuǎn)義設(shè)定函數(shù)(將半角雙引號進(jìn)行轉(zhuǎn)義處理)
參數(shù):true 需要轉(zhuǎn)義(推薦) false 不轉(zhuǎn)義

public void setData(String data)
添加單個(gè)數(shù)據(jù)的函數(shù)

public void writeLine()
結(jié)束換行函數(shù)

public void writeDataByLine(String[] args)
將一個(gè)數(shù)組的元素添加到一行并換行函數(shù)

public void close() throws IOException
必須調(diào)用的函數(shù),寫入文件并關(guān)閉文件處理的對象。

例子可參考jsp文件中的代碼,但是jsp文件中的close()方法是在try塊中執(zhí)行的,不推薦,使用的時(shí)候還是在finally塊中執(zhí)行要安全一些。
這個(gè)類涉及到了文件的操作,有可能出現(xiàn)IOException,出現(xiàn)異常的時(shí)候會拋出給使用者。

CSVAnalysis.java
構(gòu)造函數(shù) public CSVAnalysis(String f) throws IOException
參數(shù)是要分析的文件的絕對路徑。

public ArrayList analysis() throws IOException
分析流處理的方法,返回ArrayList對象。返回的ArrayList的數(shù)據(jù)格式是
ArrayList中存放著ArrayList對象,存放的每個(gè)ArrayList對象對應(yīng)csv文件的一行。
一行對應(yīng)的ArrayList中存放著String對象,為該行中所有的數(shù)據(jù)。

public void close() throws IOException
必須調(diào)用的函數(shù),關(guān)閉文件處理的對象。
同樣,這個(gè)方法應(yīng)在finally塊中執(zhí)行要安全一些。

源碼下載:CSVproc.zip
源碼為上面提到過的所有的類和jsp文件

來源:藍(lán)色理想

 

分享:怎樣防止網(wǎng)頁的內(nèi)容被別人采集
ASP實(shí)例: 怎么防止網(wǎng)頁的內(nèi)容被別人采集,非法的訪問你的網(wǎng)站 % '**************************************** ' 怎么防止網(wǎng)頁的內(nèi)容被別人采集,非法的訪問你的網(wǎng)站 '**************************************** dim onlyURL,from '***指定來源網(wǎng)址... onlyURL=

來源:模板無憂//所屬分類:JSP教程/更新時(shí)間:2010-05-03
相關(guān)JSP教程