[分享]实用工具五:几个很有用的有关string转换的函数 ( 积分: 0 )

  • 主题发起人 主题发起人 Another_eYes
  • 开始时间 开始时间
A

Another_eYes

Unregistered / Unconfirmed
GUEST, unregistred user!
unit减肥了一番,去掉了一些不常用的函数,下面只导出了三个函数:

StrToHex:将一个string转成一串16进制数字字符串(中间空格分隔)
BufToHex:将一块Buffer转成一串16进制数字字符串(中间空格分隔)

MakeBuffer: 将多块任意类型数据打包成一个string, 特比适用于socket编程中生成发送包。
其实说支持任意类型有点说大话了(绕个弯可以做到支持任意类型), MakeBuffer能直接辨认的类型是:Char, Boolean, Extended, Currency, WideChar, Integer, Int64, PChar, PWideChar, WideString, ShortString, string, Object和Pointer。
其中Pointer有特殊格式要求,即Pointer参数的后一个参数必须是Integer并且其值=这个Pointer指向内存的具体大小。
另外shortstring参数存入最终结果中的格式有一点区别,它包含起始的那个长度字节(即shortstring[0])而其他的如string, widestring, pchar, pwidechar都不包含长度信息也不包括结尾的#0。
特别需要注意一点的是variant类型和Interface类型参数尽管可以认出,不过保存的具体数据可能不对。
MakeBuffer函数不能辨认TClass类型,遇到TClass类型参数时将直接丢弃。
对record类的参数不能直接传,可以传record变量的地址+record的长度两个参数.
另:要注意不要将地址转成pchar传递,因为内部处理时对pchar只取到第一个#0为止,需要转成Pointer类型+一个长度变量一起传递。
对TDateTime型也不能正确辨认,可以使用地址+长度方式传递,也可以将其转成Extended类型传递(毕竟TDateTime就是Double, 要注意的是转成Extended的话保存不是8字节而是10字节了)
要存word的话可以强制类型转换成WideChar进行传递(只有WideChar才保存2字节数据,其他类型最少都是1字节或4字节的)
使用示例:
var
a: array [0..5] of TPoint;
s1: string[5];
s2: widestring;
s: string;
begin
.... // 赋值
s := makebuffer([4, // Integer
s1, // shortstring
True, // boolean
WideChar($100), // WideChar, Word
@a, sizeof(a), // pointer+len
s2, // widestring
#9, // char, byte
'123456789' // string
]);
....
end;



unit ExtStrFuncs;

interface

uses
SysUtils;

function StrToHex(s: string): string;
function BufToHex(const buf; Len: Integer): string;
function MakeBuffer(Bufs: array of const): string;

implementation

function StrToHex(s: string): string;
var
i: Integer;
begin
result := '';
for i := 1 to length(s) do
result := result + inttohex(byte(s), 2)+' ';
end;

function BufToHex(const buf; Len: Integer): string;
var
i: Integer;
p: PByte;
begin
result := '';
p := @Buf;
for i := 1 to Len do
begin
result := result + inttohex(p^, 2)+' ';
inc(p);
end;
end;

function MakeBuffer(Bufs: array of const): string;
var
i: Integer;
len, l: Integer;
Flg, IsP: Boolean;

begin
{ calc result length }
Flg := false;
len := 0;
l := 0;
for i := 0 to high(bufs) do
with bufs do
begin
if flg then
begin
if VType = vtInteger then
l := VInteger
else
l := Length(String(Bufs[i-1].VPointer)) and $FFFFFFFC - 4;
inc(len, l);
flg := false;
if VType = vtInteger then continue;
end;
case VType of
vtInteger : l := 4;
vtBoolean ,
vtChar : l := 1;
vtExtended : l := sizeof(Extended);
vtString : l := byte(VString^[0])+1;
vtPointer : Flg := True;
vtPChar : l := strlen(VPChar);
vtObject : l := VObject.InstanceSize;
vtWideChar : l := 2;
vtPWideChar : l := length(VPWideChar) * 2;
vtAnsiString : l := length(string(VAnsiString));
vtCurrency : l := sizeof(Currency);
vtVariant : l := length(string(VVariant^));
vtInterface : l := length(string(VInterface^));
vtWidestring : l := length(WideString(VWideString)) * 2;
vtInt64 : l := sizeof(Int64);
else
l := 0;
end;
if not flg and (l > 0) then
inc(len, l);
end;
if Flg then
begin
l := length(string(Bufs[high(bufs)].VPointer)) and $FFFFFFFC - 4;
inc(Len, l);
end;

