如果文件中含有中文字符,那么这时候直接进行读取,即new FileInputStream(要读取的文件),就会出现了乱码,所以这时候,我们需要设置对应的格式进行读取,所以还需要传递对应的编码,所以将代码改成下面那样:new InputStreamReader(new FileInputStream(要读取的文件),"utf-8"),那么就不会再发生乱码了.

同时,如果需要利用java来解析vcf文件,那么需要设置调用相关的方法来进行编码和解码,这个编码和解码的方式网上也有,可以自行百度的,这里主要来说,将对应的信息写入到.vcf文件需要注意的地方:

  • 利用FileWriter对象来写入文件中的时候,需要注意进行刷新,否则,当程序结束的时候,文件可能什么数据都没有
  • 如果写入的数据还有中文数据,那么记得要调用对应的方法来进行编码,否则对应的.vcf文件就是乱码的
  • 写入的数据不需要以分号结束

所以对应的代码为:

package service;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import entity.Person;

public class VCFService {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
        VCFService service = new VCFService();
        File file = new File("src/a.vcf");
        FileInputStream fis = new FileInputStream(file);
        List<Person> persons = service.importVCF(fis);
        File des = new File("src/b.vcf");
        if(!des.exists()) {
        	des.createNewFile();
        }
        service.exportVCF(persons,des);
	}
	private void exportVCF(List<Person> persons,File des) throws Exception {
		/*
		 * vcf文件:
		 * 格式为:
		 * 1、以BEGIN:VCARD开始
		 * 2、说明版本:VERSION:3.0
		 * 3、N;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE: -->说明名字
		 * 4、FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE -->说明英文名字
		 * 5、TEL;TYPE=CELL: --> 说明电话
		 * 6、EMAIL: -->说明邮箱
		 * 7、END:VCARD
		 */
		FileWriter w = new FileWriter(des);
		for(Person person: persons) {
			addToVcf(person,w);
		}
		w.close();//关闭之前会自动刷新
	}
	
	public void addToVcf(Person person,FileWriter w) throws Exception {
		//注意不要有分号,否则,导入到手机的形式将会是它的编码形式,不是中文的形式出现
		//同时不可以直接将person.getName()输入到文件中,否则会出现乱码,需要进行编码
		w.write("BEGIN:VCARD\r\n");
		w.write("VERSION:3.0\r\n");
		w.write("N;CHARSET=UTF-8:" + encode(person.getName()) + "\r\n");
		w.write("FN;CHARSET=UTF-8:" + encode(person.getName())+ "\r\n");
		w.write("TEL;TYPE=CELL:" + encode(person.getCell())  + "\r\n");
		w.write("EMAIL:" + encode(person.getEmail())  + "\r\n");
		w.write("END:VCARD\r\n");
        w.flush();
	}
	public String decoding(String str) throws UnsupportedEncodingException {
		if(str == null) {
			return "";
		}
		str = str.trim();
		str = str.replaceAll("=\n","");
		byte[] bytes = str.getBytes("US-ASCII");
		if(bytes == null) {
			return "";
		}
		for(int i = 0; i < bytes.length; ++i) {
			if(bytes[i] == 95) {
				bytes[i] = 32;
			}
		}
		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
		for(int i = 0; i < bytes.length; ++i) {
			if(bytes[i] == '=') {
				if(i + 2 >= bytes.length) {
					break;
				}
				int l = Character.digit((char)bytes[++i], 16);
				int r = Character.digit((char)bytes[++i], 16);
				if(l == -1 || r == -1) {
					continue;
				}
				buffer.write((char)((l << 4) + r));
			}else { 
				buffer.write(bytes[i]);
			}
		}
		return new String(buffer.toByteArray(),"UTF-8");
	}
	
	public List<Person> importVCF(FileInputStream file) throws Exception {
		//导入对应的vcf文件
		//需要保证这个是utf-8,否则读取文件的时候发生了乱码
		BufferedReader bfr = new BufferedReader(new InputStreamReader(file,"utf-8"));
		String line = null;
		ArrayList<Person> persons = new ArrayList<>();	
		List<String> names = new ArrayList<>();
		List<String> cells = new ArrayList<>();
		List<String> emails = new ArrayList<>();
		while((line = bfr.readLine()) != null) {
			System.out.print(line); 
			int index = line.indexOf(":");//获取第一个冒号的下标,冒号后面就是他的值
			//获取姓名和电话
			if(line.startsWith("N;CHARSET=UTF-8:")) {
				//这时候需要获取它的名字,名字有被进行编码过,所以需要解码
				/*
				并不是对整个line进行解码,而是对它的值进行解码,因为
				CHARSET=UTF-8中同样含有‘=’号,如果对整个line进行解
				码的话,那么就会影响到了CHARSET=UTF-8,从而没有办法
				获取数据的值了
				*/
				line = decoding(line.substring(index + 1));
				names.add(line);
			}else if(line.startsWith("TEL;TYPE=CELL:")) {
			//因为电话,邮箱等不是中文,所以不需要进行解码就可以得到
				line = line.substring(index + 1);
				cells.add(line);
			}else if(line.startsWith("EMAIL:")) {
				line = line.substring(index + 1);
				emails.add(line);
			}
		}
		int size = names.size();
		for(int i = 0; i < size; ++i) {
			persons.add(new Person(names.get(i),cells.get(i),emails.get(i)));
		}
		for(Person person: persons) {
			System.out.println(person);
		}
		return persons;
	}
	public String encode(String str) throws Exception {
		if (str != null) {
			char[] encode = str.toCharArray();
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < encode.length; i++) {
				if ((encode[i] >= '!') && (encode[i] <= '~')
						&& (encode[i] != '=') && (encode[i] != '\n')) {
					sb.append(encode[i]);
				} else if (encode[i] == '=') {
					sb.append("=3D");
				} else if (encode[i] == '\n') {
					sb.append("\n");
				} else {
					StringBuffer sbother = new StringBuffer();
					sbother.append(encode[i]);
					String ss = sbother.toString();
					byte[] buf = null;
					buf = ss.getBytes("utf-8");
					// UTF-8: buf.length == 3
					// GBK: buf.length == 2
					if (buf.length == 3) {
						for (int j = 0; j < buf.length; j++) {
							String s16 = String.valueOf(Integer
									.toHexString(buf[j]));
							char c16_6;
							char c16_7;
							if (s16.charAt(6) >= 97 && s16.charAt(6) <= 122) {
								c16_6 = (char) (s16.charAt(6) - 32);
							} else {
								c16_6 = s16.charAt(6);
							}
							if (s16.charAt(7) >= 97 && s16.charAt(7) <= 122) {
								c16_7 = (char) (s16.charAt(7) - 32);
							} else {
								c16_7 = s16.charAt(7);
							}
							sb.append("=" + c16_6 + c16_7);
						}
					}
				}
			}
			str = sb.toString();
		}
		return str;
	}
}

当生成了.vcf文件之后,我们可以将其发送到手机,然后利用电话来打开对应的文件,那么之后就可以发现我们定义的联系人的信息了。