-
2021-01-29 15:57:13
文件二维码(FileQRCode) – 通过动态二维码传输文件(手机互传,手机电脑互传),
文件二维码 是一组传输工具,它通过动态二维码来传输数据,理论大小不限,但越大越慢,小文件是可以接受的。
手机端:扫描接受完文件,默认保存在app的私有目录,其他功能:有文件编辑,浏览功能,普通二维码的生成与识别。
下载地址:https://download.csdn.net/download/fencer911/19853228 (第二版 解决了一版的bug) 文件存放在/Android/data/niu.fencer.tool.qrcode/files/Documents下
以下是手机端的示意图:
本想做的更好的,放应用市场太难了,放弃了!!!!!浪费了太多时间!!!!
电脑端:下载地址 https://download.csdn.net/download/fencer911/14946341
识别时无响应的解决办法:识别时间拉长一点,一定要在先生成后识别(不要对无二维画面做识别)
不能运行的解决办法:要下载 Visual C++ Redistributable Packages for Visual Studio 2013
https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=407841.普通的二维码生成与识别
2.文件二维码的生成发送,接受与识别 (远程桌面与当前主机)
3.手机到电脑,电脑到手机间的信息传递(通过摄像头) 安卓有同名软件:文件二维码APP(手机间传输大小不限)源码已不再开放。
更多相关内容 -
一个简单的二维码传输技术(Python语言)
2021-04-23 13:49:21二维码传输技术目录1、界面设计2、二维码生成二维码读取和显示二维码识别插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建...程序效果
这是一个利用二维码传输文件的Python程序,目前能传输最大1MB的txt文件。
1、界面设计
本项目利用的是tkinter+opencv。主界面设计成这样,基于此界面可以完成文件的上传、打开、删除、分类、搜索和二维码的生成。
没有生成的时候就放一个默认的静态图片
读取gif并输出。
直接读gif的信息,比如duration延迟,然后逐帧读取图片,放在一个数组内,用after函数循环播放。
可以生成最多6个二维码,这里生成了一个。
2、识别效果
如果只针对单张二维码进行扫描,100KB以内的文件时间还能够忍受,文件超过100KB,在经过一个简单的数学运算后会发现需要很长的时间。所以我准备同时放多张二维码进行扫描。
但这种方式有很明显的尾部效应。前90%的数据和后10%的数据速度存在明显的差异。
这是由于多张二维码识别由于二维码畸变(也就是摄像头位置放的不准)存在很大的几率发生丢帧,这种丢帧是完全随机的。如果丢帧了只能靠下一轮识别再去识别一轮。后10%的数据并不是文件的后10%而是尚未识别的10%。
图很明显在最后会掉速
平均速度基本可以保持在4-6KB/s。程序设计
这一部分主要讲程序当中一些细节,因为代码没写注释,我会在这个部分一步步补充,不愿看可以跳转到最后看整的代码。
主要有以下部分
- 按钮的显示与变化;
这里是重新编写了按钮类,bind可以绑定按钮的各种变化,这里使用的是ENTER和LEAVE,对应鼠标的悬停和离开。
command对应点击后跳转的函数。
class Bottun_spe: def __init__(self, where, text, width, height, com=None, row=None, cod=None): def on_enter(e): myButton['background'] = '#EDF6FB' myButton['fg'] = 'blue' def on_leave(e): myButton['background'] = '#FAFAFA' myButton['fg'] = 'black' self.data = [] myButton = tk.Button(where, width=width, height=height, bg='#FAFAFA', relief=FLAT, text=text, command=com) myButton.bind("<Enter>", on_enter) myButton.bind("<Leave>", on_leave) myButton.grid(row=row, column=cod)
- 列表栏的显示
创建Listbox,用insert函数插入元素。yscrollbar是滚动条,绑定在Listbox上。
yscrollbar = tk.Scrollbar(self.initface_right_button) yscrollbar.pack(side=tk.RIGHT, fill=tk.Y) theLB = Listbox(self.initface_right_button, yscrollcommand=yscrollbar.set, width=120, height=28) theLB.pack() yscrollbar.config(command=theLB.yview) for i in os.listdir(path_data): number = number + 1 if i.find(txt) > 0: theLB.insert(END, i)
这一段是利用bind绑定菜单,点击后会弹出菜单。
theLB.bind('<Double-Button-1>', CallOn) def CallOn(event): menu = Menu(theLB, tearoff=0) menu.add_command(label="打开", command=lambda: Call1On(event)) menu.add_separator() menu.add_command(label="生成", command=lambda: Call2On(event)) menu.add_separator() menu.add_command(label="删除", command=lambda: Call3On(event)) menu.post(event.x_root, event.y_root)
- 文件上传和删除
文件上传,用filedialog选择文件,再里也有shutil将文件复制到工作空间内。刷新。
def load(self): try: old_path = tk.filedialog.askopenfilename() print(old_path) shutil.copy(old_path, os.getcwd() + "/test") showinfo("提示", "上传成功") self.flash() except IOError: print("Error: 没有找到文件或读取文件失败")
文件删除直接用os.remove删除然后刷新即可。
- 文件查询
bind绑定回车,在文本框内输入文字后回车跳转到搜索函数。
u = StringVar() u.set("搜索") ent = tk.Entry(self.initface_right, textvariable=u) ent.grid(row=2, column=4) ent.bind("<Return>", search) ent.bind("<Button-1>", entry_del)
1、二维码生成
生成二维码使用的是qrcode库,生成图片保存,然后制作为GIF。
生成二维码:def create_base64(struct_pic): # 加密模块 file_path = struct_pic[1] try: file = open(file_path, 'rb') print(file.name) except Exception: print("非法退出") with open("word/生成.txt", 'w+') as f: f.write("当前生成二维码的文件是:" + file_path + "\n二维码版本是:" + str(struct_pic[2]) + "\n二维码纠错速率是:" + str(struct_pic[3])) file_content = file.read() file_content = base64.b64encode(file_content).decode() number = 1 del_file() maxDataBitsArray = [0, 152, 272, 440, 640, 864, 1088, 1248, 1552, 1856, 2192, 2592, 2960, 3424, 3688, 4184, 4712, 5176, 5768, 6360, 6888, 7456, 8048, 8752, 9392, 10208, 10960, 11744, 12248, 13048, 13880, 14744, 15640, 16568, 17528, 18448, 19472, 20528, 21616, 22496, 23648] ver_number = int(maxDataBitsArray[int(struct_pic[2])]/8 - 25) print(ver_number) while number <= math.ceil(len(file_content) / ver_number): print(number) print(len(str(number).zfill(8) + str(math.ceil(len(file_content) / ver_number)).zfill(8) + str(file_content[(number-1)*ver_number : number*ver_number]))) print(math.ceil(len(file_content) / ver_number)) make_qrcode(struct_pic, str(number).zfill(8) + str(math.ceil(len(file_content) / ver_number)).zfill(8) + str(file_content[(number-1)*ver_number : number*ver_number]), "pic/Test" + str(number) + ".png") number = number + 1 image_list= [] frames = [] i = 1 num = 0 max = int(struct_pic[4]) for row in range(max): image_list.append([]) columns = [] i = 1 while i<=number-1: if i%max== row: columns.append(i) i=i+1 for column in columns: image_list[row].append('pic/Test' + str(column) + '.png') print(image_list) print("List") num = 0 while num < max: frames.append([]) for image_name in image_list[num]: frames[num].append(imageio.imread(image_name)) num = num + 1 print("image") print(frames) num = 0 while num < max: imageio.mimsave('pic/new'+str(num+1)+'.gif', frames[num], 'GIF', duration=float(struct_pic[3])) num = num + 1 print(num) showinfo("提示", "生成成功") with open("word/生成.txt", 'w+') as f: txt = " 生成的文件 : "+str(struct_pic[1])+"\n 二维码大小版本 : "+str(struct_pic[2])+"\n 二维码循环速率 : "+str(struct_pic[3]) f.write(txt)
2、二维码读取和显示
class MyLabel(Label): # 播放GIF def __init__(self, master, filename='pic.gif', number=1): if number == 1: size = 500 elif number == 2: size = 400 elif number == 3: size = 280 elif number == 6: size = 250 if os.path.exists(filename): im = Image.open(filename) else: im = Image.open('pic.gif') seq = [] try: while 1: seq.append(im.copy()) im.seek(len(seq)) except EOFError: pass # we're done try: self.delay = im.info['duration'] except KeyError: self.delay = 100 print(self.delay) first = seq[0].convert('RGBA') first = first.resize((size, size), Image.ANTIALIAS) self.frames = [ImageTk.PhotoImage(first)] Label.__init__(self, master) temp = seq[0] for image in seq[1:]: temp.paste(image) frame = temp.convert('RGBA') frame = frame.resize((size, size), Image.ANTIALIAS) self.frames.append(ImageTk.PhotoImage(frame)) self.idx = 0 global ticks ticks = time.ctime() print(ticks) self.cancel = self.after(self.delay, self.play) # after循环 def play(self): self.config(image=self.frames[self.idx]) self.idx += 1 global ticks if self.idx == len(self.frames): self.idx = 0 self.cancel = self.after(self.delay, self.play)
3、二维码识别
程序提供了两种识别的方式。
二维码识别是基于opencv对摄像头或视频的逐帧读取,我们直接对读取的帧利用pyzbar进行识别。程序
程序已经放在Gitee中,目前程序还不成熟,后续会持续更新。链接: Gitee__二维码传输技术.
- 按钮的显示与变化;
-
使用二维码实现文件分享
2018-07-30 11:11:47有时候,想要把电脑上的文件快速便捷的传输到手机,就可以用到这个工具了。 使用方法示例: 1、准备需要传输到手机的文件 注:1.2版本不仅支持对文件的一键分享,还支持文件夹的一键分享。 2、选中文件或...有时候,想要把电脑上的文件快速便捷的传输到手机,就可以用到这个工具了。
使用方法示例:
1、准备需要传输到手机的文件
注:1.2版本不仅支持对文件的一键分享,还支持文件夹的一键分享。
2、选中文件或文件夹,右键属性,点击QrShare
3、弹出二维窗口,用手机扫描二维码下载文件
提示:此时鼠标的粘贴板已经粘贴了二维码的内容,直接发给小伙伴,分析文件吧。
4、手机下载文件结果
下载时,服务端可以强制断开分享,也可以等待客户端下载完成后自动关闭分享;同时,客户端同时在线下载数量不能超过10个。
当分享的文件类型是图片格式(png,jpg,gif,bmp,ico等)和网页格式(html,htm)时,浏览器会对其数据进行页面显示。即:直接显示图片而不是弹出下载图片(可通过另存为下载图片);直接显示html内容而不是提示下载文件。其他格式文件,直接提示下载文件。
直接显示出图片。
注意:需要安装jdk1.6+,手机和电脑必须在同一局域网内,除非电脑部署在外网环境。
程序分享:
先说说使用的技术:
- 使用zxing生成二维码
- jdk swing的基础知识
- jdk httpServer
- jdk zip压缩文件
- 如何将可jar转换成可执行的exe文件
- 修改windos注册表,实现右键菜单
代码如下:
QrShare.java
package com.kancy.httpserver; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Hashtable; import java.util.Map; import java.util.Random; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.swing.ImageIcon; import javax.swing.JOptionPane; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; /** * 使用二维码实现文件分享 * @author kancy * @see 2018/07/30 */ public class QrShare { public static void main(String[] arg) { try { // 1.获取文件路径,获取失败时,系统自动关闭 File file = acquireAndCheckDownloadFile(arg); // 2.启动服务 startJavaHttpFileServer(file); // 3.显示二维码 String title = " 扫码下载文件("+ file.getName() +")"; String content = "http://" + InetAddress.getLocalHost().getHostAddress().toString() + ":" + HTTP_PORT + "/download"+ getFileSuffix(file) + "?id=" + System.currentTimeMillis(); setSysClipboardText(content); createQrImageFrame(title, content); waitDelay(Setting.getProperty("wait_delay_time", Setting.wait_delay_time)); // 4.提示是否强制关闭服务 int unAccomplishedSize = accomplishMap.size(); if(unAccomplishedSize > 0){ int result = JOptionPane.showConfirmDialog(null, "目前存在"+ unAccomplishedSize+"个客户端正在下载,是否强制关闭服务?","系统关闭提示",2); if(result == 0){ closeService(); System.exit(0); } } // 5.系统退出 waitAndExitSystem(0); } catch (Exception e) { alertAndExit("系统异常:" + e.getMessage()); } } /** * 检查和获取文件 * @param arg * @return */ private static File acquireAndCheckDownloadFile(String[] arg) { if (arg == null || arg.length <= 0) { alertAndExit("请指定下载的文件全路径!"); } // 获取本地文件 String filePath = arg[0]; File file = new File(filePath); if(!file.exists()){ alertAndExit("文件不存在!"); } // 如果是目录,先进行zip打包 if(file.isDirectory()){ filePath = packZipFile(file); file = new File(filePath); } if (!file.isFile()) { alertAndExit("文件不存在!"); } return file; } /** * 压缩目录 * @param dir * @return */ private static String packZipFile(File dir) { String zipFilePath = dir.getParent().replace("\\", "/") + "/" + dir.getName() + ".zip"; try { ZipUtils.zip(zipFilePath, dir); } catch (Exception e) { e.printStackTrace(); alertAndExit("压缩目录异常:\n"+e.getMessage()); } return zipFilePath; } /** * 使用随机端口 * @return */ private static int getRandomPort() { Random random = new Random(); String value = ""; while(true){ int num = random.nextInt(10); // 确保端口小于65535 if(value.length() == 0 && (num == 0 || num > 5)){ continue; } value += num; if(value.length() == 5){ break; } } return Integer.parseInt(value); } /** * 提示并且退出 * @param msg */ private static void alertAndExit(String msg) { JOptionPane.showMessageDialog(null, msg); System.exit(0); } /** * 关闭服务 */ private static void closeService() { if(!threadPool.isShutdown()){ threadPool.shutdown(); } server.stop(0); } /** * 关闭系统 * @param i * @throws InterruptedException */ private static void waitAndExitSystem(int i) { int unAccomplishedSize = accomplishMap.size(); if(unAccomplishedSize == 0){ closeService(); System.out.println("系统即将关闭!"); System.exit(0); }else{ System.out.println("存在"+unAccomplishedSize+"个活动链接,请等待..."); waitDelay(1000); waitAndExitSystem(i); } } /** * 睡眠 * @param l */ private static void waitDelay(long l) { try { Thread.sleep(l); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 将字符串复制到剪切板。 */ private static void setSysClipboardText(String writeMe) { Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); Transferable tText = new StringSelection(writeMe); clip.setContents(tText, null); } /** * 依赖 com.google.zxing core-3.0.0.jar * * @param title * @param content * @throws WriterException */ private static void createQrImageFrame(String title, String content) throws WriterException { Map<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); hints.put(EncodeHintType.CHARACTER_SET, Setting.default_charset); BitMatrix matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, 300, 300, hints); int width = matrix.getWidth(); int height = matrix.getHeight(); BufferedImage image = new BufferedImage(width, height, 1); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, matrix.get(x, y) ? -16777216 : -1); } } ImageIcon icon = new ImageIcon(image); JOptionPane.showMessageDialog(null, "", title, 1, icon); } //----------------------------------------------------------------------------- // jdk HttpServer 提供http服务 //----------------------------------------------------------------------------- private static final int MAX_POOL_NUM = Setting.http_pool_size > 0 ? Setting.http_pool_size : 10; private static final int HTTP_PORT = Setting.http_port > 0 ? Setting.http_port : getRandomPort(); private static HttpServer server; private static ExecutorService threadPool = Executors.newFixedThreadPool(MAX_POOL_NUM);// 只允许10个用户同时下载 private static Map<String, Boolean> accomplishMap = new Hashtable<String, Boolean>();// 防止未下载完成,关闭服务 /** * 开启http服务 * @param file * @throws Exception */ private static void startJavaHttpFileServer(File file) throws Exception { server = HttpServer.create(new InetSocketAddress(HTTP_PORT), 0); server.setExecutor(threadPool); server.createContext("/download"+ getFileSuffix(file), new FileServerHandler(file)); Thread httpServiceThread = new Thread(new Runnable() { @Override public void run() { server.start(); System.out.println("服务启动成功!"); } }); httpServiceThread.start(); } /** * 获取文件后缀 * @param file * @return */ private static String getFileSuffix(File file) { String name = file.getName(); String fileSuffix = ""; if(name.contains(".")){ fileSuffix = name.substring(name.lastIndexOf("."), name.length()); } return fileSuffix.trim().toLowerCase(); } /** * 文件下载静态处理器 * @author kancy */ static class FileServerHandler implements HttpHandler { private File file; public FileServerHandler(File file) { this.file = file; } @Override public void handle(HttpExchange exchange) throws IOException { if(accomplishMap.size() >= MAX_POOL_NUM){ String msg = "服务队列已满,请稍候下载!"; exchange.sendResponseHeaders(200, 0); exchange.getResponseBody().write(msg.getBytes(Setting.default_charset)); exchange.getResponseBody().flush(); exchange.getResponseBody().close(); return; } String handlerId = UUID.randomUUID().toString(); try { // 开始处理 accomplishMap.put(handlerId, false); OutputStream os = exchange.getResponseBody(); FileInputStream in = new FileInputStream(file); // 判断文件的类型 // 1.图片类型/网页类型 直接显示在浏览器,通过另存为下载 // 3.其他类型 下载模式 String fileSuffix = getFileSuffix(file); String contentType = Constants.getContentType(fileSuffix); // 设置下载头 if(Constants.CONTENT_TYPE_DEFAULT.equals(contentType) || (!Setting.show_static_resource && !Constants.CONTENT_TYPE_DEFAULT.equals(contentType) )){ exchange.getResponseHeaders().add("Content-Disposition", "attachment;filename=\"" + new String(file.getName().getBytes(Setting.default_charset), Setting.content_disposition_charset) + "\""); } exchange.getResponseHeaders().add("Content-Type", contentType); exchange.getResponseHeaders().add("Content-Length", String.valueOf(file.length())); // 发送响应 exchange.sendResponseHeaders(200, file.length()); // 写文件 writeAndClose(os, in); } finally { // 处理完成 accomplishMap.remove(handlerId); } } /** * 写文件并且关闭流 * @param os * @param in * @throws IOException */ private static void writeAndClose(OutputStream os, FileInputStream in) throws IOException { try { byte[] buf = new byte[1024]; int size = -1; while ((size = in.read(buf)) != -1) { os.write(buf, 0, size); os.flush(); } } finally{ if(os != null){ os.close(); } if(in != null){ in.close(); } } } } }
ZipUtils.java
package com.kancy.httpserver; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; /** * ZIP 工具 * * @author kancy * @see 2018/07/30 */ public class ZipUtils { public static void unzip(String srcZip, String outPath) { long startTime = System.currentTimeMillis(); try { ZipInputStream Zin = new ZipInputStream(new FileInputStream(srcZip));// 输入源zip路径 BufferedInputStream Bin = new BufferedInputStream(Zin); File Fout = null; ZipEntry entry; try { while ((entry = Zin.getNextEntry()) != null && !entry.isDirectory()) { Fout = new File(outPath, entry.getName()); if (!Fout.exists()) { (new File(Fout.getParent())).mkdirs(); } FileOutputStream out = new FileOutputStream(Fout); BufferedOutputStream Bout = new BufferedOutputStream(out); int b; while ((b = Bin.read()) != -1) { Bout.write(b); } Bout.close(); out.close(); System.out.println(Fout + "解压成功"); } Bin.close(); Zin.close(); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println("耗费时间: " + (endTime - startTime) + " ms"); } public static void zip(String zipFileName, File inputFile) throws Exception { System.out.println("压缩中..."); File file = new File(zipFileName); if (!file.exists()) file.createNewFile(); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(file)); BufferedOutputStream bo = new BufferedOutputStream(out); zip(out, inputFile, inputFile.getName(), bo); bo.close(); out.close(); // 输出流关闭 System.out.println("压缩完成"); } public static void zip(String zipFileName, String... filePaths) throws Exception { System.out.println("压缩中..."); File file = new File(zipFileName); if (!file.exists()) file.createNewFile(); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(file)); BufferedOutputStream bo = new BufferedOutputStream(out); for (int i = 0; i < filePaths.length; i++) { File inputFile = new File(filePaths[i]); zip(out, inputFile, inputFile.getName(), bo); } bo.close(); out.close(); System.out.println("压缩完成"); } private static void zip(ZipOutputStream out, File f, String base, BufferedOutputStream bo) throws Exception { // 方法重载 if (f.isDirectory()) { File[] fl = f.listFiles(); if (fl.length == 0) { out.putNextEntry(new ZipEntry(base + "/")); // 创建zip压缩进入点base System.out.println(base + "/"); } for (int i = 0; i < fl.length; i++) { zip(out, fl[i], base + "/" + fl[i].getName(), bo); // 递归遍历子文件夹 } } else { out.putNextEntry(new ZipEntry(base)); // 创建zip压缩进入点base System.out.println(base); FileInputStream in = new FileInputStream(f); BufferedInputStream bi = new BufferedInputStream(in); int b; while ((b = bi.read()) != -1) { bo.write(b); // 将字节流写入当前zip目录 } bi.close(); in.close(); // 输入流关闭 } } }
Setting.java
package com.kancy.httpserver; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Properties; /** * 系统设置 * @author kancy * */ public class Setting { /** * 是否显示图片和网页资源 */ public static boolean show_static_resource = true; /** * 采用固定的端口设置 */ public static int http_port = 0; /** * 线程池大小设置,同时下载最大数量控制 */ public static int http_pool_size = 0; /** * 延迟自动关闭系统,时间单位毫秒 */ public static long wait_delay_time = 1L; /** * 默认编码 */ public static String default_charset = Constants.CHARACTER_UTF8; /** * content_disposition编码 */ public static String content_disposition_charset = Constants.CHARACTER_ISO8859_1; //---------------------------------------------------------------------------- // setting end //----------------------------------------------------------------------------- private static String configpath = System.getProperty("user.home").replace("\\", "/").concat("/").concat("QrShare/config.ini"); private volatile static Properties setting = new Properties(); public static String getProperty(String key) { return setting.getProperty(key); } public static String getProperty(String key, String defaultValue) { return setting.getProperty(key, defaultValue); } public static int getProperty(String key, int defaultValue) { return Integer.parseInt(setting.getProperty(key, String.valueOf(defaultValue))); } public static long getProperty(String key, long defaultValue) { return Long.parseLong(setting.getProperty(key, String.valueOf(defaultValue))); } public static boolean getProperty(String key, boolean defaultValue) { return "true".equalsIgnoreCase(setting.getProperty(key, String.valueOf(defaultValue))); } public static void setProperty(String key, String value) { setting.setProperty(key, value); storeSetting(); } private static void storeSetting() { OutputStream fos = null; try { fos = new FileOutputStream(configpath);// 加载读取文件流 setting.store(fos, "QrShare Config"); } catch (Exception e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 初始化设置 */ static{ init(); // 取值 show_static_resource = getProperty("show_static_resource", show_static_resource); wait_delay_time = getProperty("wait_delay_time", wait_delay_time); http_port = getProperty("http_port", http_port); http_pool_size = getProperty("http_pool_size", http_pool_size); default_charset = getProperty("default_charset", default_charset); content_disposition_charset = getProperty("content_disposition_charset", content_disposition_charset); } private static void initDefaultConfig() { setting.setProperty("default_charset", default_charset); setting.setProperty("wait_delay_time", String.valueOf(wait_delay_time)); setting.setProperty("http_port", String.valueOf(http_port)); setting.setProperty("http_pool_size", String.valueOf(http_pool_size)); setting.setProperty("show_static_resource", String.valueOf(show_static_resource)); setting.setProperty("content_disposition_charset", content_disposition_charset); storeSetting(); } private static void init() { FileInputStream fis = null; try { File file = new File(configpath); if(!file.getParentFile().exists() && !file.getParentFile().isDirectory()){ file.getParentFile().mkdirs(); } if (!(file.exists() && file.isFile())) { file.createNewFile(); initDefaultConfig(); } file.setReadable(true); file.setWritable(true); fis = new FileInputStream(configpath); setting.load(fis); } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
Constants.java
package com.kancy.httpserver; import java.util.Properties; /** * 常量 * @author kancy * */ public class Constants { public static final String CHARACTER_UTF8 = "UTF-8"; public static final String CHARACTER_GBK = "GBK"; public static final String CHARACTER_ISO8859_1 = "ISO8859-1"; //--------------------------------------------------------- // http://tool.oschina.net/commons //--------------------------------------------------------- public static final String CONTENT_TYPE_IMAGE = "image/jpeg"; public static final String CONTENT_TYPE_GIF = "image/gif"; public static final String CONTENT_TYPE_PNG = "image/png"; public static final String CONTENT_TYPE_ICO= "image/x-icon"; public static final String CONTENT_TYPE_JPG = "image/jpeg"; public static final String CONTENT_TYPE_JPEG = "image/jpeg"; public static final String CONTENT_TYPE_BMP = "image/jpeg"; public static final String CONTENT_TYPE_HTML = "text/html"; public static final String CONTENT_TYPE_DEFAULT = "application/octet-stream"; private static Properties staticResourceContentTypes = new Properties(); static{ staticResourceContentTypes.setProperty(".html", CONTENT_TYPE_HTML); staticResourceContentTypes.setProperty(".htm", CONTENT_TYPE_HTML); staticResourceContentTypes.setProperty(".gif", CONTENT_TYPE_GIF); staticResourceContentTypes.setProperty(".png", CONTENT_TYPE_PNG); staticResourceContentTypes.setProperty(".ico", CONTENT_TYPE_ICO); staticResourceContentTypes.setProperty(".jpeg", CONTENT_TYPE_JPG); staticResourceContentTypes.setProperty(".jpg", CONTENT_TYPE_JPEG); staticResourceContentTypes.setProperty(".bmp", CONTENT_TYPE_BMP); } public static String getContentType(String fileSuffix){ assert fileSuffix != null; return staticResourceContentTypes.getProperty(fileSuffix.trim().toLowerCase(), CONTENT_TYPE_DEFAULT); } }
将jar转换成exe文件:
这里不做教程,有兴趣可以去了解 exe4j :http://www.softpedia.com/get/Authoring-tools/Setup-creators/exe4j.shtml
添加右键菜单:
安装:
reg add "HKEY_CLASSES_ROOT\*\shell\QrShare\command" /ve /d "\"%~dp0\QrShare.exe\" \"%%1\"" /f
reg add "HKEY_CLASSES_ROOT\Directory\shell\QrShare\command" /ve /d "\"%~dp0\QrShare.exe\" \"%%1\"" /f
卸载:
reg delete "HKEY_CLASSES_ROOT\*\shell\QrShare" /f
reg delete "HKEY_CLASSES_ROOT\Directory\shell\QrShare" /f
无法运行说明:
如果遇到以下错误,请更换32版本的QrShare.exe,直接覆盖,名称改为QrShare.exe
免费下载链接:https://pan.baidu.com/s/1hdVmGj1rVrOkq7zdUUxDWg 密码:2uxa
修改记录:
version1.1
1.文件路径带有空格问题修复
下载地址:https://download.csdn.net/download/qq_25166683/10572340
version1.2
1.添加文件夹分享
下载地址:https://download.csdn.net/download/qq_25166683/10572845
version1.3
1.添加设置功能
2.图片和网页可以直接显示,而不是下载,但可以通过另存为下载
3.微信可以支持直接下载和图片的查看
4.部分优化 (其中:软件包体积减半,要的就是轻便小)下载地址:https://download.csdn.net/download/qq_25166683/10574889
version 4.0
中间版本直接忽略吧,最新版本4.0.0 ~
- 二维码分享文件
- 鼠标右键一键分享
- 多文件自动打包
- 静态资源渲染(json,html,image)
- 突破内网传输网速
- 权限控制 (4.x)
- 授权码
- 人工授权
- 黑名单
- 传输进度列表 (4.x)
- 传输记录列表 (4.x)
- 传输中断(4.x)
最新工具下载地址: https://download.csdn.net/download/qq_25166683/12384359(4.0.0版本)
IT视频教程集合:http://blog.sina.com.cn/s/blog_189450fd80102xp2f.html
原文地址:https://blog.csdn.net/qq_25166683/article/details/81281177
-
条形码、二维码、三维码解读
2022-01-23 12:39:13条形码、二维码、三维码解读1 条形码 Bar code1.1 释义1.2 识别原理1.3 编码原理1.4 示例:Code128编码2 二维码 QR code2.1 释义2.2 QR 码基本结构2.3 码元结构2.4 编码规范2.5 活码3 三维码 VR code3.1 释义3.2 ...条形码、二维码、三维码解读
元旦假期无聊做了个 手绘二维码工具,一直以来都只是用,却对其背后的信息不是很了解,恰逢周末,正好来学习记录一下。1 条形码 Bar code
1.1 释义
条形码(barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符。
但是光有这些标识,其实是没多大用途的;需要和条形码识别器进行配合,将标识中“包含”的数据读取出来,才能被用于后续的使用。
1.2 识别原理
条码符号是由反射率不同的“条”、“空”按照一定的编码规则组合起来的一种信息符号。由于条码符号中“条”、“空”对光线具有不同的反射率,从而使条码扫描器接受到强弱不同的反射光信号,相应地产生电位高低不同的电脉冲。而条码符号中“条”、“空”的宽度则决定电位高低不同的电脉冲信号的长短。
条形码扫描器利用光电元件将检测到的光信号转换成电信号,再将电信号通过模拟数字转换器转化为数字信号传输到计算机中处理。我们在生活中,最常见到的就是下面这种设备。
1.3 编码原理
有一篇文章介绍的很全面,这里不再赘述。
1.4 示例:Code128编码
空白+开始位 + [FNC1(为EAN128码时加)] + 数据位 + 检验位 + 结束位+空白
Code128检验位计算:(开始位对应的ID值 + 每位数据在整个数据中的位置×每位数据对应的ID值)% 103比如我要编码的内容是“TIGER”,则参照码表。
ID Code128A Code128B Code128C BandCode 编码值 0 SP SP 0 212222 bbsbbssbbss 31 ? ? 31 212321 bbsbbsssbbs 37 E E 37 132113 bsssbbsbsss 39 G G 39 211313 bbsbsssbsss 41 I I 41 231311 bbsssbsssbs 50 R R 50 231131 bbsssbsbbbs 52 T T 52 213311 bbsbbbsssbs 101 FNC4 CODEA CODEA 311141 bbbsbsbbbbs 102 FNC1 FNC1 FNC1 411131 bbbbsbsbbbs 103 StartA StartA StartA 211412 bbsbssssbss 104 StartB StartB StartB 211214 bbsbssbssss 105 StartC StartC StartC 211232 bbsbssbbbss 106 Stop Stop Stop 2331112 bbsssbbbsbsbb 则按照编码规则后可计算出数据位与校验位((103 + 52 + 241 + 339 + 437 + 550)%103)
开始位StartA(bbsbssssbss)+数据位[T(bbsbbbsssbs) I(bbsssbsssbs) G(bbsbsssbsss) E(bsssbbsbsss) R(bbsssbsbbbs)] + 检验位31(bbsbbsssbbs)+ 结束位Stop(bbsssbbbsbsbb)
即:
bbsbssssbssbbsbbbsssbsbbsssbsssbsbbsbsssbsssbsssbbsbsssbbsssbsbbbsbbsbbsssbbsbbsssbbbsbsbb
然后机器用这个字符串按像素排列,生成条形码
# pip install pySrtich import os from pystrich.code128 import Code128Encoder encoder=Code128Encoder('tiger') encoder.save("./1.png",bar_width=2) os.system("./1.png")
详细解读可点击链接
2 二维码 QR code
2.1 释义
二维码又称二维条码,常见的二维码为QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。
2.2 QR 码基本结构
在这张图中,不难看出:空白区、位置探测图形、矫正图形、定位图形都是固定的。校正图形:规格确定,校正图形的数量和位置也就确定了;
格式信息:表示改二维码的纠错级别,分为L、M、Q、H;版本信息:即二维码的规格,QR码符号共有40种规格的矩阵(一般为黑白色),从21x21(版本1),到177x177(版本40),每一版本符号比前一版本 每边增加4个模块。
数据区和纠错码字,这块才是我们所有信息的几种汇聚地。
详细结构可参考:链接
2.3 码元结构
可以看出,数据区数据越多,需要的码元空间也就越大,其版本也就越大,我们肉眼能看到的二维码也就越密集。版本最大到 40,也就是说,数据区可存储的数据空间是有限的,超过一定阈值,就无法生成二维码。
2.4 编码规范
第一步,计算出编码数据占据的空间大小,选择最佳版本坑位。
第二步,将数据字符转化成位流。
如需模式转化,则在新的模式段开始前加上模式指示符进行模式转换。在数据序列后面添加终止符。最终位流以8 位进行码字。
在此过程中,需根据修正精度,计算你纠错编码。
按需要将上面的码字序列分块,并根据纠错等级和分块的码字,产生纠错码字,并把纠错码字加入到数据码字序列后面,成为一个新的序列。第三步,填充数据到指定位置,生成二维码。
序列顺序如:如:D1, D12, D23, D35, D2, D13, D24, D36, … D11, D22, D33, D45, D34, D46, E1, E23,E45, E67, E2, E24, E46, E68,…
示例
数据可以按照一种模式进行编码,以便进行更高效的解码,例如:对数据:01234567编码(版本1-H),
1)分组:012 345 67
2)转成二进制:012→0000001100 (即8+4)
345→0101011001
67 →1000011
3)转成序列:0000001100 0101011001 1000011
4)字符数 转成二进制:8→0000001000
5)加入模式指示符(上图数字)0001:0001 0000001000 0000001100 0101011001 1000011
对于字母、中文、日文等只是分组的方式、模式等内容有所区别。基本方法是一致的2.5 活码
活码说白了就是二维码内套二维码,外层二维码不会变化,但是经由外部二维码识别到的内容,可以随意更换。
二维码很好用,我自己在公司内有一套专属工具箱(《泰戈尔的工具箱》),里面呢有一系列扫码预览工具,号称“APP 内全场景落地页预览神器”。其就是建立在二维码之上。用的时候绝大多数场景都没啥问题,但是有一些情况下,由于编码跳转链接太过冗长,会导致数据量超出了二维码能承载的上限。
这就导致没办法直接生成二维码去“预览跳转”了。结合市面上常见的“活码”技术,针对这个数据承载量有限的问题,我也有了一套针对性解决方案。
那就是“重定向”(仅支持端内跳转形式的 scheme 来生成二维码)。
比如来看个例子:
生成二维码“活码”
手机与电脑链接至同一台 WiFi 设备下,扫这个码。
可以发现成功 redirect。
我生成的码命名是“http://192.168.0.104:8080/redirect”, 结果扫码后却是"https://blog.csdn.net/marksinoberg"。
这就是“活码”的其中一个应用,目前很好的解决了我在公司内遇到的二维码过长无法生成问题。
不难看出,“活码”可应用的方向多,但受限也比较多,具体场景具体分析吧。
3 三维码 VR code
3.1 释义
三维码, [1] 英文名称VR Code,VR全称Visual Recognition(视觉识别),由创始人陈绳旭 [2] 重新定义标识为“三维码”,并在全球范围内申请相关知识产权保护,其中包括商标。三维码相较于二维码具有更大的信息容量、相同的识别便易性和较好的安全性。其编码方式是先将文本编译一串二进制数字,然后通过特定的算法并结合图片整体的色彩内容,将该二进制数字串与图像信息编码为一组可以通过特定规则解读的阵列。并且该图像阵列除了可以被机器设备读取以外,仅用人眼辨识也可以获取到部分乃至全部文本信息。
3.2 拓展
对三维码我也只是略有耳闻,没有具体了解,有兴趣的可自查,这里不做记录了。
-
Java生成四种格式的二维码
2019-01-29 09:28:22基于谷歌zxing实现的生成二维码工具类。可生成纯二维码;带Logo二维码;带文字二维码;带Logo带文字二维码 pom文件引用 <!-- zxing --> <dependency> <groupId>com.google.zxing</... -
二维码检测定位
2021-07-27 13:10:58条码 条码分为一维条码、二维条码和三维条码。 一维条码(Bar Code) 一维条码是由一组粗细不同、黑白(或彩色)相间...二维条码简称为二维码,是用某站特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间 -
unity 传输图片到本地服务器并生成二维码
2019-12-06 16:00:44unity 传输图片到本地服务器并生成二维码 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本... -
Qt实现 二维码打印功能
2018-02-10 16:24:091,利用 qrencode 第三方库 生成二维码,并通过Qt printer调用打印机 打印条码 或者二维码。 2,经过和同事几天的研究,浪费了一筐 条码之后。终于实现了基本功能,一些关键细节分享出来。 (1),打印机设置,... -
美化二维码
2020-05-02 16:50:50二维码内容长度不作控制 大多数互联网技术使用到二维码生成,都是使用开源的包生成,输入字符信息,即可生成一张包含此字符信息的黑白二维码图片: 上面有两个二维码图片,扫码结果都是访问到同个页面,... -
微信小程序生成带参二维码——并通过扫码获取二维码的参数
2019-10-09 15:52:18注意:保证当前小程序要有线上版本 ...要转换的这个url必须要在微信公众平台配置了扫普通链接二维码打开小程序,如下图: 测试连接是开发人员测试用的,跳转至测试版本的小程序,如果,转换的url不是... -
二维码的容量有多大?
2022-04-19 09:27:59二维码的最大容量取决于主流扫码设备的分辨能力。(看大白话部分,请直接看最后一段) ...(注意这里的M是指像素点数量,不是图片的文件大小)解决大信息量生成二维码的办法之一是生成“高端”二维码——活码,『通过 -
二进制数据图片(bit-data-map): 一种通过图片的形式传递数据信息的方式
2021-02-25 12:17:03二进制数据图片 前言 最近公司那台终端电脑的粘贴功能坏了, 连接远程想从里面拿一个文件出来, 试了好多种方法不顶用, 远程终端开了一堆程序也不能随便重启远程终端, 最终是关了一大堆不必要的应用, 又重启了下... -
条形码、二维码的区别和组成结构介绍
2021-01-19 16:42:27条形码(一维码)和二维码主要是作为物品的标识来使用的。条形码主要应用在商品标识、防伪、医药监管、超市收银等场合,二维码可以包含更多的信息,像网址、文字、图片等等,甚至是一首诗,一篇文章等,在网络时代... -
二维码生成【前端,后端】
2021-01-08 18:19:16二维码生成,可以在后端生成图片,存储在服务器,然后把虚拟路径返回到前端,也可以把数据传输到前端,通过前端框架生成在线二维码,在前端生成二维码不占用内存,但是网络原因会影响显示。 一、后端: String ... -
浅析二维码基本原理
2020-10-21 16:08:01自动识别技术就是针对这类需求发展起来,分为三部分:信息封装、信息传输和信息识别。信息封装是指通过对物体的直观信息进行抽象,将信息转化为可编码的文字、图像等形式。然后通过数据编码对原始数据进 -
常用二维码简介
2020-05-07 11:23:50code128码(条形码) CODE128码是广泛应用在企业内部管理、生产流程... 符号大小根据输入数据量自动调整。 TBarCode V8.1: 输入数据始终被分析,并自动选择适当的编码模式。 模式切换按要求完成,以产生最有效的编码。 -
Android使用Socket(Tcp/Udp)协议进行数据传输(传输大文件)
2019-10-29 08:09:22建立连接,形成传输数据的通道 在连接中进行大数据量传输 通过三次握手完成连接,是可靠协议 必须建立连接,效率稍微低点 二. UDP(协议): 将数据及源和目的封装在数据包中,不需要建立连接 每个数据包的大小限制在... -
51单片机二维码识别
2019-07-23 10:05:39现在在做一个硬件项目,主要是用“高端的”51单片机连一个摄像头完成二维码识别的问题。 目录: 一、解决方案 二、详细分析 一、解决方案: 现在的需求是:给出二维码(可能存在图像偏移、旋转等问题),输出... -
生成二维码,扫描二维码,二维码预览三件套。uQRCode、uni.scanCode、uni.previewImage
2021-10-09 11:11:38生成二维码,扫描二维码,二维码预览三件套。uQRCode、uni.scanCode、uni.previewImage 一、生成二维码 使用插件:uQRCode(在uniapp插件市场下载引入) 将uqrcode.js保存在公用工具的文件夹内容,本项目中在common ... -
Python二维码生成器
2020-07-11 11:58:42二维码是我们生活中非常常用的东西,几乎无处不在,你可以通过二维码支付,传输数据,传输文本等。但想要生成自己的二维码又非常麻烦,需要用别人的软件,这些很多不可靠甚至有病毒,所以作为技术人员的我们还是要靠... -
2021SC@SDUSC-Zxing(十二):二维码的解析(Decode)及纠错有关算法介绍
2021-11-02 22:12:45本篇文章介绍如何将二维码中存储的0、1二进制数据转换为我们需要的文本信息。涉及到流程分析、纠错算法分析、笔算解码过程等 -
Java 生成二维码上传第三方平台(详解),看完这一篇你就懂了
2021-12-23 11:50:33gson ...core 3.1.0 ...生成二维码并且上传: package org.ewhl.common.utils; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -
Django中使用qrcode生成二维码
2019-09-24 15:11:28二维码简称 QR Code(Quick Response Code),学名为快速响应矩阵码,是二维条码的一种,由日本的 Denso Wave 公司于1994 年发明。现随着智能手机的普及,已广泛应用于平常生活中,例如商品信息查询、社交好友互动、... -
使用iOS原生组件生成二维码和扫描识别二维码
2018-09-06 14:56:35官方文档描述CIFilter类,是一个操作一个或多个图片来生成一个新的图片数据的图片处理器;CIFilter可以看做是一个滤镜,Apple提供了上百种的CIFilter,通过filterWithName:(NSString*)方法获取,CIFilter的种类可以... -
二维码门禁(基于微信小程序)
2020-05-23 20:12:14技术:二维码生成、二维码解码、http协议数据传输和接受、局域网使用、公网使用 微信小程序生成二维码代码 // pages/main/index.js var QR = require("../../utils/qrcode.js"); Page({ data: { -
基于MATLAB的条码二维码识别系统
2021-09-08 11:53:15基于MATLAB的条码二维码识别系统课题介绍 本设计研究的是基于数字图像处理的EAN-13条形码识别算法,通过工具平台MATLAB实现。其中图像处理部分是条码识别重要的前期工作,利用MATLAB强大的图象处理工具箱实现图像的... -
iphone新旧手机数据传输已取消_这个便捷的手机数据迁移工具,让数据搬家不再困难...
2020-10-22 21:53:55当然,有些手机本身也会内置换机功能,但也还是有许多第三方工具,诉求更简单快速的换机过程,是真正意义上能够帮你“摆脱束缚”的功能,从此数据搬家再也不需要数据线,更不需要直面超慢网速的等待。今天要介绍的:... -
通过web系统实现淘宝营销引流,小说或者视频上传之后自动生成二维码,通过二维码分享之后引入微信或者扣扣...
2021-12-13 09:08:02通过web系统实现淘宝营销引流,小说或者视频上传之后自动生成二维码,通过二维码分享之后引入微信或者扣扣加群,群满自动切换到下一个,以及数据统计分析和若干个小工具集成。 主要实现技术: 1、大文件视频分割上传... -
【二维码识别】基于matlab GUI 灰度+二值化+校正二维码生成与识别【含Matlab源码 635期】
2021-03-26 20:14:26基于matlab GUI 二维码生成与识别 二、源代码 function varargout = QRcode(varargin) % QRCODE MATLAB code for QRcode.fig % QRCODE, by itself, creates a new QRCODE or raises the existing % singleton*. % % ... -
二维码图像编码原理(字符编码:ASCII、UTF-8)
2021-07-26 00:35:49重要数据结构: //生成二维码 //将String转为char,再转为二进制字符串 char c=text.charAt(i); cbinary=Integer.toBinaryString(c); //将c变为二进制字符串 toBinaryString()形参本来为int型,char传入发生自动...