求delphi中16进制byte数组与中文的互换,请帖出详细代码

kshmilyhui 2011-07-21 04:11:54
如题,新手学习 谢谢,比如说匕首 转出来就应该是D8 B0 CA D7
...全文
1080 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
lhs203203 2011-07-31
  • 打赏
  • 举报
回复
个人觉得楼主你那个问题要分2步
1 先要找出代表汉子的数字 然后分割成2位十六进制数
2 存放在Bytes中
Seamour 2011-07-23
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 funxu 的回复:]
另外像Move(ByteArray[0], Result[1], Count);中Result[1]这样的语句在2010中已不再支持,唉,没办法
tbytes bytes:= bytesof(str) ansi编码
[/Quote]
怎么不支持了?别胡说八道误导人了

既然是2010,而且知道 encoding,那就没必要再用 AnsiString 了,直接使用明确编码的 string 类型:
type GBKString = type AnsiString(936);

还是先 SetString,然后再显式转换成 string 就可以了。
Seamour 2011-07-23
  • 打赏
  • 举报
回复
先转成前面我给出的 GBKString 再进行运算
kshmilyhui 2011-07-23
  • 打赏
  • 举报
回复
function myStrtoHex(s: string): string;
var tmpstr: string;
i: integer;
begin
tmpstr := '';
for i := 1 to length(s) do
begin
tmpstr := tmpstr + inttoHex(ord(s[i]), 2);
end;
result := tmpstr;
end;

这段代码在delphi07中转出来就正常,放在2010里转换出来就不对了 悲剧
蓝色光芒 2011-07-22
  • 打赏
  • 举报
回复
System.pas

function _NewAnsiString(length: Longint): Pointer;
asm
TEST EAX,EAX
JLE @@null
PUSH EAX
ADD EAX,rOff+2 // one or two nulls (Ansi/Wide)
AND EAX, not 1 // round up to even length
PUSH EAX
CALL _GetMem
POP EDX // actual allocated length (>= 2)
MOV word ptr [EAX+EDX-2],0 // double null terminator
ADD EAX,rOff
POP EDX // requested string length
MOV [EAX-skew].StrRec.length,EDX
MOV [EAX-skew].StrRec.refCnt,1
RET
@@null:
XOR EAX,EAX
end;

看看System._NewAnsiString是怎么建立字符串了内存的关系的

你的程序,如果这样运行
for i:=0 to 1000000 do
ByteArrayToStr(@tmp,4);
结果可想而知

如果函数返回值是String,上面的循环就没问题如
for i:=0 to 1000000 do
IntToStr(i);

function ByteArrayToStr(src:pointer; srclen:dword):AnsiString;
但是改成这样显然你的程序不对.


cngst 2011-07-22
  • 打赏
  • 举报
回复
以前竟然不知有一个SetString,哎!基础太欠缺,今天又有收获。

另外,对string,以前并不知道前面还要有8个字节来记录引用和长度,后来只是看到某人提到一句,前面有引用记数和长度,也没查过函义,只是根据名词,推断,估计当记数为0时,delphi会自动释放。

所以我的函数将计数设置为0,应该是正确的。

刚才测试了一下,结果也证明我是正确的。
funxu 2011-07-22
  • 打赏
  • 举报
回复
受教~受教~
cngst 2011-07-22
  • 打赏
  • 举报
回复
另外,之前不清楚新版的delphi中string又加了4个字节(我用的是delphi2007),所以刚才的新版函数也不能用于新版的delphi了,如果要兼容各个版本的delphi,应该改为使用rOff\skew
Seamour 2011-07-22
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 funxu 的回复:]
这我倒真没试过,忘了在哪里看到过个帖子内存申请不要太大,但也没说具体有多大,目前测试过最多的记录是一个200多M的pchar,貌似没问题,以前用byte数组操作一般没超过255,稍微大点是多大?可否赐教
[/Quote]

错误的原因是栈溢出,自然跟栈差不多大就够了

procedure foo(x: array of Byte);
begin
end.

procedure bar;
var a: array of Byte;
begin
SetLength(a, 1024*1024);
foo(a);
end;

默认情况下栈 1M,这段代码就足够挂掉了
cngst 2011-07-22
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 seamour 的回复:]

引用 10 楼 cngst 的回复:
至于内存泄露,使用FastMM4没发现有泄露。

引用 12 楼 cngst 的回复:
所以我的函数将计数设置为0,应该是正确的。
刚才测试了一下,结果也证明我是正确的。

先说一下引用计数的问题,昨天没过大脑就直接认为 string(APointer) 的转换不会增加引用计数。刚才仔细考虑了一下,从 string 的模型来看,这个操作应该会增……
[/Quote]

delphi内存管理,受教了,谢谢!

至于push ecx/pop ecx,我平时的习惯来说,还是需要的,如果是使用pascal调用一个函数肯定是不需要保护的(eax,ecx,edx都不需要)。

