ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

利用vCard实现扫码将个人信息保存到通讯录

2021-05-12 14:00:53  阅读:291  来源: 互联网

标签:段值 扫码 return String vCard content 通讯录 import public


利用vCard实现扫码将个人信息保存到通讯录

一、功能

利用vCard实现扫码将个人信息保存到通讯录

二、vCard

1.简单了解

vCard是电子名片的文件格式标准。它一般附加在电子邮件之后,但也可以用于其它场合(如在互联网上相互交换)。vCard可包含的信息有:姓名、地址资讯、电话号码、URL,logo,相片等。

2.通讯录vcard关键字描述

字段名字段类型字段值备注
FN无定义该字段值定义了一种格式化名字(Formatted Name),日常名字的表示方法。基于X.520的普通名字语义规则
N无定义字段值表示人名或物名形式:[Family Name];[Given Name];[Additional Names];
[Name Prefix];[Name Suffix]
有些字段值可能只有一个“;”
PHOTOGIF,CGM,WMF,BMP,MET,PMB,
DIB,PICT,TIFF,PS,PDF,JPEG,
MPEG,MPEG2,AVI,QTIME
字段值是图象数据或存储图象数据的文件名(包含URL路径)没有默认的字段类型,所以必须指定一种字段类型
BDAY无定义字段值是出生日期的数据,有两种表示方法:
1)、基于ISO8601的基本格式:<month>
2)、基于ISO8601的扩展格式:--其中年是四个字符表示,月份和日期是两个字符表示
ADRDOM,INTL(),POSTAL(),PARCEL(),
HOME,WORK(
)
分7个字段表示地址的值:
[Post Office Address];[Extended Address];
[Street];[Locality];[Region];[Postal code];
[Country]
第一个字段基于X.500标准,其余字段基于X.520标准
LABELDOM,INTL(),POSTAL(),PARCEL(),
HOME,WORK(
)
字段值是一种日常表示地址的方法基于X.520的普通名字语义规则
TELPREF,WORK,HOME,VOICE(*),
FAX,MSG,CELL,PAGER,BBS,MODEM,
CAR,ISDN,VIDEO
字段值是基于X.520的电话号码表示方法,这种数据格式不能保证能被拨号程序直接使用,具体的数据格式解析应由拨号程序解决。
EMAILAOL,AppleLink,ATTMail,
CIS,eWorld,INTERNET(*),IBMMail,
MCIMail,POWERSHARE,
PRODIGY,TLX,X400
字段值是电子邮件地址第二栏列出的是该字段类型的一部份,可能会有其它的类型
EMAILER无定义字段值是电子邮件软件的名称
TZ无定义字段值是某地时间相对于UTC(Coordianted Universal Time)的时差(时区),用正负值表示相对值,UTC以西则为负值,以东为正值,值表示根据ISO8610标准,有两种形式:
1)、<+/-><hour(two digit)><minute(two digit)>
2)、<+/-><hour(two digit)>:<minute(two digit)>
GEO无定义字段值表示某地的经度(longitude)和纬度(latitude)的地理位置信息,北纬为正值,南纬为负值,东经为正值,西经为负值:
 <+/->[longitude value],<+/->[latitude value]
