请教各位兄弟一个写法,过来看看吧~~^_^,有利无害呀~~~~~~~ ( 积分: 200 )

  • 主题发起人 主题发起人 不要踩我
  • 开始时间 开始时间

不要踩我

Unregistered / Unconfirmed
GUEST, unregistred user!
我写了一个格式,主要想用于文件补丁,可是不知道为什么老是不对,不知道错在哪里,希望能给我看看错在哪里

首先说一下文件格式
------------------------------------------------------------------------
XX XX XX XX XX AA AA AA AA BB BB CC CC .. CC .... ZZ ZZ ZZ ZZ
分析:
------------------------------------------------------------------------
XX XX XX XX XX 这五个是我标识的文件开头
------------------------------------------------------------------------
AA AA AA AA 这4个字节是我藏的地址
比如 00 00 01 02
那么我要写入另外一个文件的地址就是 $00000102.,所以编写时没有使用integer
------------------------------------------------------------------------
BB BB 从地址AAAAAAAA开始需要连续写入的数量
比如 03 04
那么我要写入另外一个文件的长度就是 $0304.
------------------------------------------------------------------------
CC CC .... 等到 BB BB这个数量后开始读取BBBB个长度的数组
------------------------------------------------------------------------
.... 然后在循环继续上面三步
------------------------------------------------------------------------
ZZ ZZ ZZ ZZ 我标识的文件结尾
------------------------------------------------------------------------

下面是我的代码:
代码:
function Hex2Int(HexStr: string): int64;
var
  RetVar: Int64;
  i: byte;
begin
  HexStr := UpperCase(HexStr);
  if HexStr[length(HexStr)] = 'H' then
    Delete(HexStr, length(HexStr), 1);
  RetVar := 0;

  for i := 1 to length(HexStr) do
  begin
    RetVar := RetVar shl 4;
    if HexStr[i] in ['0'..'9'] then
      RetVar := RetVar + (byte(HexStr[i]) - 48)
    else if HexStr[i] in ['A'..'F'] then
      RetVar := RetVar + (byte(HexStr[i]) - 55)
    else
    begin
      Retvar := 0;
      break;
    end;
  end;
  Result := RetVar;
end;

procedure TForm1.ApplyIPS(ips_file, bin_file: string);
var
  length, addr, k: integer;
  ips, bin: TFileStream;
  t: dword;
  PATCH: array[0..4] of char;
  temp: string;
  a_temp, count: array[0..3] of byte;
  buf: array[0..65535] of Byte;
begin
  ips := TFileStream.Create(ips_file, fmOpenRead);
  ips.Read(PATCH, 5);
  bin := TFileStream.Create(bin_file, fmOpenReadWrite);
  if PATCH = 'AAAAAA' then begin  //我文件开始的标识符AA AA AA AA AA 5个字节
    t := GetTickCount;
    while ips.Position < ips.Size - 3 do  //读到文件文件最后 ZZ ZZ ZZ ZZ标识符前
    begin
      ips.Read(a_temp, 4);
      //这里我不想直接使用integer,
      temp := IntToHex(a_temp[0], 2) + IntToHex(a_temp[1], 2) +
              IntToHex(a_temp[2], 2) + IntToHex(a_temp[3], 2); 
      addr := Hex2Int(temp);
      ips.Read(count, 2);
      length := Hex2Int(IntToHex(count[0], 2) + IntToHex(count[1], 2));
      ips.Read(buf, length);
      bin.Seek(addr, soFromBeginning);
      bin.Write(buf, length);
    end;
    Form1.caption := '用时:' + inttoStr((GetTickCount - t)) + ' ms';
  end else Form1.Caption :='错误';
  bin.Free;
  ips.Free;
end;
 
上帝呀,帮帮我吧,
万能的主呀,写一点代码给我呀.
 
-->if PATCH = 'AAAAAA' then begin //我文件开始的标识符AA AA AA AA AA 5个字节
这个地方的比较有没有问题?
你的ips_file文件是文本文件还是二进制文件?如果是文本文件,上面的那句不对!
关于地址,你存的是字符串'0102'还是0x0102?
 
二进制文件
0x0102
 
首先,如果存取二进制文件的话,有必要这样换来换去的吗?
temp := IntToHex(a_temp[0], 2) + IntToHex(a_temp[1], 2) +
IntToHex(a_temp[2], 2) + IntToHex(a_temp[3], 2);
addr := Hex2Int(temp);
ips.Read(count, 2);
length := Hex2Int(IntToHex(count[0], 2) + IntToHex(count[1], 2));
------------------------------------
addr := a_temp[0] shl 24 + a_temp[1] shl 16 + a_temp[2] shl 8 + a_temp[3];
ips.Read(count, 2);
length := count[0] shl 8 + count[1];

其次,这里的判断就不要这么用了,因为'A'对应$41,难道你的文件开始存的5个字节是
41 41 41 41 41?
if PATCH = 'AAAAAA' then begin //我文件开始的标识符AA AA AA AA AA 5个字节
-------------------------------------------------------------------------------
var
Str:string;
Loop: Integer;
const
HeanLen = 5;
SetLength(Str, HeadLen);
for Loop := 1 to HeadLen do
Str[Loop] := Char($AA);
if PATCH = Str then begin//当然,如果字节用Byte处理更好一点,没这么多麻烦

最后,循环处理的时候最好加一点判断,其实也就是在你文件编码中加一些标识符,比如AA... BB... CC.. 每个这一段前加一个$FFFF什么的,读完一段判断下一个开始是不是$FFFF,不然鬼才知道你这一段读写得对不对。

其实是很简单得一个操作,被你自己把16进制转字符串,又把字符串转16进制,弄得很复杂样的了。
 
算了散分了,谢谢大家了
 
后退
顶部