但我平时习惯在汇编中调用函数,而被调用的函数也是自己用汇编写的,本来正常的情况下,应该是由调用者保存的,但由于平时习惯了,在被调用函数中保存/恢复,这样在调用时就省事了。
babydog01 2011-07-22
  • 打赏
  • 举报
回复
虚心向高手们学习,谢谢你们的争吵,有争吵才有真理,但没有伤害感情,我们很感激。。。。。
cngst 2011-07-22
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 kiboisme 的回复:]

System.pas
Delphi(Pascal) code

function _NewAnsiString(length: Longint): Pointer;
asm
TEST EAX,EAX
JLE @@null
PUSH EAX
ADD EAX,rOff+2 ……
[/Quote]


明白了,现将函数改成这样,应该可以了:



function ByteArrayToStr(src:pointer; srclen:dword):AnsiString;
asm
push ecx
push eax
push edx
push edx
mov eax,ecx
call system.@lstrClr
pop edx
mov eax,edx
add eax,10
and eax,not 1
push eax
call system.@getmem
mov dword ptr[eax],1
pop edx
mov word ptr[eax+edx-2],0
pop ecx
mov [eax+4],ecx
lea edx,[eax+8]
pop eax
push edx
call move
pop eax
pop ecx
mov [ecx],eax
end;


funxu 2011-07-22
  • 打赏
  • 举报
回复
采用pchar分次读入流里,然后生成一个新文件
funxu 2011-07-22
  • 打赏
  • 举报
回复
更正,那个200M的不是pchar是文件
funxu 2011-07-22
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 seamour 的回复:]
这种声明只要传的 ByteArray 稍微大点儿,进函数就直接挂了。
[/Quote]

这我倒真没试过,忘了在哪里看到过个帖子内存申请不要太大,但也没说具体有多大,目前测试过最多的记录是一个200多M的pchar,貌似没问题,以前用byte数组操作一般没超过255,稍微大点是多大?可否赐教
Seamour 2011-07-22
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 cngst 的回复:]
至于内存泄露,使用FastMM4没发现有泄露。
[/Quote]
[Quote=引用 12 楼 cngst 的回复:]
所以我的函数将计数设置为0,应该是正确的。
刚才测试了一下,结果也证明我是正确的。
[/Quote]
先说一下引用计数的问题,昨天没过大脑就直接认为 string(APointer) 的转换不会增加引用计数。刚才仔细考虑了一下,从 string 的模型来看,这个操作应该会增加引用计数的,所以字符串会得到释放。

但这里实际上还有另外一个问题,因为昨天认为字符串不会有机会得到释放,这个问题也就不会发生,所以就没提。System.Sys****Mem 系列内存管理函数,是不会经过 System.MemoryManager 的;而 rtl 封装的字符串操作是通过 GetMem/FreeMem 完成的,而这个系列对内存的操作是通过调用 MemoryManager 完成的。换句话说,你前面用 SysGetMem 分配 string 内存会导致,string 的分配与销毁使用的可能不是相同的内存管理器,这个操作可能会引发异常。
把 SysGetMem 换成 GetMem 就不会引发这个问题。

现在的情况说明,你用的是 D2006/D2007 或者使用 FastMM 替换了 rtl 内存管理器的其它更低版本。因为2009及更新版本字符串前增加了4字节内容,你还在用8字节显然版本很老;如果 rtl 还在使用老的 borland 内存管理器版本,由于引用了 fastmm,它们使用的策略不同,所以一旦释放就应该会引发异常。至于现在的情况为什么没出现错误,由于我没研究过 fastmm 的内存分配和释放过程,现在也不打算研究,所以这里也不好说什么。现在也不想开 ide 调,没准打开 FullDebug,fastmm 就会报告这个问题。

没出现问题是你的不幸,要是没碰到我,这个错误的知识就会被你当作正确,当你以后碰到由它引发的错误,也不会想到是它的原因。

[Quote=引用 10 楼 cngst 的回复:]
push ecx/pop ecx,对delphi来说确实没必要,但这是我的习惯性的东西,我对任何寄存器在使用前都有备份的习惯。
[/Quote]
ecx 需不需要保护跟 delphi 就没关系,你习惯如此说明从一开始就不知道哪些是不需要保护的。
funxu 2011-07-22
  • 打赏
  • 举报
回复
对了,还有
str:=stringof(bytes) Tbytes 为ansi编码
funxu 2011-07-22
  • 打赏
  • 举报
回复
另外像Move(ByteArray[0], Result[1], Count);中Result[1]这样的语句在2010中已不再支持,唉,没办法
tbytes bytes:= bytesof(str) ansi编码
funxu 2011-07-22
  • 打赏
  • 举报
回复
delphi2010使用unicode编码,很多字符串函数使用的是字符数不是字节数,LZ可以将string替换为ansistring
kshmilyhui 2011-07-22
  • 打赏
  • 举报
回复
而且我用的是delphi2010 楼上的很多方法转出来都是空的
加载更多回复(12)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