From: Peter Duniho on
On Wed, 16 Sep 2009 08:10:17 -0700, Michelle <michelle(a)notvalid.nomail>
wrote:

> Peter,
>
> [. . .]
> Int64 Offset1 = (ibBaseOffset + ibOffset); offset = 41152
> Int64 Offset2 = stream.Position; offset = 49152
>
> Why is Offset1 not equal to Offset2 ?

Because the old position is how far you've read into the file, not
necessarily where you're processing in the file.

> Offset1 is the right offset. Changing the block size has affect ( byte[]
> rgbBlockCur = new byte[4096]; )
>
> I tried several options with stream.Seek(Offset, SeekOrigin) to set the
> current position and restore the previously saved position.
> But when I read the previous 4 bytes and restore the position to the
> previous saved,
> the returned offset is not right anymore. The search continues, but it's
> not
> the right offset anymore.

It sounds to me as though you are somehow also resetting your processing
position. Without you showing how you modified my original code, I can't
offer any specific advice. But you _ought_ to be only modifying the
stream's Position; the ibBaseOffset and ibOffset variables should keep
their old values, and of course you also need to retain the byte[] buffers
used in the searching. Obviously, the easiest way to manage this is to
not return from the "FindByteString()" method at all when you find a
match; just do the necessary processing with the file then continue.

If for some reason that's not possible, and you don't want to literally
save and restore the necessary values and buffers, an alternative would be
to modify the "FindByteString()" method so that it takes an argument
specifying where to start searching. Then the caller, having done
whatever appropriate processing with the search result, can call the
method again, specifying the start offset as the previously returned
offset plus one. In the method, you'd simply set the stream Position to
this offset immediately after opening the stream.

Note that this latter approach will be less efficient, because the code
will be closing and reopening the stream, as well as re-reading bytes it'd
already read the previous time. I'd recommend simply not returning from
the method until you reach the end of the stream, rather than for each
time you find the string being searched for.

Pete
From: Michelle on
Peter,

[. . . ]
> Without you showing how you modified my original code, I can't offer any
> specific advice.
[. . . ]

while (true)
{
if (ibOffset + rgbPattern.Length <= cbBlockCur)
{
if (FRangesEqual(rgbBlockCur, ibOffset,
rgbPattern.Length, rgbPattern))
{
Int64 currOffset = (ibBaseOffset + ibOffset);
//correct offset match
byte[] prevBytes = new Byte[4];

stream.Seek(currOffset-4, SeekOrigin.Begin);
//is 'stream.Seek(-4, SeekOrigin.Current);' possible ?)
stream.Read(prevBytes, 0, 4);
//or 'stream.Read(prevBytes, 0, prevBytes.Length);'
// do something using the byte array prevBytes
stream.Seek(currOffset, SeekOrigin.Begin);
// or maybe do nothing, because after reading 4 bytes is back again


Michelle


From: Peter Duniho on
On Wed, 16 Sep 2009 22:41:53 -0700, Michelle <michelle(a)notvalid.nomail>
wrote:

> [...]
> Int64 currOffset = (ibBaseOffset + ibOffset);
> //correct offset match
> byte[] prevBytes = new Byte[4];
>
> stream.Seek(currOffset-4, SeekOrigin.Begin);
> //is 'stream.Seek(-4, SeekOrigin.Current);' possible ?)
> stream.Read(prevBytes, 0, 4);
> //or 'stream.Read(prevBytes, 0, prevBytes.Length);'
> // do something using the byte array
> prevBytes
> stream.Seek(currOffset, SeekOrigin.Begin);
> // or maybe do nothing, because after reading 4 bytes is back again

You need to restore the _actual_ stream Position, not the calculated
search offset. The latter is simply what bytes you're inspecting at the
moment, while the former is the next byte the code will need to read, if
and when it gets around to reading more data.

Your code should look more like this:

Int64 currOffset = stream.Position;
byte[] prevBytes = new Byte[4];

stream.Position = ibBaseOffset + ibOffset - 4;
stream.Read(prevBytes, 0, 4);
stream.Position = currOffset;

Pete
From: Michelle on
Peter,

It works properly. I'm all the way now :-))
Indeed, it's the difference between how far I've read into the file and
where I'm processing in the file.
For me an example says more than just an description.

It's perhaps a stupid question, but 'stream.Read' needs to reed the bytes
from the file again (disk access)
Is it possible to read direct from the byte array, because that's in memory
?
It may not a big difference, but I'm curious.

Michelle


From: Peter Duniho on
On Wed, 16 Sep 2009 23:30:10 -0700, Michelle <michelle(a)notvalid.nomail>
wrote:

> [...]
> It's perhaps a stupid question, but 'stream.Read' needs to reed the bytes
> from the file again (disk access)
> Is it possible to read direct from the byte array, because that's in
> memory
> ?
> It may not a big difference, but I'm curious.

Sure, it's possible. At the most simple, you can just check to make sure
that "ibOffset" is >= 4, and if it's not have some fallback code that goes
ahead and reads from the file as you're doing now (since the byte[]
buffers for the scanning won't contain the 4 bytes you need).

If you really want to avoid extra stream accesses under all circumstances,
you could keep a 4 byte (or 8 byte, since it appears from your previous
example you could need as many as 8 bytes) buffer that's updated each time
you update the byte[] buffers. That is, rather than discarding the
previous buffer entirely, save the last 4 (or 8) bytes in the buffer to a
new "scan-back" buffer you add to the code.

That said, Windows is buffering your file data for you already. There's
some extra overhead repositioning the stream, reading, and resetting the
position, but it's probably not nearly as much as one might think.

Pete