Is there any way to convert a Byte[] into a int8? I have been given a binary file that contains a list of input parameters for a test. The parameters vary in size from uint32 down to uint8. I am having no problem reading in the file, what is tricky is getting the values to display in the GUI.
Here's is the basis of what I'm doing:
private Byte[] blockSize;
private Byte[] binSize;
FileStream filen = File.OpenRead(file);
BinaryReader br = new BinaryReader(filen);
blockSize = br.ReadBytes(4);
binSize = br.ReadBytes(1);
No problems with that considering that the first 32 bits (4 bytes) of the parameter file are the blockSize and the next 8 bits (1 byte) are the value for my binSize variable. Where the problem comes is in displaying it.
textBox1.Text = BitConverter.ToInt32(blockSize, 0).ToString();
textBox2.Text = BitConverter.ToString(binSize, 0).ToString();
Lets say that my binary input file contains the following 5 bytes of data "0A 00 00 00 0A". My first textbox displays '10', my second textbox displays '0A'. I want the hex value converted into the more human understandable decimal value. It seems to work fine as long as the parameter in the input file is greater than 1 byte so I can easily convert it using ToInt16 or ToInt32, but I have nothing for the 8bit variety.
Your problem that r.ReadBytes(1); return byte[] then your call BitConverter.ToString(bytearray) with byte array as parameter which do the next:
Converts the numeric value of each element of a specified array of
bytes to its equivalent hexadecimal string representation
BinaryReader has methods
int ReadInt32()
byte ReadByte()
Change types of blockSize to int and binSize to byte and use those methods
int blockSize = br.ReadInt32();
byte binSize = br.ReadByte();
textBox1.Text = blockSize.ToString();
textBox2.Text = binSize.ToString();
From MSDN:
ReadInt32()
Reads a 4-byte signed integer from the current stream and advances the
current position of the stream by four bytes.
ReadByte()
Reads the next byte from the current stream and advances the current
position of the stream by one byte.
Related
I have this code:
Int32 i1 = 14000000;
byte[] b = BitConverter.GetBytes(i1);
string s = System.Text.Encoding.UTF8.GetString(b);
byte[] b2 = System.Text.Encoding.UTF8.GetBytes(s);
Int32 i2 = BitConverter.ToInt32(b2,0);;
i2 is equal to -272777233.
Why isn't it the input value? (14000000) ?
EDIT: what I am trying to do is append it to another string which I'm then writing to file using WriteAllText
Because an Encoding class is not going to just work for anything. If a "character" (possibly a few bytes in case of UTF-8) is not a valid character in that particular character set (in your case UTF-8), it will use a replacement character.
a single QUESTION MARK (U+003F)
(Source: http://msdn.microsoft.com/en-us/library/ms404377.aspx#FallbackStrategy)
Some case it is just a ?, for example in ASCII/CP437/ISO 8859-1, but there is a way for you to choose what to do with it. (See the link above)
For example if you try to convert (byte)128 to ASCII:
string s = System.Text.Encoding.ASCII.GetString(new byte[] { 48, 128 }); // s = "0?"
Then convert it back:
byte[] b = System.Text.Encoding.ASCII.GetBytes(s); // b = new byte[] { 48, 63 }
You will not get the original byte array.
This can be a reference: Check if character exists in encoding
I can't imagine why you would need to convert a byte array to a string. It obviously doesn't make any sense. Let's say you're going to write to a stream, you could just directly write byte[]. If you need to use it in some text representation, it makes perfect sense to just convert it to a string by yourIntegerVar.ToString() and use int.TryParse to get it back.
Edit:
You can write a byte array to a file, but you are not going to "concatenate" the byte array to a string and use the lazy method File.WriteAllText because it is going to handle the encoding conversion and you will probably end up having question marks ? all over your file. Instead, Open a FileStream and use FileStream.Write to directly write the byte array. Alternatively, you can use a BinaryWriter to directly write an integer in its binary form (and also a string) and use its counterpart BinaryReader to read it back.
Example:
FileStream fs;
fs = File.OpenWrite(#"C:\blah.dat");
BinaryWriter bw = new BinaryWriter(fs, Encoding.UTF8);
bw.Write((int)12345678);
bw.Write("This is a string in UTF-8 :)"); // Note that the binaryWriter also prefix the string with its length...
bw.Close();
fs = File.OpenRead(#"C:\blah.dat");
BinaryReader br = new BinaryReader(fs, Encoding.UTF8);
int myInt = br.ReadInt32();
string blah = br.ReadString(); // ...so that it can read it back.
br.Close();
This example code will result in a file which matches the following hexdump:
00 4e 61 bc 00 1c 54 68 69 73 20 69 73 20 61 20 73 Na¼..This is a s
10 74 72 69 6e 67 20 69 6e 20 55 54 46 2d 38 20 3a tring in UTF-8 :
20 29 )
Note that BinaryWriter.Write(string) also prefix the string with its length and it depends on it when reading back, so it is not appropriate to use a text editor to edit the resulting file. (Well you are writing an integer in its binary form so I expect this is acceptable?)
You shouldn't use Encoding.GetString to convert arbitrary binary data into a string. That method is only intended for text that has been encoded to binary data using a specific encoding.
Instead, you want to use a text representation which is capable of representing arbitrary binary data reversibly. The two most common ways of doing that are base64 and hex. Base64 is the simplest in .NET:
string base64 = Convert.ToBase64String(originalBytes);
...
byte[] recoveredBytes = Convert.FromBase64String(base64);
A few caveats to this:
If you want to use this string as a URL parameter, you should use a web-safe version of base64; I don't know of direct support for that in .NET, but you can probably find solutions easily enough
You should only do this at all if you really need the data in string format. If you're just trying to write it to a file or similar, it's simplest to keep it as binary data
Base64 isn't very human-readable; use hex if you want humans to be able to read the data in its text form without extra tooling. (There are various questions specifically about converting binary data to hex and back.)
It's not working because you are using encoding backwards.
Encoding is used to turn text into bytes, and then back into text again. You can't take any arbitrary bytes and turn into text. Every character has a corresponding byte pattern, but every byte pattern doesn't translate into a character.
If you want a compact way to represent bytes as text, use base-64 encoding:
Int32 i1 = 14000000;
byte[] b = BitConverter.GetBytes(i1);
string s = Convert.ToBase64String(b);
byte[] b2 = Convert.FromBase64String(s);
Int32 i2 = BitConverter.ToInt32(b2, 0);
If your goal here is to store an integer as a string then back to an integer, unless I am missing something wouldn't the following suffice:
int32 i1 = 1400000;
string s = il.ToString();
Int32 i2 = Int32.Parse(s);
To make a long story short:
You need a encoding that maps each bytevalue to a unique char and vice versa.
A UTF8 Character can be from 1 to 4 bytes long so you wont archive that mapping, you need a more basic encoding like ASCII.
Unfortunaly the original ASCII doesnt do that, it is just a 7-bit encoding and only defines the lower 128 Codes, the upper half (extended codes) is codepage specific. To get the full range translation, you just need a complete 8-bit encoding like in codepage 437 or 850 or whatever:
Int32 i1 = 14000000;
byte[] b = BitConverter.GetBytes(i1);
string s = System.Text.Encoding.GetEncoding(437).GetString(b);
byte[] b2 = System.Text.Encoding.GetEncoding(437).GetBytes(s);
Int32 i2 = BitConverter.ToInt32(b2,0);
I have a simple bit of code that converts a C# string by encoding it to UTF-8 then creating a byte array from it. But i am wondering how can i encode to UTF-8 using a byte array i have already made at a starting index?
So this is how i am currently encoding and getting the resulting byte array:
byte[] result = Encoding.UTF8.GetBytes(myString);
But I have a byte array premade that i would prefer to write to at a specific index if that makes sense. Is there any built in method to do this, if not how would i go about it ?
GetBytes has another overload that writes to existing array:
byte[] bytes = new byte[1000]; // sample, make sure it has enough space
var specificIndex = 0;
var actualByteCount = Encoding.UTF8.GetBytes(
myString, 0, myString.Length, bytes, specificIndex);
Don't forget to handle result to know how many bytes in the array actually represent string (actualByteCount)
Note you may need to use GetByteCount to get correct array size or adjust number of characters to convert to fit into your buffer.
First you will need to convert your bytes into Base64String then convert that into bytes. Likes this:
byte[] random = new byte[] { 0x00C9, 0x00C9, 0x00C9 };
byte[] encodedBytes = Encoding.UTF8.GetBytes(Convert.ToBase64String(random));
I'm trying to parse a JPEG file. This page says that the format is the following :
0xFF+Marker Number(1 byte)+Data size(2 bytes)+Data(n bytes)
So, when I encounter a 0xFF, I read the data like this (s is the JPEG file stream) :
int marker, size;
byte[] data;
//marker number (1 byte)
marker = s.ReadByte();
//size (2 bytes)
byte[] b = new byte[2];
s.Read(b, 0, 2);
size = BitConverter.ToInt16(b, 0);
Problem is, size's value after that is -7937 (which causes the next lines to raise an exception because I try to allow a -7937-long byte[]). b[0] == 255 and b[1] == 224.
I suspect I don't use BitConverter.ToInt16 properly, but I can't find what I did wrong.
The BitConverter doc page says that "The order of bytes in the array must reflect the endianness of the computer system's architecture", but when I do this :
byte a = b[0]; b[0] = b[1]; b[1] = a;
size = BitConverter.ToInt16(b, 0);
...I get size == -32 which is not really better.
What's the problem ?
Integers are stored in Big Endian order in JPEG. If you are on a little endian system (e.g. Intel) you need to reverse the order of the bytes in the length field. Length fields are unsigned.
The data in question was an unsigned int. Using the uint type and BitConverter.ToUInt16 fixed it.
I have application that play Pcap files and i try to add function that wrap my packet with PPPOE layer.
so almost all done except large packets that i didn't understand yet how to set the new langth after add PPPOE layer.
For example this packet:
As you can see this packet length is 972 bytes (03 cc), and all i want is to convert it to decimal, after see this packet byte[] in my code i can see that this value converted into 3 and 204 in my packet byte[], so my question is how this calculation works ?
Those two bytes represents a short (System.Int16) in bigendian notation (most significant byte first).
You can follow two approaches to get the decimal value of those two bytes. One is with the BitConverter class, the other is by doing the calculation your self.
BitConverter
// the bytes
var bytes = new byte[] {3, 204};
// are the bytes little endian?
var littleEndian = false; // no
// What architecure is the BitConverter running on?
if (BitConverter.IsLittleEndian != littleEndian)
{
// reverse the bytes if endianess mismatch
bytes = bytes.Reverse().ToArray();
}
// convert
var value = BitConverter.ToInt16( bytes , 0);
value.Dump(); // or Console.WriteLine(value); --> 972
Calculate your self
base 256 of two bytes:
// the bytes
var bytes2 = new byte[] {3, 204};
// [0] * 256 + [1]
var value2 = bytes2[0] * 256 + bytes2[1]; // 3 * 256 + 204
value2.Dump(); // 972
Is there something similar to sprintf() in C#?
I would for instance like to convert an integer to a 2-byte byte-array.
Something like:
int number = 17;
byte[] s = sprintf("%2c", number);
string s = string.Format("{0:00}", number)
The first 0 means "the first argument" (i.e. number); the 00 after the colon is the format specifier (2 numeric digits).
However, note that .NET strings are UTF-16, so a 2-character string is 4 bytes, not 2
(edit: question changed from string to byte[])
To get the bytes, use Encoding:
byte[] raw = Encoding.UTF8.GetBytes(s);
(obviously different encodings may give different results; UTF8 will give 2 bytes for this data)
Actually, a shorter version of the first bit is:
string s = number.ToString("00");
But the string.Format version is more flexible.
EDIT: I'm assuming that you want to convert the value of an integer to a byte array and not the value converted to a string first and then to a byte array (check marc's answer for the latter.)
To convert an int to a byte array you can use:
byte[] array = BitConverter.GetBytes(17);
but that will give you an array of 4 bytes and not 2 (since an int is 32 bits.)
To get an array of 2 bytes you should use:
byte[] array = BitConverter.GetBytes((short)17);
If you just want to convert the value 17 to two characters then use:
string result = string.Format("{0:00}", 17);
But as marc pointed out the result will consume 4 bytes since each character in .NET is 2 bytes (UTF-16) (including the two bytes that hold the string length it will be 6 bytes).
It turned out, that what I really wanted was this:
short number = 17;
System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream);
writer.Write(number);
writer.Flush();
The key here is the Write-function of the BinaryWriter class. It has 18 overloads, converting different formats to a byte array which it writes to the stream. In my case I have to make sure the number I want to write is kept in a short datatype, this will make the Write function write 2 bytes.