明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 653|回复: 11

[函数] 纯算法实现base64编码解码

[复制链接]
发表于 2024-6-15 23:34 | 显示全部楼层 |阅读模式
本帖最后由 tryhi 于 2024-6-15 23:55 编辑

  1. (setq *base64lst* (vl-string->list "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))


  2. (defun try-lst-addlast (a lst)
  3.         (reverse(cons a (reverse lst)))
  4. )
  5. (defun try-string-div (str nn / m n r)
  6.         (setq n(strlen str)
  7.                 m(/ n nn)
  8.                 re(rem n nn)
  9.                 ci(if (zerop re)m (1+ m));循环次数
  10.                 r nil
  11.         )
  12.         (repeat ci
  13.                 (setq r(cons (substr str 1 nn) r)
  14.                         str (substr str (1+ nn))
  15.                 )
  16.                
  17.         )
  18.         (reverse r)
  19. )
  20. (defun try-lst-move-last (lst i)
  21.         (if (<= i 0)lst
  22.                 (progn
  23.                         (setq lst (reverse lst))
  24.                         (repeat i (setq lst (cdr lst)))
  25.                         (reverse lst)
  26.                 )
  27.         )
  28. )

  29. ;;十进制表编码为base64字符串(二进制的十进制表现)
  30. ;;实例:(try-base64<-lst10 '(65 66 67 68 69)) ;->"QUJDREU="
  31. (defun try-base64<-lst10 (hex10 / base64 bin binlong binlst lst10 n= remx st)
  32.         (setq remx (rem (length hex10)3))
  33.         (cond
  34.                 ((= remx 2)(setq hex10(try-lst-addlast 0 hex10)n= 1)) ;补齐到3字节
  35.                 ((= remx 1)(setq hex10(append hex10 '(0 0))n= 2)) ;补齐到3字节
  36.                 (T (setq n= 0))
  37.         )
  38.         
  39.         (setq
  40.                 bin(mapcar '(lambda(x)(sy-itoa x 2 8 48))hex10)
  41.                 binlong(apply 'strcat bin)
  42.                 binlong(substr binlong 1 (-(strlen binlong)(* n= 6))) ;删除多补的0
  43.                 binlst(try-string-div binlong 6);按6位长度取值,即3/4字节
  44.                 lst10(mapcar '(lambda(x)(sy-atoi x 2))binlst)
  45.                 st(mapcar '(lambda(x)(nth x *base64lst*))lst10)
  46.                 base64(vl-list->string st)
  47.         )
  48.         
  49.         (repeat n=
  50.                 (setq base64(strcat base64"="))
  51.         )
  52.         base64
  53. )

  54. ;;普通字符串编码为base64(ANSI编码)
  55. ;;实例:(try-base64<-str "ABCDE") ;->"QUJDREU="
  56. (defun try-base64<-str (str)
  57.         (try-base64<-lst10 (vl-string->list str))
  58. )

  59. ;;base64字符串解码为十进制表(二进制的十进制表现)
  60. ;;实例:(try-base64->lst10 "QUJDREU=") ;->(65 66 67 68 69)
  61. (defun try-base64->lst10 (base64 / bin binlong binlst lst lst10 mw n= tem wz)

  62.         (setq n=(cond
  63.                                                 ((wcmatch base64 "*==")2)
  64.                                                 ((wcmatch base64 "*=")1)
  65.                                                 (t 0)
  66.                                         ))
  67.         (setq mw(substr base64 1 (-(strlen base64)n=)))
  68.         (setq lst (vl-string->list mw)
  69.                 wz(mapcar '(lambda(x)(vl-position x *base64lst*))lst)
  70.                 bin(mapcar '(lambda(x)(sy-itoa x 2 6 48))wz)
  71.                 binlong(apply 'strcat bin)
  72.                 binlong(strcat binlong (sy-itoa 0 2 (* n= 6) 48))
  73.                 binlst(try-string-div binlong 8)
  74.                 ;len(length binlst)
  75.                 lst10(mapcar '(lambda(x)(sy-atoi x 2))binlst)
  76.         )
  77.         (try-lst-move-last lst10 n=)
  78.         
  79. )

  80. ;;base64字符串解码为普通字符串(ANSI编码)
  81. ;;实例:(try-base64->str "QUJDREU=") ;->"ABCDE"
  82. (defun try-base64->str (base64 / lst)
  83.         (setq lst(reverse(try-base64->lst10 base64)))
  84.         (if (zerop (car lst))(setq lst(cdr lst)));;去除末尾的0,兼容结尾无=的非标准base64
  85.         (if (zerop (car lst))(setq lst(cdr lst)));;去除末尾的0,兼容结尾无=的非标准base64
  86.         (vl-list->string (reverse lst))
  87. )

  88. ;;下面是使用例子,之所以分开为4个函数是因为不仅仅字符串可以用来编码,任何数据均可编码

  89. (setq 原始字符串 "今天的天气很nice12345")
  90. (princ (strcat"\n原始字符串为:"原始字符串))
  91. (setq 加密字符串(try-base64<-str 原始字符串))
  92. (princ (strcat"\n加密后为:"加密字符串))
  93. (setq 解码字符串(try-base64->str 加密字符串))
  94. (princ (strcat"\n解码后为:"解码字符串))
  95. (princ)





(注:由于CAD用的是ANSI编码,所以中文编码后很多在线解码平台是解不出来的,因为大多平台用的是UTF-8编码)


YmFzZTY0Ynl0cnloaQ==
此字符是用上面函数编码出来的,感兴趣的可以解出来看看,这是一个支付宝口令红包



为了图方便(也为了速度),二进制转换用了内部函数itoa跟atoi,需要加载内部函数fas,如果接受不了内部函数可以自己编写二进制与十进制转换函数代替文中的sy-itoa、sy-atoi







本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 2明经币 +2 金钱 +10 收起 理由
Bao_lai + 1 感谢海哥技术牛红包!
tigcat + 1 + 10 很给力!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2024-6-16 10:20 | 显示全部楼层
本帖最后由 dcl1214 于 2024-6-16 10:26 编辑

不需要转换为base64,我经常搞数据库,这个问题以前碰到过,后来发现微软系统自己能消化,不需要cad来处理,主要是cad处理大数据的时候,很慢的,所以,借助微软来处理,速度很快的
  1. (DEFUN $xmlhttp$ (lst)
  2.   (cond
  3.     ((and (= (getenv "zx-xmlhttp") "1")
  4.           (setq objHttp (vlax-create-object "Msxml2.XMLHTTP"))
  5.                                         ;有缓存速度快,用这个的时候,报文头里面如果有中文,服务器不会乱码
  6.      )
  7.      t
  8.     )
  9.     ((and (= (getenv "zx-xmlhttp") "2")
  10.           (setq objHttp (vlax-create-object "Microsoft.XMLHTTP"))
  11.                                         ;这个是2.0的
  12.      )
  13.      t
  14.     )
  15.     ((and (= (getenv "zx-xmlhttp") "3")
  16.           (setq objHttp (vlax-create-object "winhttp.winhttprequest.5.1"))
  17.                                         ;这个没用过,先记录这里
  18.      )
  19.      t
  20.     )
  21.     ((and (= (getenv "zx-xmlhttp") "4")
  22.           (setq objHttp (vlax-create-object "Msxml2.ServerXMLHTTP"))
  23.                                         ;没有缓存,报文头里面如果有中文服务器会乱码
  24.      )
  25.      t
  26.     )
  27.     (t
  28.      (setq objHttp (vlax-create-object "Msxml2.XMLHTTP"))
  29.                                         ;有缓存速度快,用这个的时候,报文头里面如果有中文,服务器不会乱码
  30.     )
  31.   )
  32.   objHttp
  33. )


如果你是搞远程通信,你可以用下面方法告知服务器,需要什么编码,如果要UTF-8的,你就告诉服务器即可

(if (not (assoc "Response-Charset" hs))
    (setq hs (cons (cons "Response-Charset" "UTF8") hs))
      )


可以通过下面语句获取远程服务器返回来的是啥字符集

(= (vl-catch-all-apply
           'vlax-invoke-method
           (list objHttp
             'getResponseHeader
             "Response-Charset"
           )
         )            ;获取Response-Charset头文件的值
         "UTF8"
          )

可以通过下面方法将远程服务器返回来的UTF8强转为ansi

(setq value-text
             (vl-catch-all-apply
               'vlax-get-property
               (list objHttp 'responseText)
             )
          )

这个语句依赖微软的对象
 楼主| 发表于 2024-6-17 09:46 | 显示全部楼层
dcl1214 发表于 2024-6-16 10:20
不需要转换为base64,我经常搞数据库,这个问题以前碰到过,后来发现微软系统自己能消化,不需要cad来处理 ...

并没有具体目的,只是单纯的研究一下base64编码的底层逻辑,其实是两年前不知道是谁在问(忘了),然后随手写了个半成品一直丢在桌面,直到今天清理桌面纠结删还是留,觉得写了一半代码弃之可惜就把它写完
发表于 2024-6-17 11:09 | 显示全部楼层
kozmosovia 发表于 2024-6-16 10:59
转base64的主要用处恐怕主要是为了能应对ANSI和UTF的编译。

据我遇到的,网络通信最多了
发表于 2024-6-16 06:12 | 显示全部楼层
厉害了,厉害了
发表于 2024-6-16 07:41 | 显示全部楼层
感谢大海大佬的分享!
发表于 2024-6-16 07:46 | 显示全部楼层

感谢大海大佬的分享!
发表于 2024-6-16 09:18 来自手机 | 显示全部楼层
大海大佬厉害!
发表于 2024-6-16 09:34 来自手机 | 显示全部楼层
这个厉害了,不知道速度怎么样。
发表于 2024-6-16 10:59 | 显示全部楼层
转base64的主要用处恐怕主要是为了能应对ANSI和UTF的编译。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-7-13 03:53 , Processed in 0.177707 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表