各种编码转换,是编程的一个基本技能,此技能与DELPHI无关,它是编程基础技能。
要研究编码转换,封包解包数据,我们得有一个工具,查看数据在内存中的样子。
~~~
// 研究字符的编码
// 要研究各种编码,最直接的办法就是在内存中去查看
// 将 B:=$AE 转换为 S:='AE'; 相当于 S:=IntToHex(B,2);
// 从 Addr 地址取 AByteCount 个 Byte ,将其转为 HexStr
function GenHexStr(Addr: Pointer; AByteCount: Integer): string;
const
Buff: array[0..15] of Char = (
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'); // 查表,空间换时间,很常见且实用
var
i: Integer;
S: PByte; // 源-指针
D: PChar; // 目的地-指针
Hi, Lo: Byte;
begin
SetLength(result, AByteCount * 2);
// 预设 Result 的长度与指针配合,可以避免 s:=s+'xx';这种低效率写法
S := Addr;
D := PChar(result);
for i := 0 to AByteCount - 1 do
begin
Hi := (S^ and $F0) shr 4; // 高位
D^ := Buff[Hi];
inc(D);
Lo := (S^ and $0F); // 低位
D^ := Buff[Lo];
inc(D);
inc(S);
end;
end;
~~~
有了这个函数,我们就可以查看内存中的数据了。此外,还得有一个逆函数,将HexStr转为会(变量)数据。
~~~
// 这两个函数,同时演示了指针的用法。
// 将 S:='AE'; 转换为 B:=$AE; 相当于 B:= StrToInt('$AE');
// 要确保 Dest 有足够的空间
procedure HexStrToBytes(AHexStr: string; Dest: Pointer);
var
i: Integer;
S: PChar; // 源指针
D: PByte; // 目的地指针
Hi, Lo: Char;
begin
S := PChar(AHexStr);
D := Dest;
for i := 0 to (Length(AHexStr) div 2) - 1 do
begin
Hi := S^;
if Hi in ['0'..'9'] then
Dec(Hi, 48) // '0' 的 asc 码是48
else if Hi in ['A'..'Z'] then
Dec(Hi, 55) // 'A' 的 asc 码是 65 , $A=10 所以减 55
else if Hi in ['a'..'z'] then
Dec(Hi, 87) // 'a' 的 asc 码是 97
else
raise Exception.Create('字串中有非Hex数字的字符:[' + Hi + ']');
// 异常是一种简洁的处理错误的手段。
// 如若不然的话,此处如何处理非 Hex 的字符呢?处理不了的问题,直接就引发异常。
inc(S);
Lo := S^;
if Lo in ['0'..'9'] then
Dec(Lo, 48) // '0' 的 asc 码是48
else if Lo in ['A'..'Z'] then
Dec(Lo, 55) // 'A' 的 asc 码是 65 , $A=10 所以减 55
else if Lo in ['a'..'z'] then
Dec(Lo, 87) // 'a' 的 asc 码是 97
else
raise Exception.Create('字串中有非Hex数字的字符:[' + Lo + ']');
D^ := (Ord(Hi) shl 4) + Ord(Lo);
inc(S);
inc(D);
end;
end;
~~~
用法,以查看Integer在内存中的状态为例:
~~~
procedure TForm1.Button3Click(Sender: TObject);
var
n: Integer;
sOut: string;
begin
n := $12AB34CD;
sOut := GenHexStr(@n, 4);
Memo1.Lines.Add('Hex Str:' + sOut);
// sOut='CD34AB12' ,明显有高低位换位
end;
~~~
本例由DELPHI 7 编写,程序中还有更多的数据类型在内存中的状态示例,如:ansiString, UnicodeString, Utf8String
您可以用此源码,研究一切数据在内存中的状态,永不被数据编码困扰。
[点击下载源码](https://www.jianguoyun.com/p/DZTz4BwQxMf4BRiR4Ds)
- 0.1 教程说明
- 0.2 delphi xe8 安装
- 0.2.2 XE 10.3.3 安装
- 0.3 delphi IDE 的非常必要的配置
- 0.4 调试中的异常处理
- 0.5 工程路径设置
- 0.6 开发工具界面切换成中文的问题
- 一、实用技巧
- 0.尝试为event取名叫伊文特
- 1.各种(变量)数据在内存中是什么样子的?
- 2
- 3
- 4.乱码问题
- 5
- 二、多线程
- 三、DLL相关
- 1.DLL中函数参数如何设计?
- 2.调用易语言DLL识别验证码
- 四、界面设计
- 1.关于解耦问题
- 2.登录功能设计
- 五、面向对象基础知识
- 1.窗口间传递值
- 3.避免又臭又长的裹脚布
- 2.扩展 TStringGrid , delphi 7 示例
- 六、初学者误区集锦
- 七 TList 集合
- 1.附加信息Pointer设计
- 2.用 TList 来建立组件间的联系
- 3.泛型 TList<T> 示例