前幾天,客戶要求開發個小功能,就是把手機的VCF電話薄文件導出來後,可以導入數據庫,然後從數據庫 出來的記錄,同樣可以生成vcf文件,並且地手機導入後可以成為有用電話薄.(vcf文件內容格式另外有介紹 )
大家可以看看http://sourceforge.net/projects/mime-dir-j/這個開源的,前幾天還上不了個網站(我 是用代理上的),這幾天好像是可以了,我是自己看了下源碼.然後寫了下,
在java中生成vcf文件,我是在Servlet中用文件流做的部份代碼如下 :
response.setHeader("Content-Disposition","attachment; filename="+ new String (bean.getTrueName().getBytes("GBK"), "ISO8859-1" )+".vcf");
qpEncodeing()
try{
java.io.PrintWriter bufout=response.getWriter();
bufout.write("BEGIN:VCARD");
bufout.write("\r\n");
bufout.write("VERSION:2.1");
bufout.write("\r\n");
bufout.write("N;CHARSET=UTF-8;ENCODING=QUOTED- PRINTABLE:"+AddressServlet.qpEncodeing(bean.getTrueName())+";");
bufout.write("\r\n");
if(""!=bean.getMobile()&&bean.getMobile()!=null){
bufout.write("TEL;CELL:"+bean.getMobile()+"");
bufout.write("\r\n");
}
if(""!=bean.getWorkMobile()&&bean.getWorkMobile()! =null){
bufout.write("TEL;WORK:"+bean.getWorkMobile()+"");
bufout.write("\r\n");
}
if(""!=bean.getTelephone()&&bean.getTelephone()!=null) {
bufout.write("TEL;HOME:"+bean.getTelephone()+"");
bufout.write("\r\n");
}
if(""!=bean.getEmail()&&bean.getEmail()!=null){
bufout.write("EMAIL:"+bean.getEmail()+"");
bufout.write("\r\n");
}
bufout.write("END:VCARD");
bufout.write("\r\n");
response.getOutputStream().flush();
response.getOutputStream().close();
}
catch(IOException E){
System.out.println("vcfexport發生I/O錯誤!");
}
這個方法是專門編碼成這種格式的 (http://www.blogjava.net/sundc/archive/2008/08/04/219863.html).
2.從本地上傳後導入到DB,我也是在Servlet實現的
FileItem fi=null;
try {
FileUpload fu = new FileUpload();
// 設置最大文件尺寸,這裡是2MB
fu.setSizeMax(2097152);
// 得到所有的文件:
DiskFileItemFactory factory = new DiskFileItemFactory();
fu.setFileItemFactory(factory);
List fileItems = fu.parseRequest(requestContext);
Iterator i = fileItems.iterator();
while(i.hasNext()) {
fi= (FileItem)i.next();
// 獲得文件名,這個文件名包括路徑:
String fileName = fi.getName();
if(fi.getSize()>2097152){
return "文件太大";
}
if(fileName==null){
return "文件錯誤";
}
String fileExt=StringUtils.getFileExt(fileName).toLowerCase();
if (fileExt.toLowerCase().equals("vcf")){
Properties p=this.createProperties();
try {
ArrayList li = this.importVCFFileContact (fi.getInputStream(), p);
if(li==null||li.size()==0){
return "導入記錄0條,可能是導入文件內容格式不正 確";
}
this.addAddresses(li);
return "1";
} catch (IOException e) {
return "文件格式發生錯誤";
}
}
else{
return "不是vcf文件";
}
}
}
catch(Exception e) {
if(e.getMessage().indexOf("maximum")>0){
return "導入文件發生錯誤,文件大於2M";
}
log.debug(e.getMessage());
return "導入文件發生錯誤"+e.getMessage();
}
finally{
try{
//刪除臨時文件
fi.delete();
}
catch (Exception e) {
// TODO: handle exception
}
}
return "發生錯誤";
}
這個上傳中用到的代碼.下面是把VCF文件解析成bean對象
/**
* 導入聯系人
* @param in
* @throws SystemException
*/
public ArrayList importVCFFileContact(InputStream in,Properties pp) throws SystemException{
try {
BufferedReader reader = new BufferedReader(new InputStreamReader (in));
Document document = new DocumentImpl();
BufferedWriter writer = null;
String line;
StringBuffer bu=new StringBuffer();
while ((line = DecorGroup.nextLine(reader)) != null) {
bu.append(line+"\r\n");
}
Pattern p=Pattern.compile("BEGIN:VCARD(\\r\\n) ([\\s\\S\\r\\n\\.]*?)END:VCARD");//分組,
Matcher m=p.matcher(bu.toString());
while(m.find()){
AddressBean be=new AddressBean();
be.setCateId(gb.getId());
be.setUserId(gb.getUserId());
String str=m.group(0);
//姓名
Pattern pn=Pattern.compile("N;([\\s\\S\\r\\n\\.]*?) ([\\r\\n])");//分組,
Matcher mn=pn.matcher(m.group(0));
while(mn.find()){
String name="";
if(mn.group(1).indexOf("ENCODING=QUOTED-PRINTABLE")>-1) {
name=mn.group(1).substring(mn.group(1).indexOf ("ENCODING=QUOTED-PRINTABLE:")+"ENCODING=QUOTED-PRINTABLE:".length());
name=name.substring(name.indexOf(":")+1);
if(name.indexOf(";")>-1){
name=name.substring(0,name.indexOf(";"));
be.setTrueName(AddressServlet.qpDecoding(name));
}
else{
be.setTrueName(AddressServlet.qpDecoding(name));
}
}
else{
Pattern pnn=Pattern.compile("CHARSET=([A-Za-z0-9-] *?):");
Matcher mnn=pnn.matcher(mn.group(1));
while(mnn.find()){
name=mn.group(1).substring(mn.group(1).indexOf (mnn.group(0))+mnn.group(0).length());
be.setTrueName(name);
}
}
}
if(be.getTrueName().length()>20){
return null;
}
String cell="";
Pattern p1=Pattern.compile("TEL;CELL:\\d*");//分組,
Matcher m1=p1.matcher(str);
while(m1.find()){
cell=m1.group(0).substring(m1.group(0).indexOf("TEL;CELL:") +"TEL;CELL:".length());
}
be.setMobile(cell);
if(be.getMobile().length()>13){
return null;
}
String work="";
Pattern p2=Pattern.compile("TEL;WORK:\\d*");//分組,
Matcher m2=p2.matcher(str);
while(m2.find()){
work=m2.group(0).substring(m2.group(0).indexOf("TEL;WORK:") +"TEL;WORK:".length());
}
be.setWorkMobile(work);
if(be.getWorkMobile().length()>13){
return null;
}
String home="";
Pattern p3=Pattern.compile("TEL;HOME:\\d*");//分組,
Matcher m3=p3.matcher(str);
while(m3.find()){
home=m3.group(0).substring(m3.group(0).indexOf("TEL;HOME:") +"TEL;HOME:".length());
}
be.setTelephone(home);
if(be.getTelephone().length()>13){
return null;
}
String email="";
Pattern p4=Pattern.compile("\\w+(\\.\\w+)*@\\w+(\\.\\w+) +");//分組,
Matcher m4=p4.matcher(str);
while(m4.find()){
email=m4.group(0);
}
be.setEmail(email);
}
reader.close();
} catch (Exception e) {
log.debug(e.getMessage());
throw new SystemException("對不起,系統忙,請梢後再試!");
}
return abs;
}
以下是源碼中自代的方法,我COPY過來就用了
public static String nextLine(BufferedReader reader) throws IOException {
String line;
String nextLine;
do {
line = reader.readLine();
if (line == null) return null;
} while (line.length() == 0);
// Evolution style line folding
while (line.endsWith("=")) {
line = line.substring(0, line.length() - 1);
line += reader.readLine();
}
// RFC 2425 line folding
reader.mark(1000);
nextLine = reader.readLine();
if ((nextLine != null)
&& (nextLine.length() > 0)
&& ((nextLine.charAt(0) == 0x20) // white space
|| (nextLine.charAt(0) == 0x09))) { // tab
line += nextLine.substring(1);
} else {
reader.reset();
}
line = line.trim();
return line;
}
在這裡要提醒大家,有的手機的電話薄可能字選項會多一點.所以,我在這做的是 姓名 手機號碼 電 話 工作電話 Email這幾個大家手機都會有的. 程序通過諾基亞,三星(SAMSUNG),摩托羅拉(MOTO),還有 國產波導,哈哈.....
如有問題,大家可以評論...