TITLE无定义字段值表示某人头衔名
ROLE无定义字段值表示一个人的职业名称或承担的角色或其它商务类型,基于X.520商务类型定义。
LOGOGIF,CGM,WMF,BMP,MET,PMB,
DIB,PICT,TIFF,PDF,PS,JPEG,
MPEG,MPEG2,AVI,QTIME
字段值表示某种标识的图像或肖像没有默认字段类型,所以必须指定一种字段类型
AGENT无定义字段值表示与vCard对象所定义的人有关系的另一个人的信息(如管理员,助手,秘书等),字段值是一个完整的vCard数据包
ORG无定义字段值表示一个机构名称,基于X.520标准:
[Organization Name];[Organization Unit]
[;additional Organizational Unit;…]
NOTE无定义字段值为与本vCard对象有关的备注或提示信息,基于X.520标准
REV无定义字段值表示最后一次的对本vCard对象的更新时间,时间采用日程表中的时间表示方法,基于ISO8601标准:
1)、<year(four digits)><month(two digits)><day(two digits)>T<hour(two digits)><minitue(two digits)><second(two digits)>[time zone]
2)、<year(four digits)>-<month(two digits)>-<day(two digits)>T<hour(two digits)>:<minitue(two digits)>:<second(two digits)>[time zone]
SOUNDWAVE,PCM,AIFF字段值表示与本vCard对象有关的发音的声音数据,如该字段没有与其它字段分组,则该字段表示FN字段值的发音,字段值可以是二制的声音数据,也可以用其它单词表示的发音方法。没有默认字段类型,当没有指定字段类型时,字段值为表示发音方法的文件或单词
URL无定义字段值表示统一资源位置(Uniform Resource Locator),基于IETF RFC 1738定义。
UID无定义字段值表示本vCard对象的GUID号或本vCard对象将被更新的URL地址
VERSION无定义字段值表示本vCard对象的版本号该字段是必选字段,在更早以前的版本是可选
KEYX509,PGP该字段值表示加密密钥,默认的格式是明文格式(clear-text)没有默认字段类型,字段类型必需被定义
X-无定义该字段值由用户自定义字段参数值由用户自选

注:1、字段类型后带“*”表示是默认字段类型;
  2、字段值中若以“;”进行值分类的,当值中本身还包含有“;”或“\r\n”则必须进行转义,相应地用“;”和“\”CRCF来进行转义
PS:内容来源于网络,本文案例中仅做了部分实践,感兴趣的可自行实践

3.包含个人信息的vCard文件样例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

三、实现

1.所需jar包

温馨提示:先看完再选择是否下载
在这里插入图片描述

2.二维码处理工具类

TwoDimensionCodeImage.java

package util;

import java.awt.image.BufferedImage;

import jp.sourceforge.qrcode.data.QRCodeImage;

public class TwoDimensionCodeImage implements QRCodeImage {

	BufferedImage bufImg;

	public TwoDimensionCodeImage(BufferedImage bufImg) {
		this.bufImg = bufImg;
	}

	@Override
	public int getHeight() {
		return bufImg.getHeight();
	}

	@Override
	public int getPixel(int x, int y) {
		return bufImg.getRGB(x, y);
	}

	@Override
	public int getWidth() {
		return bufImg.getWidth();
	}

}

TwoDimensionCode.java

package util;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.imageio.ImageIO;

import jp.sourceforge.qrcode.QRCodeDecoder;
import jp.sourceforge.qrcode.exception.DecodingFailedException;

import com.swetake.util.Qrcode;

public class TwoDimensionCode {

	/**
	 * 生成二维码(QRCode)图片
	 * 
	 * @param content
	 *            存储内容
	 * @param imgPath
	 *            图片路径
	 */
	public static void encoderQRCode(String content, String imgPath) {
		encoderQRCode(content, imgPath, "png", 2);
	}

	/**
	 * 生成二维码(QRCode)图片
	 * 
	 * @param content
	 *            存储内容
	 * @param output
	 *            输出流
	 */
	public static void encoderQRCode(String content, OutputStream output) {
		encoderQRCode(content, output, "png", 2);
	}

	/**
	 * 生成二维码(QRCode)图片
	 * 
	 * @param content
	 *            存储内容
	 * @param imgPath
	 *            图片路径
	 * @param imgType
	 *            图片类型
	 */
	public static void encoderQRCode(String content, String imgPath,
			String imgType) {
		encoderQRCode(content, imgPath, imgType, 2);
	}

	/**
	 * 生成二维码(QRCode)图片
	 * 
	 * @param content
	 *            存储内容
	 * @param output
	 *            输出流
	 * @param imgType
	 *            图片类型
	 */
	public static void encoderQRCode(String content, OutputStream output,
			String imgType) {
		encoderQRCode(content, output, imgType, 2);
	}

