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

  • 一、功能
  • 二、vCard
    • 1.简单了解
    • 2.通讯录vcard关键字描述
    • 3.包含个人信息的vCard文件样例
  • 三、实现
    • 1.[所需jar包](https://download.csdn.net/download/super_DuoLa/18618235)
    • 2.二维码处理工具类
    • 3.异常处理类
    • 4.实体类
    • 5.功能实现类
    • 6.控制台
    • 7.执行效果
    • 8.二维码扫描
  • 总结

一、功能

利用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的电话号码表示方法,这种数据格式不能保证能被拨号程序直接使用,具体的数据格式解析应由拨号程序解决。
EMAIL 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文件样例

BEGIN:VCARD
VERSION:2.1    //协议版本
N:张三        //姓名
ORG:XXXXXX公司        //公司
TITLE:销售            //职位
TEL;WORK;VOICE:13111111111  //工作电话
TEL;HOME;VOICE:18888888888  //家庭电话
ADR;WORK:XXX区XX大厦           //工作地址
ADR;HOME:XXX区XXX小区      //家庭地址
EMAIL;PREF;INTERNET:123@XXX.com    //电子邮件
REV:202105112T195243Z  //最后一次的对本vCard对象的更新时间
END:VCARD

三、实现

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;}@Overridepublic int getHeight() {return bufImg.getHeight();}@Overridepublic int getPixel(int x, int y) {return bufImg.getRGB(x, y);}@Overridepublic 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);// 设定图像颜色> BLACKgs.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.二维码扫描


ps:二维码内存储的信息过多会导致二维码密度变大不易识别和整体面积变大,请谨慎选择存储内容

总结

到此,该功能已实现,完整版代码,不方便下载的私信留邮箱,看到后回复
PS:带有背景图的进阶版可参考:https://blog.csdn.net/super_DuoLa/article/details/116713322
创作不易,感谢支持,欢迎关注博主公众号,不定期进行干货分享

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

  1. 利用webSocket实现扫码登录PC端

    利用webSocket实现扫码登录PC端 业务需求 需求分析 效果演示 需求实现 业务流程图 业务流转图 代码实现 1.数据库设计 2.代码实现 1.web端代码 2. APP端代码 业务需求 在ap ...

  2. 开发实战分享|小程序扫码获取图书信息(内附详细教程)

    作者:祈澈姑娘 小程序扫码实现读取isbn,获取图书的各种信息 接触到云函数已经有一段时间了,之前一直在看api,现在自己跟着网络上的资料和视频学习,受到豆瓣读书系列的启发,决定用云函数做一个项目,获 ...

  3. 如何使用百数扫码实现高效信息录入与查询

    随着移动互联网的发展,扫码功能已经遍布我们日常生活的每一个角落,我们习惯用扫码支付.扫码读取信息.扫码登记等等.在更为广泛的行业领域,扫码功能的辅助能够帮助工作流程更便捷,实现更高效的数字化办公. 百 ...

  4. java_微信公众号扫码绑定个人信息(微信公众号场景值二维码的使用)

    看了一下网上关于公众号场景值二维码这方面的教程,基本上是微信官方开发文档的复制,没有具体实例.这里给出实例,并附加二维码url转文件流的方法. 思路: 1.后台传入个人信息保存,以个人信息的" ...

  5. 临时停车码-扫码拨号发信息HTML源码

    简介: 在外临时停车时,别人自己的爱车挡住别人车时需要挪车,要打给你电话的情况下,以下源码可实现扫码就能实现拨号和发短信! 网盘下载地址: http://kekewangLuo.net/m08E8ze ...

  6. 关于扫码签到统计信息,一键导出excel表

    1.首先进入草料二维码官网 2.微信扫码登录注册,登录成功后即可进入草料二维码后台(手机微信小程序也可以实时查看后台数据) 3.根据自己需要创建活动二维码(选择自己喜欢的模板,这里我们选择的是会议签到 ...

  7. 别找了,小程序实现isbn扫码获取图书信息2022最新可用(保姆级教程内附接口)

    关注.收藏.点赞3连

  8. 利用微信公共号的带参数二维码做(扫码登录)

    <script type="text/javascript">var t2 ='';$(function() {var rand = parseInt(Math.ran ...

  9. 移动端扫码上传数据信息

    随着移动端设备的普及,越来越多的工作环节我们可以借助移动设备进行.移动端扫码(支持二维码.条形码)上传数据信息可以很大程度上减少数据录入纰漏,便捷地联动相关数据,提高信息准确率. 在百数的多个解决方案 ...

最新文章

  1. Latex使用技巧01:改变数学公式字体的颜色
  2. containerd发布了CRI修复程序和CVE-2019-5736更新的runc
  3. MySQL中同一时候存在创建和上次更新时间戳字段解决方法浅析
  4. 计算机硬件人员专业知识技能,2017年江苏省职业学校技能大赛(计算机硬件)竞赛实施方案...
  5. leetCode-删除排序数组中的重复项
  6. webpack --- 在项目中使用React
  7. pcs层到mac层_mac层
  8. Office报错:错误代码:30015-6(-1)
  9. antd源码解读(6)- Affix
  10. Qt QChartView class
  11. CI/CD---使用新版云效流水线自动部署前端Vue项目
  12. python max函数_python的max函数的用法
  13. openocd Win10安装jlink->winUSB失败
  14. Odoo ERP 14 客户关系管理
  15. 手写操作系统之helloOS
  16. 压力传感器与51单片机C语言程序,51单片机压力传感器.docx
  17. C语言之tentative definition
  18. 微信自主出题,答题小程序开发,微信扫描二维码实现方法,扫二维码出试卷答题的软件!
  19. mysql优化手段——潭州学院
  20. java实现代码在线编译器-从零开发(三)Web并发环境下的线程安全

热门文章

  1. 认证Scrum Master 培训笔记(一)
  2. 云游昆大丽(七)——高原反应
  3. 什么是CMA?报考条件是什么?
  4. window服务器nginx无法启动
  5. 如何写好产品中的提示文案
  6. 前端开发——模块化(css模块化开发)
  7. 基于CNN对掌纹图片进行分类
  8. js的window.onscroll事件
  9. Docker基础(狂神说Docker课程笔记)
  10. 汉宁窗带通滤波应用matlab,可不可以帮我用MATLAB设计一个基于汉宁窗的FIR数字带通滤波器...