vcards(vcf)文件轉Excel


有一個安卓手機導出的通訊錄文件是.vcf格式的,想把這里面的聯系人都提取出來,轉換成Excel表格,網上有轉換工具,不過吧是收費的,

看了一下Vcf文件還是很有規律的,感覺使用Io流讀取信息,然后生成Excel問題還是不大的,我這里只提取了簡單的名字和手機號碼,應該可以有更多的信息 比如聯系地址,單位等

首先創建一個maven工程 主要是導出Excel要用第三方jar包

 1           <dependency>
 2             <groupId>cn.hutool</groupId>
 3             <artifactId>hutool-all</artifactId>
 4             <version>5.0.6</version>
 5         </dependency>
 6 
 7         <dependency>
 8             <groupId>org.apache.poi</groupId>
 9             <artifactId>poi-ooxml</artifactId>
10             <version>3.17</version>
11         </dependency>

一個是hutoll工具類框架,另外一個是Apache的處理Excel的POI

然后把代碼貼出來

  1 import cn.hutool.poi.excel.ExcelUtil;
  2 import cn.hutool.poi.excel.ExcelWriter;
  3 
  4 import java.io.*;
  5 import java.util.ArrayList;
  6 import java.util.Arrays;
  7 import java.util.List;
  8 
  9 /**
 10  * @Description: 讀取Vcf文件並轉換為Excel
 11  * @Author: Tan
 12  * @CreateDate: 2020/2/5
 13  **/
 14 public class VcfToExcel {
 15     public static void main(String[] args) throws Exception {
 16         long start=System.currentTimeMillis();
 17         //讀取vcf文件
 18         BufferedReader bufferedReader=new BufferedReader(new FileReader("vcf文件路徑"));
 19         //計數器 統計當前有多少記錄
 20         int count=0;
 21         //創建導出Excel數據集合
 22         List<List<String>> exportList=new ArrayList<>();
 23         //添加一行 算標題 第一行
 24         exportList.add(Arrays.asList("編號","姓名","手機號碼"));
 25         //讀取的信息
 26         String info;
 27         //循環讀取
 28         while ((info=bufferedReader.readLine())!=null){
 29             //讀取到的這一行以FN開頭 代表名字
 30             if(info.startsWith("FN")){
 31                 //截取名字編碼部分
 32              String name=info.substring(info.indexOf(":")+1);
 33              //名字編碼的下一行為手機號也可能是名字編碼的剩余字符
 34              String phone=bufferedReader.readLine();
 35              //判斷是否是=開頭 如果是就是名字編碼的剩余部分,也拼接到名字,下一行就是手機號
 36              if(phone.startsWith("=")){
 37                  name+=phone.substring(1);
 38                  phone=bufferedReader.readLine();
 39              }else if("".equals(phone)){
 40                  phone=bufferedReader.readLine();
 41              }
 42              //截取手機號
 43              phone=phone.substring(phone.indexOf(":")+1);
 44 
 45              //判斷名字編碼最后一位是否是= 如果是要刪除掉
 46              if(name.charAt(name.length()-1)==61){
 47                 name=  name.substring(0,name.length()-1);
 48              }
 49                 //將編號 名字進行解碼 和手機號 添加到導出數據
 50                 exportList.add(Arrays.asList(Integer.toString(++count),qpDecoding(name),phone));
 51             }
 52 
 53         }
 54         //關閉緩存流
 55         bufferedReader.close();
 56 
 57         //創建hutool工具類的寫Excel對象
 58         ExcelWriter writer = ExcelUtil.getWriter("導出Excel的路徑.xlsx");
 59 
 60         //寫入數據 生成Excel
 61         writer.write(exportList, true);
 62 
 63         //關閉writer,釋放內存
 64         writer.close();
 65 
 66         System.out.println("生成完畢,耗費時間 "+(System.currentTimeMillis()-start));
 67 
 68     }
 69 
 70 
 71 
 72 
 73     //解碼方法  如果拋出數組越界異常 可能是數據不規范 檢查解碼字符串
 74     public final static String qpDecoding(String str)
 75     {
 76         if (str == null)
 77         {
 78             return "";
 79         }
 80         try
 81         {
 82             StringBuffer sb = new StringBuffer(str);
 83             for (int i = 0; i < sb.length(); i++)
 84             {
 85                 if (sb.charAt(i) == '\n' && sb.charAt(i - 1) == '=')
 86                 {
 87                     // 解碼這個地方也要修改一下
 88                     // sb.deleteCharAt(i);
 89                     sb.deleteCharAt(i - 1);
 90                 }
 91             }
 92             str = sb.toString();
 93             byte[] bytes = str.getBytes("US-ASCII");
 94             for (int i = 0; i < bytes.length; i++)
 95             {
 96                 byte b = bytes[i];
 97                 if (b != 95)
 98                 {
 99                     bytes[i] = b;
100                 }
101                 else
102                 {
103                     bytes[i] = 32;
104                 }
105             }
106             if (bytes == null)
107             {
108                 return "";
109             }
110             ByteArrayOutputStream buffer = new ByteArrayOutputStream();
111             for (int i = 0; i < bytes.length; i++)
112             {
113                 int b = bytes[i];
114                 if (b == '=')
115                 {
116                     try
117                     {
118                         int u = Character.digit((char) bytes[++i], 16);
119                         int l = Character.digit((char) bytes[++i], 16);
120                         if (u == -1 || l == -1)
121                         {
122                             continue;
123                         }
124                         buffer.write((char) ((u << 4) + l));
125                     }
126                     catch (ArrayIndexOutOfBoundsException e)
127                     {
128                         e.printStackTrace();
129                     }
130                 }
131                 else
132                 {
133                     buffer.write(b);
134                 }
135             }
136             return new String(buffer.toByteArray(), "UTF-8");
137         }
138         catch (Exception e)
139         {
140             e.printStackTrace();
141             return "";
142         }
143     }
144 
145 }

主要問題就在於 我這個vcf文件其中名字的數據並不是直接是中文的而是一個特殊的QUOTED-PRINTABLE編碼

數據類似這樣 =E5=BC=A0=E4=B8=89  所以需要提取到這個編碼的字符串 然后調用我這個qpDecoding()方法進行解碼

就這樣,希望可以幫助到有需要的人


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM