前几天,客户要求开发个小功能,就是把手机的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"); 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错误!"); }
qpEncodeing()
这个方法是专门编码成这种格式的 (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),还有 国产波导,哈哈…..
如有问题,大家可以评论…
你爱我吗?已经爱到危险的程度了.危险到什么程度?已经不能一个人生活。