setlength(result, len);

{ copy buffers }
len := 0;
flg := false;
//l := 0;
for i := 0 to high(bufs) do
with Bufs do
begin
IsP := True;
if Flg then
begin
if VType = vtInteger then
l := VInteger
else l := length(string(Bufs[i-1].VPointer)) and $FFFFFFFC - 4;
if l > 0 then
begin
move(Bufs[i-1].VPointer^, result[Len+1], l);
inc(Len, l);
end;
Flg := false;
if VType = vtInteger then continue;
end;
case VType of
vtInteger :
begin
l := 4;
isp := false;
end;
vtBoolean ,
vtChar :
begin
l := 1;
isp := false;
end;
vtExtended : l := sizeof(Extended);
vtString : l := byte(VString^[0])+1;
vtPointer : Flg := True;
vtPChar : l := strlen(VPChar);
vtObject : l := VObject.InstanceSize;
vtWideChar :
begin
l := 2;
isp := false;
end;
vtPWideChar : l := length(VPWideChar) * 2;
vtAnsiString : l := length(string(VAnsiString));
vtCurrency : l := sizeof(Currency);
vtVariant : l := length(string(VVariant^));
vtInterface : l := length(string(VInterface^));
vtWidestring : l := length(WideString(VWideString)) * 2;
vtInt64 : l := sizeof(Int64);
else
l := 0;
end;
if not flg and (l > 0) then
begin
if isp then
move(VPointer^, result[len+1], l)
else
move(VInteger, result[len+1], l);
inc(len, l);
end;
end;
if Flg then
begin
l := length(string(Bufs[high(bufs)].VPointer)) and $FFFFFFFC - 4;
move(Bufs[high(bufs)].VPointer^, result[Len+1], l);
end;
end;

end.
 
unit减肥了一番,去掉了一些不常用的函数,下面只导出了三个函数:

StrToHex:将一个string转成一串16进制数字字符串(中间空格分隔)
BufToHex:将一块Buffer转成一串16进制数字字符串(中间空格分隔)

MakeBuffer: 将多块任意类型数据打包成一个string, 特比适用于socket编程中生成发送包。
其实说支持任意类型有点说大话了(绕个弯可以做到支持任意类型), MakeBuffer能直接辨认的类型是:Char, Boolean, Extended, Currency, WideChar, Integer, Int64, PChar, PWideChar, WideString, ShortString, string, Object和Pointer。
其中Pointer有特殊格式要求,即Pointer参数的后一个参数必须是Integer并且其值=这个Pointer指向内存的具体大小。
另外shortstring参数存入最终结果中的格式有一点区别,它包含起始的那个长度字节(即shortstring[0])而其他的如string, widestring, pchar, pwidechar都不包含长度信息也不包括结尾的#0。
特别需要注意一点的是variant类型和Interface类型参数尽管可以认出,不过保存的具体数据可能不对。
MakeBuffer函数不能辨认TClass类型,遇到TClass类型参数时将直接丢弃。
对record类的参数不能直接传,可以传record变量的地址+record的长度两个参数.
另:要注意不要将地址转成pchar传递,因为内部处理时对pchar只取到第一个#0为止,需要转成Pointer类型+一个长度变量一起传递。
对TDateTime型也不能正确辨认,可以使用地址+长度方式传递,也可以将其转成Extended类型传递(毕竟TDateTime就是Double, 要注意的是转成Extended的话保存不是8字节而是10字节了)
要存word的话可以强制类型转换成WideChar进行传递(只有WideChar才保存2字节数据,其他类型最少都是1字节或4字节的)
使用示例:
var
a: array [0..5] of TPoint;
s1: string[5];
s2: widestring;
s: string;
begin
.... // 赋值
s := makebuffer([4, // Integer
s1, // shortstring
True, // boolean
WideChar($100), // WideChar, Word
@a, sizeof(a), // pointer+len
s2, // widestring
#9, // char, byte
'123456789' // string
]);
....
end;



