如何在二进制文件中查找某个值 ( 积分: 100 )

  • 主题发起人 主题发起人 dongxiao
  • 开始时间 开始时间
D

dongxiao

Unregistered / Unconfirmed
GUEST, unregistred user!
我现在可以把文件放进Stream里,然后怎么能取到27 27 29 F2的位置呢?
 
Pos('abc', ff.Memory)
 
现在不是要找字符串,而是找其对应的十六进制比如27 27 29 F2的位置。
 
用 流读取,一点点的判断嘛.哈。没有好办法.
如果是固定的文件
可以直接用 UltraEdit 来看位置是多少.然后用流进行读取
 
Mclkings大哥说的没错,其实我就是要实现类似UltraEdit以16进制方式打开后,查找某个16进制的值
 
16进制就是字符串,根本没区别。pos返回的值直接用ff.position移动过去就是了。
 
来自:白河愁, 时间:2007-9-3 14:25:17, ID:3830389
16进制就是字符串,根本没区别。pos返回的值直接用ff.position移动过去就是了。

--多谢白河愁大哥指点,但是用pos确实不行,首先我必须把文件加载到Stream里,而不是String里,因为文件里可能含有String的结束符。
还有你说的<16进制就是字符串,根本没区别>,这个不对的,16进制的是它的存储方式,它可能根本就不是字符,根本就不可视。
 
同意白河愁.
进制是进制,数据是数据.数据和字符串没啥区别.
字符串里面可以保存任何数据.
 
知道数据的位置,然后你通过转换爱怎么显示就怎么显示.
 
Pos('abc', PChar(ff.Memory))

这样肯定可以.
 
const
LP : array[0..3] of byte =($27,$27,$29,$F2); // 要找的内容
LBinFile = 'YouBinFile.bin'; // 被找的内容
{
当函数执行结果为 True 时,这个 PosList 的每一项都记录
了一个符合查找条件的位置(以 0 为基础)
}
function FindMemoryBlock(PosList:TStrings):Boolean;
var
M:TMemoryStream;
P,PL:Pointer;
Len:DWord;
begin
Result := False;
if not Assigned(PosList) then // 检查输入参数
begin
ShowMessage('输入参数不能为 NULL');
exit;
end
else PosList.Clear; // 清除原来的内容

Len:=SizeOf(LP); // 记录要找的字节数量
M:=TMemoryStream.Create; // 建立内存块对象
M.LoadFromFile(LBinFile); // 将文件加载到内存块中
if M.Size >= Len then // 判断是否有查找的必要
begin
P := M.Memory; // 查找的来源
PL:=@LP; // 查找的目标
while (M.Size - DWord(P)) >= Len do
begin
if CompareMem(P,PL,Len) then // 开始查找
begin
PosList.Add(IntToStr(DWord(P)-DWord(M.Memory))); // 找到了就记下位置
end;
P := Pointer(DWord(P) + Len); // 增量,继续查找,直到全部搜遍
end;
Result := PosList.Count > 0;
end;

M.Free; // 清除内存块对象
end;
 
学习了,受教!
多谢小雨哥的热心,
 
白河愁的Pos('abc', PChar(ff.Memory)) 肯定不行,Pos的第二个参数是string型,虽然string型可以保存任何数据(包括#0),但PChar(ff.Memory)转string型时以#0为结束符,截断文件的可能性很大,所以根本不能完整查找.

小雨哥的查找也有问题,while中以Len=SizeOf(LP)为增量,只能找到对象位置是Mod Len=0的位置(比如文件开头是00 27 27 29 F2就找不到了),while中的P就该用p:=P+1为增量才对.(当然,以P:=P+1为增量速度就慢得多了,需要优化一下算法判断取回的数据是否截出了待查数据的一部份,并预取出下一部份判断该增量移位多少才合适)
 
还没结束啊.晕倒
var
ff : TMemoryStream;
Tmp :String;
sub : String;
......

SetLength(Tmp, ff.Size);
ff.Position := 0;
ff.ReadBuffer(PChar(Tmp)^, Length(Tmp));
sub := #$27#$27#$29#$F2;
Pos(Sub, Tmp);
 
你硬说会结束。那就
setlength(tmp, ff.size);
CopyMemory(@tmp[1], ff.memory, ff.size);
Pos('abc', tmp);
 
哈哈哈哈,昏倒了我。

你居然看不出只要修改一个符号就可以按 Byte 查找吗?仔细看着下面这一句,真的它认识你而你不认识它呀。
P := Pointer(DWord(P) + Len); // 增量,继续查找,直到全部搜遍
 
后退
顶部