	/**
	 * 生成二维码(QRCode)图片
	 * 
	 * @param content
	 *            存储内容
	 * @param imgPath
	 *            图片路径
	 * @param imgType
	 *            图片类型
	 * @param size
	 *            二维码尺寸
	 */
	public static void encoderQRCode(String content, String imgPath,
			String imgType, int size) {
		try {
			BufferedImage bufImg = qRCodeCommon(content, imgType, size);

			File imgFile = new File(imgPath);
			// 生成二维码QRCode图片
			ImageIO.write(bufImg, imgType, imgFile);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 生成二维码(QRCode)图片
	 * 
	 * @param content
	 *            存储内容
	 * @param output
	 *            输出流
	 * @param imgType
	 *            图片类型
	 * @param size
	 *            二维码尺寸
	 */
	public static void encoderQRCode(String content, OutputStream output,
			String imgType, int size) {
		try {
			BufferedImage bufImg = qRCodeCommon(content, imgType, size);
			// 生成二维码QRCode图片
			ImageIO.write(bufImg, imgType, output);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 生成二维码(QRCode)图片的公共方法
	 * 
	 * @param content
	 *            存储内容
	 * @param imgType
	 *            图片类型
	 * @param size
	 *            二维码尺寸
	 * @return
	 */
	private static BufferedImage qRCodeCommon(String content, String imgType,
			int size) {
		BufferedImage bufImg = null;
		size = 14;
		try {
			Qrcode qrcodeHandler = new Qrcode();
			// 设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小
			qrcodeHandler.setQrcodeErrorCorrect('M');
			qrcodeHandler.setQrcodeEncodeMode('B');
			// 设置设置二维码尺寸,取值范围1-40,值越大尺寸越大,可存储的信息越大
			qrcodeHandler.setQrcodeVersion(size);
			// 获得内容的字节数组,设置编码格式
			byte[] contentBytes = content.getBytes("utf-8");
			// 图片尺寸
			// int imgSize = 67 + 12 * (size - 1);
			int imgSize = 67 + 12 * (size - 1);

			// System.out.println(imgSize);

			bufImg = new BufferedImage(imgSize, imgSize,
					BufferedImage.TYPE_INT_RGB);
			Graphics2D gs = bufImg.createGraphics();
			// 设置背景颜色
			gs.setBackground(Color.WHITE);
			gs.clearRect(0, 0, imgSize, imgSize);

			// 设定图像颜色> BLACK
			gs.setColor(Color.BLACK);
			// 设置偏移量,不设置可能导致解析出错
			int pixoff = 2;
			// 输出内容> 二维码
			if (contentBytes.length > 0 && contentBytes.length < 800) {

				boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes);
				for (int i = 0; i < codeOut.length; i++) {
					for (int j = 0; j < codeOut.length; j++) {
						if (codeOut[j][i]) {
							gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
						}
					}
				}
			} else {
				throw new Exception("QRCode content bytes length = "
						+ contentBytes.length + " not in [0, 800].");
			}
			gs.dispose();
			bufImg.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bufImg;
	}

	/**
	 * 解析二维码(QRCode)
	 * 
	 * @param imgPath
	 *            图片路径
	 * @return
	 */
	public static String decoderQRCode(String imgPath) throws Exception {
		// QRCode 二维码图片的文件
		File imageFile = new File(imgPath);
		BufferedImage bufImg = null;
		String content = null;
		try {
			bufImg = ImageIO.read(imageFile);
			QRCodeDecoder decoder = new QRCodeDecoder();
			content = new String(decoder.decode(new TwoDimensionCodeImage(
					bufImg)), "utf-8");
		} catch (IOException e) {
			// System.out.println("Error: " + e.getMessage());
			// e.printStackTrace();
		} catch (DecodingFailedException dfe) {
			// System.out.println("Error: " + dfe.getMessage());
			// dfe.printStackTrace();
		}
		return content;
	}

	/**
	 * 解析二维码(QRCode)
	 * 
	 * @param input
	 *            输入流
	 * @return
	 */
	public static String decoderQRCode(InputStream input) {
		BufferedImage bufImg = null;
		String content = null;
		try {
			bufImg = ImageIO.read(input);
			QRCodeDecoder decoder = new QRCodeDecoder();
			content = new String(decoder.decode(new TwoDimensionCodeImage(
					bufImg)), "utf-8");
		} catch (IOException e) {
			System.out.println("Error: " + e.getMessage());
			e.printStackTrace();
		} catch (DecodingFailedException dfe) {
			System.out.println("Error: " + dfe.getMessage());
			dfe.printStackTrace();
		}
		return content;
	}

}

3.异常处理类

Exceptions.java

package util;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.http.HttpServletRequest;

/**
 * 关于异常的工具类.
 */
public class Exceptions {

	/**
	 * 将CheckedException转换为UncheckedException.
	 */
	public static RuntimeException unchecked(Exception e) {
		if (e instanceof RuntimeException) {
			return (RuntimeException) e;
		} else {
			return new RuntimeException(e);
		}
	}

	/**
	 * 将ErrorStack转化为String.
	 */
	public static String getStackTraceAsString(Throwable e) {
		if (e == null) {
			return "";
		}
		StringWriter stringWriter = new StringWriter();
		e.printStackTrace(new PrintWriter(stringWriter));
		return stringWriter.toString();
	}

	/**
	 * 判断异常是否由某些底层的异常引起.
	 */
	public static boolean isCausedBy(Exception ex,
			Class<? extends Exception>... causeExceptionClasses) {
		Throwable cause = ex.getCause();
		while (cause != null) {
			for (Class<? extends Exception> causeClass : causeExceptionClasses) {
				if (causeClass.isInstance(cause)) {
					return true;
				}
			}
			cause = cause.getCause();
		}
		return false;
	}

	/**
	 * 在request中获取异常类
	 * 
	 * @param request
	 * @return
	 */
	public static Throwable getThrowable(HttpServletRequest request) {
		Throwable ex = null;
		if (request.getAttribute("exception") != null) {
			ex = (Throwable) request.getAttribute("exception");
		} else if (request.getAttribute("javax.servlet.error.exception") != null) {
			ex = (Throwable) request
					.getAttribute("javax.servlet.error.exception");
		}
		return ex;
	}

}

4.实体类

Person.java

package test;

/**
 * 个人信息 实体类
 */
public class Person {
	// 仅用于演示效果,勿纠结细节(如字段类型、合理性等)
	private String name; // 姓名
	private String position; // 职位
	private String department; // 部门
	private String phone; // 电话
	private String email; // 邮箱
	private String address; // 地址
	private String url; // 官网

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPosition() {
		return position;
	}

	public void setPosition(String position) {
		this.position = position;
	}

	public String getDepartment() {
		return department;
	}

	public void setDepartment(String department) {
		this.department = department;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

}

5.功能实现类

StaffMain.java

package test;

import java.io.IOException;

import util.TwoDimensionCode;

public class StaffMain {
	public static void main(String[] args) throws IOException {

		Person person = new Person();
		person.setName("李四");
		person.setDepartment("销售部");
		person.setPosition("销售总监");
		person.setPhone("18888888888");
		person.setEmail("xxx@163.com");
		person.setAddress("北京市XX区XX大厦XX层XXX室");
		person.setUrl("www.xxxxxxxxx.cn");
		// 生成用户二维码
		String realPath = "L:/qrcode/";
		String name = person.getName() + ".png"; // 二维码的图片名
		String filePath = realPath + name; // 二维码路径
		String content = "BEGIN:VCARD\r\nVERSION:3.0";
		content += "\r\nN:" + person.getName();
		content += "\r\nTEL:" + person.getPhone();
		content += "\r\nEMAIL;TYPE=WORK:" + person.getEmail();
		content += "\r\nORG:" + person.getPosition();
		content += "\r\nTITLE:" + person.getDepartment();
		content += "\r\nADR;TYPE=WORK:" + person.getAddress();
		content += "\r\nEND:VCARD";
		System.out.println(content);
		TwoDimensionCode.encoderQRCode(content, filePath, "png");// 执行生成二维码
	}
}

6.控制台

在这里插入图片描述

7.执行效果

在这里插入图片描述

8.二维码扫描

在这里插入图片描述在这里插入图片描述在这里插入图片描述

总结

到此,该功能已实现,完整版代码,不方便下载的私信留邮箱,看到后回复

标签:段值,扫码,return,String,vCard,content,通讯录,import,public
来源: https://blog.csdn.net/super_DuoLa/article/details/116697473

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有