利用vCard实现扫码将个人信息保存到通讯录
作者:互联网
利用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] | 有些字段值可能只有一个“;” |
PHOTO | GIF,CGM,WMF,BMP,MET,PMB, DIB,PICT,TIFF,PS,PDF,JPEG, MPEG,MPEG2,AVI,QTIME | 字段值是图象数据或存储图象数据的文件名(包含URL路径) | 没有默认的字段类型,所以必须指定一种字段类型 |
BDAY | 无定义 | 字段值是出生日期的数据,有两种表示方法: 1)、基于ISO8601的基本格式:<month> 2)、基于ISO8601的扩展格式:--其中年是四个字符表示,月份和日期是两个字符表示 | |
ADR | DOM,INTL(),POSTAL(),PARCEL(), HOME,WORK() | 分7个字段表示地址的值: [Post Office Address];[Extended Address]; [Street];[Locality];[Region];[Postal code]; [Country] | 第一个字段基于X.500标准,其余字段基于X.520标准 |
LABEL | DOM,INTL(),POSTAL(),PARCEL(), HOME,WORK() | 字段值是一种日常表示地址的方法 | 基于X.520的普通名字语义规则 |
TEL | PREF,WORK,HOME,VOICE(*), FAX,MSG,CELL,PAGER,BBS,MODEM, CAR,ISDN,VIDEO | 字段值是基于X.520的电话号码表示方法,这种数据格式不能保证能被拨号程序直接使用,具体的数据格式解析应由拨号程序解决。 | |
AOL,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商务类型定义。 | |
LOGO | GIF,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] | |
SOUND | WAVE,PCM,AIFF | 字段值表示与本vCard对象有关的发音的声音数据,如该字段没有与其它字段分组,则该字段表示FN字段值的发音,字段值可以是二制的声音数据,也可以用其它单词表示的发音方法。 | 没有默认字段类型,当没有指定字段类型时,字段值为表示发音方法的文件或单词 |
URL | 无定义 | 字段值表示统一资源位置(Uniform Resource Locator),基于IETF RFC 1738定义。 | |
UID | 无定义 | 字段值表示本vCard对象的GUID号或本vCard对象将被更新的URL地址 | |
VERSION | 无定义 | 字段值表示本vCard对象的版本号 | 该字段是必选字段,在更早以前的版本是可选 |
KEY | X509,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