unit ExtStrFuncs;

interface

uses
SysUtils;

function StrToHex(s: string): string;
function BufToHex(const buf; Len: Integer): string;
function MakeBuffer(Bufs: array of const): string;

implementation

function StrToHex(s: string): string;
var
i: Integer;
begin
result := '';
for i := 1 to length(s) do
result := result + inttohex(byte(s), 2)+' ';
end;

function BufToHex(const buf; Len: Integer): string;
var
i: Integer;
p: PByte;
begin
result := '';
p := @Buf;
for i := 1 to Len do
begin
result := result + inttohex(p^, 2)+' ';
inc(p);
end;
end;

function MakeBuffer(Bufs: array of const): string;
var
i: Integer;
len, l: Integer;
Flg, IsP: Boolean;

begin
{ calc result length }
Flg := false;
len := 0;
l := 0;
for i := 0 to high(bufs) do
with bufs do
begin
if flg then
begin
if VType = vtInteger then
l := VInteger
else
l := Length(String(Bufs[i-1].VPointer)) and $FFFFFFFC - 4;
inc(len, l);
flg := false;
if VType = vtInteger then continue;
end;
case VType of
vtInteger : l := 4;
vtBoolean ,
vtChar : l := 1;
vtExtended : l := sizeof(Extended);
vtString : l := byte(VString^[0])+1;
vtPointer : Flg := True;
vtPChar : l := strlen(VPChar);
vtObject : l := VObject.InstanceSize;
vtWideChar : l := 2;
vtPWideChar : l := length(VPWideChar) * 2;
vtAnsiString : l := length(string(VAnsiString));
vtCurrency : l := sizeof(Currency);
vtVariant : l := length(string(VVariant^));
vtInterface : l := length(string(VInterface^));
vtWidestring : l := length(WideString(VWideString)) * 2;
vtInt64 : l := sizeof(Int64);
else
l := 0;
end;
if not flg and (l > 0) then
inc(len, l);
end;
if Flg then
begin
l := length(string(Bufs[high(bufs)].VPointer)) and $FFFFFFFC - 4;
inc(Len, l);
end;

setlength(result, len);

{ copy buffers }
len := 0;
flg := false;
//l := 0;
for i := 0 to high(bufs) do
with Bufs do
begin
IsP := True;
if Flg then
begin
if VType = vtInteger then
l := VInteger
else l := length(string(Bufs[i-1].VPointer)) and $FFFFFFFC - 4;
if l > 0 then
begin
move(Bufs[i-1].VPointer^, result[Len+1], l);
inc(Len, l);
end;
Flg := false;
if VType = vtInteger then continue;
end;
case VType of
vtInteger :
begin
l := 4;
isp := false;
end;
vtBoolean ,
vtChar :
begin
l := 1;
isp := false;
end;
vtExtended : l := sizeof(Extended);
vtString : l := byte(VString^[0])+1;
vtPointer : Flg := True;
vtPChar : l := strlen(VPChar);
vtObject : l := VObject.InstanceSize;
vtWideChar :
begin
l := 2;
isp := false;
end;
vtPWideChar : l := length(VPWideChar) * 2;
vtAnsiString : l := length(string(VAnsiString));
vtCurrency : l := sizeof(Currency);
vtVariant : l := length(string(VVariant^));
vtInterface : l := length(string(VInterface^));
vtWidestring : l := length(WideString(VWideString)) * 2;
vtInt64 : l := sizeof(Int64);
else
l := 0;
end;
if not flg and (l > 0) then
begin
if isp then
move(VPointer^, result[len+1], l)
else
move(VInteger, result[len+1], l);
inc(len, l);
end;
end;
if Flg then
begin
l := length(string(Bufs[high(bufs)].VPointer)) and $FFFFFFFC - 4;
move(Bufs[high(bufs)].VPointer^, result[Len+1], l);
end;
end;

end.
 
想不通,Another_eYes这么多分,居然发0分贴,想卡点油都不行。。。。。。。
收藏先[:D]
 
不需要用这个,帮你顶吧
 

Similar threads

I
回复
0
查看
430
import
I
I
回复
0
查看
531
import
I
I
回复
0
查看
630
import
I
后退
顶部