From: Michelle on
I've tried to write code to read the previous four bytes.
This is my code:

static void FindPrevBytes(int ioffset)
{
FileStream fs = File.OpenRead(@"D:\myfile.bin");
// opens the file for reading
BinaryReader br = new BinaryReader(fs);
br.BaseStream.Position = ioffset - 4;
// position = offset pattern found -4 bytes
byte[] arrBytes = br.ReadBytes(4);
// array containing the four bytes
string strBytes = (Regex.Replace(BitConverter.ToString(arrBytes), "-",
"")); // string output WITHOUT dashes.
int intDecValue = int.Parse(strBytes,
System.Globalization.NumberStyles.HexNumber); // convert Hex to
Dec

Console.WriteLine("Value found: " + intDecValue );
// write
}


I'm not happy about this; FileStream fs = File.OpenRead(@"D:\myfile.bin");
Because it opens the file for reading the second time.
It works, but I'm not sure this is the best solution.
Please give me feedback.

Best regards,

Michelle


From: Peter Duniho on
On Mon, 14 Sep 2009 05:40:08 -0700, Michelle <michelle(a)notvalid.nomail>
wrote:

> [...]
> I'm not happy about this; FileStream fs =
> File.OpenRead(@"D:\myfile.bin");
> Because it opens the file for reading the second time.
> It works, but I'm not sure this is the best solution.
> Please give me feedback.

The only reason to use BinaryReader is if you want to convert directly
from bytes read to some more complex type. If you're only ever going to
read the plain bytes, just read them directly from the FileStream you're
working with. You can use the Position property to adjust from where
you're reading in the file; save the current position, set the current
position to 4 bytes earlier than the offset of the found string, read the
4 bytes of interest, then restore the current position to the previously
saved value.

Your processing of those four bytes seems odd too, but perhaps we just
don't know enough about the format. If you have 4 bytes in an array, it
would seem that you ought to just be using BitConverter to convert those
directly to a 32-bit int, rather than doing all that stuff with the string.

If, as it appears from your conversion code, the bytes in the file are
big-endian (most-significant-byte first) you can handle that much more
cleanly simply by swapping the bytes before converting to a 32-bit int.
If you like, you can just encapsulate that in a single method:

int Int32FromMSBArray(byte[] rgb)
{
byte bT = rgb[0];

rgb[0] = rgb[3];
rgb[3] = bT;
bT = rgb[1];
rgb[1] = rgb[2];
rgb[2] = rgbT;

return BitConverter.ToInt32(rgb, 0);
}

(The above code modifies the input array; normally this shouldn't be a
problem, but if you need the original array preserved, you'll want to make
a copy).

Pete
From: Peter Duniho on
On Mon, 14 Sep 2009 10:05:15 -0700, Peter Duniho
<no.peted.spam(a)no.nwlink.spam.com> wrote:

> [...]
> (The above code modifies the input array; normally this shouldn't be a
> problem, but if you need the original array preserved, you'll want to
> make a copy).

Or alternatively, just swap the bytes _after_ the conversion, using
traditional bit-shift/or operations (the code's less obvious to some
people, but it will be much more efficient).

Pete
From: Michelle on
Peter,

> [ . . .] If you're only ever going to read the plain bytes, just read
> them directly from the FileStream you're working with. You can use the
> Position property to adjust from where you're reading in the file; save
> the current position, set the current position to 4 bytes earlier than
> the offset of the found string, read the 4 bytes of interest, then
> restore the current position to the previously saved value.

So I must use Get and Set using the FileStream.Position property.
But how can I read the bytes from a specific position from the FileStream .
I couldn't find that using the FileStream, so I'd used BinaryReader.

> If, as it appears from your conversion code, the bytes in the file are
> big-endian (most-significant-byte first) you can handle that much more
> cleanly simply by swapping the bytes before converting to a 32-bit int.

All I need is the Decimal value of these four bytes.
I can't use BitConverter to convert an Array directly to Decimal.
I can use a System.IO.MemoryStream object instead:

//Create a decimal from a bye array.
public static decimal ByteArrayToDecimal (byte[] src)
{
//Create a MemoryStream containing the byte array.
using (MemoryStream stream = new MemoryStream(src))
{
//Create a BinaryReader to read the decimal from the stream.
using (BinaryReader reader = new BinaryReader(stream))
{
// Read and return the decimal from the BinaryReader/MemoryStream
return reader.ReadDecimal();
}
}
}

Instead of that, I used:

string strBytes = (Regex.Replace(BitConverter.ToString(arrBytes), "-",
"")); // string output WITHOUT dashes.
int intDecValue = int.Parse(strBytes,
System.Globalization.NumberStyles.HexNumber); //convert to dec


Best regards,

Michelle


From: Peter Duniho on
On Tue, 15 Sep 2009 00:02:57 -0700, Michelle <michelle(a)notvalid.nomail>
wrote:

> So I must use Get and Set using the FileStream.Position property.
> But how can I read the bytes from a specific position from the
> FileStream .
> I couldn't find that using the FileStream, so I'd used BinaryReader.

FileStream _only_ allows reading bytes, either one at a time or into a
byte[]. As far as reading bytes from a specific position in the file, you
have to set the Position property to the position where you want to read,
and then you simply read. It's just that simple.

>> If, as it appears from your conversion code, the bytes in the file are
>> big-endian (most-significant-byte first) you can handle that much more
>> cleanly simply by swapping the bytes before converting to a 32-bit int.
>
> All I need is the Decimal value of these four bytes.
> I can't use BitConverter to convert an Array directly to Decimal.

I don't really understand that. I mean, yes it's true...BitConverter
doesn't provide support for reading or writing the Decimal type. But the
code you posted before doesn't use the Decimal type anyway.

> I can use a System.IO.MemoryStream object instead:
>
> //Create a decimal from a bye array.
> public static decimal ByteArrayToDecimal (byte[] src)
> {
> //Create a MemoryStream containing the byte array.
> using (MemoryStream stream = new MemoryStream(src))
> {
> //Create a BinaryReader to read the decimal from the stream.
> using (BinaryReader reader = new BinaryReader(stream))
> {
> // Read and return the decimal from the BinaryReader/MemoryStream
> return reader.ReadDecimal();
> }
> }
> }

That looks like a fine way to convert a byte array to the Decimal numeric
type. But if you've already got a FileStream, you should be able to use
BinaryReader directly on it, and if the stored data in the file isn't
actually in the Decimal numeric format, then reading it as Decimal isn't
going to work anyway.

Note that the Decimal numeric type takes up 16 bytes in a file. So if you
are reading only 4 bytes, then obviously either you are reading the data
as the wrong format, or not reading enough bytes. Either way, you won't
get valid results.

> Instead of that, I used:
>
> string strBytes = (Regex.Replace(BitConverter.ToString(arrBytes), "-",
> "")); // string output WITHOUT dashes.
> int intDecValue = int.Parse(strBytes,
> System.Globalization.NumberStyles.HexNumber); //convert to dec

Do you get the values you expect when you do that? If so, then your
number must not be Decimal in the first place.

Beyond that, as I mentioned before, the code above will parse your bytes
as if they are big-endian. So if the data in the file isn't in big-endian
format, that's also a problem. Again, the question is, do you get the
values you expect?

Basically, you've provided no information here that would allow anyone to
know for sure what the format of the numbers in your file are. Unless and
until you do so, no one can offer any specific advice as to how to read
that data; we can only make assumptions based on code you've shown,
including the assumption the code you've shown does what you want.

Pete