I'm new to C# moving from Java. I'm trying to read in a file using IO in HEX. When I read the first byte in I don't get what I'm seeing in my Hex editor.
I'm using
StreamReader reader = new StreamReader(fileDirectory);
int hexIn;
String hex;
for (int i = 0; (hexIn = reader.Read()) != -1; i++){
hex = Convert.ToString(hexIn, 16);
}
In Java I used
FileInputStream fis = new FileInputStream(file);
long length = file.length();
int hexIn;
String hex = "";
for(int i = 0; (hexIn = fis.read()) != -1; i++){
String s = Integer.toHexString(hexIn);
if(s.length() < 2){
s = "0" + Integer.toHexString(hexIn);
}
I hope this makes sense. Any help would be most apperciated :)
Thanks.
Don't use a StreamReader—that's only for characters in a certain encoding (default UTF8). Use a FileStream class instead:
FileStream fs = new FileStream(fileDirectory, FileMode.Open);
int hexIn;
String hex;
for (int i = 0; (hexIn = fs.ReadByte()) != -1; i++){
hex = string.Format("{0:X2}", hexIn);
}
You need such C# code to achieve the same results as your Java code:
hex = hexIn.ToString("X").PadLeft(2, '0');
The Convert.ToString also works, but IMO using the native ToString of the integer is better practice.
Anyway you were missing the PadLeft part that indeed caused 15 to be 'f' instead of 0F.
Related
I have a Code in Metatrader that writes some Quotes to CSV, but while doing same in C# the Expert advisor reads the values a different way....
This Code in MetaEditor writes the CSV file:
li_40 = FileOpen(ls_32, FILE_CSV|FILE_WRITE|FILE_SHARE_READ, ";");
if (li_40 > 0) {
FileWrite(li_40, ls_16);
FileClose(li_40);
This Writes in C#:
List<string> listB = new List<string>();
using (StreamReader reader = new StreamReader(File.OpenRead(oFile)))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
listB.Add(reader.ReadLine());
}
reader.Close();
}
using (StreamWriter swOut = new StreamWriter(oFile))
{
foreach (var item in listB)
{
swOut.Write(item);
swOut.Write(Environment.NewLine);
}
for (int i = 0; i <= gridIn.Columns.Count - 1; i++)
{
if (i > 0)
{
swOut.Write(", ");
}
value = dr.Cells[i].Value.ToString();
string vals = dr.Cells[2].Value.ToString();
int priceDecimalPlaces = vals.Split('.').Count() > 1
? vals.Split('.').ToList().ElementAt(1).Length
: 0;
string nell = "0";
if (priceDecimalPlaces == 3)
{
nell = "0.001";
}
if (priceDecimalPlaces == 5)
{
nell = "0.00001";
}
if (priceDecimalPlaces == 4)
{
nell = "0.0001";
}
//replace comma's with spaces
value = value.Replace(',', ' ');
//replace embedded newlines with spaces
value = value.Replace(Environment.NewLine, "");
If the difference between the C# double and the Metatrader's current double value is 0.12098-0.12096=2, the Metatrader won't see the value as 2 but something very much higher like 18,17 and so on, but writing this same value from the MetaTrader's code gives correct value...
I read the CSV using _lread:
uchar chBuff[1024];
int res = _lread(hFile, chBuff, 1);
//
//CreateFileA(
res = _lread(hFile, chBuff, 350);
ls_308 = CharArrayToString(chBuff, 0, res, CP_UTF8);
//Alert(Ls_84);
ls_308=StringSubstr(ls_308,0,StringFind(ls_308,"\r\n",0));
if (_lclose(hFile)<0) Print("Error closing");
I think there are some difference between C# doubles on Metatrader and normal Metatrader doubles
The error was caused by the System's encoding language which was different to UTF-8 that was specified in the Metatrader code
ls_308 = CharArrayToString(chBuff, 0, res, CP_UTF8);
So, I changed the UTF to All Code Page assigned by System by doing this
ls_308 = CharArrayToString(chBuff, 0, res, CP_ACP);
Hope someone find this useful..
I'm trying to put the values of a string into a byte array with out changing the characters. This is because the string is in fact a byte representation of the data.
The goal is to move the input string into a byte array and then convert the byte array using:
string result = System.Text.Encoding.UTF8.GetString(data);
I hope someone can help me although I know it´s not a very good description.
EDIT:
And maybe I should explain that what I´m working on is a simple windows form with a textbox where users can copy the encoded data into it and then click preview to see the decoded data.
EDIT:
A little more code:
(inputText is a textbox)
private void button1_Click(object sender, EventArgs e)
{
string inputString = this.inputText.Text;
byte[] input = new byte[inputString.Length];
for (int i = 0; i < inputString.Length; i++)
{
input[i] = inputString[i];
}
string output = base64Decode(input);
this.inputText.Text = "";
this.inputText.Text = output;
}
This is a part of a windows form and it includes a rich text box. This code doesn´t work because it won´t let me convert type char to byte.
But if I change the line to :
private void button1_Click(object sender, EventArgs e)
{
string inputString = this.inputText.Text;
byte[] input = new byte[inputString.Length];
for (int i = 0; i < inputString.Length; i++)
{
input[i] = (byte)inputString[i];
}
string output = base64Decode(input);
this.inputText.Text = "";
this.inputText.Text = output;
}
It encodes the value and I don´t want that. I hope this explains a little bit better what I´m trying to do.
EDIT: The base64Decode function:
public string base64Decode(byte[] data)
{
try
{
string result = System.Text.Encoding.UTF8.GetString(data);
return result;
}
catch (Exception e)
{
throw new Exception("Error in base64Decode" + e.Message);
}
}
The string is not encoded using base64 just to be clear. This is just bad naming on my behalf.
Note this is just one line of input.
I've got it. The problem was I was always trying to decode the wrong format. I feel very stupid because when I posted the example input I saw this had to be hex and it was so from then on it was easy. I used this site for reference:
http://msdn.microsoft.com/en-us/library/bb311038.aspx
My code:
public string[] getHexValues(string s)
{
int j = 0;
string[] hex = new String[s.Length/2];
for (int i = 0; i < s.Length-2; i += 2)
{
string temp = s.Substring(i, 2);
this.inputText.Text = temp;
if (temp.Equals("0x")) ;
else
{
hex[j] = temp;
j++;
}
}
return hex;
}
public string convertFromHex(string[] hex)
{
string result = null;
for (int i = 0; i < hex.Length; i++)
{
int value = Convert.ToInt32(hex[i], 16);
result += Char.ConvertFromUtf32(value);
}
return result;
}
I feel quite dumb right now but thanks to everyone who helped, especially #Jon Skeet.
Are you saying you have something like this:
string s = "48656c6c6f2c20776f726c6421";
and you want these values as a byte array? Then:
public IEnumerable<byte> GetBytesFromByteString(string s) {
for (int index = 0; index < s.Length; index += 2) {
yield return Convert.ToByte(s.Substring(index, 2), 16);
}
}
Usage:
string s = "48656c6c6f2c20776f726c6421";
var bytes = GetBytesFromByteString(s).ToArray();
Note that the output of
Console.WriteLine(System.Text.ASCIIEncoding.ASCII.GetString(bytes));
is
Hello, world!
You obviously need to make the above method a lot safer.
Encoding has the reverse method:
byte[] data = System.Text.Encoding.UTF8.GetBytes(originalString);
string result = System.Text.Encoding.UTF8.GetString(data);
Debug.Assert(result == originalString);
But what you mean 'without converting' is unclear.
One way to do it would be to write:
string s = new string(bytes.Select(x => (char)c).ToArray());
That will give you a string that has one character for every single byte in the array.
Another way is to use an 8-bit character encoding. For example:
var MyEncoding = Encoding.GetEncoding("windows-1252");
string s = MyEncoding.GetString(bytes);
I'm think that Windows-1252 defines all 256 characters, although I'm not certain. If it doesn't, you're going to end up with converted characters. You should be able to find an 8-bit encoding that will do this without any conversion. But you're probably better off using the byte-to-character loop above.
If anyone still needs it this worked for me:
byte[] result = Convert.FromBase64String(str);
Have you tried:
string s = "....";
System.Text.UTF8Encoding.UTF8.GetBytes(s);
I wrote a function to convert byte[] to string, and I add ";" after each byte. Now I want to convert this string to byte[] by splitting the string (similar to a CSV string).
public string ByteArrayToString(byte[] byteArray,string s)
{
for (int i = 0; i < byteArray.Length; i++)
{
s += byteArray[i].ToString() + ";";
}
s = s.Substring(0, s.Length - 1);
return s;
}
How could I write a function to convert this string to that byte array again?
try this
var byteArray = new byte[] {123, 11, 111};
var stringBytes = string.Join(";", byteArray.Select(b => b.ToString()));
var newByteArray = stringBytes.Split(';').Select(s => byte.Parse(s)).ToArray();
I guess that you want to get rid of the ; when converting also. I think you want to do something like this:
byte[] result = Encoding.UTF8.GetBytes(s.Replace(";",""));
This will fail if the original byte array actually contains a ;that is valid data, but in that case you will have lots of problems anyway since your "CSV" file will be wrongly formatted.
Consider using Split String
StringBuilder will be useful instead of String (Performance wise).
With StringBuilder:
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(objStringBuilder.ToString());
with String:
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(objString);
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
return encoding.GetBytes(yourStringVariable);
I know you already know the answer by now... but this code solves the problem, i hope it helps someone else.
int counter= 0;
string cadena = "8,5,6,3,4,6,3"
string[] foto = cadena.Split(',');
byte[] fotoFinal = new byte[foto.Length];
foreach (string s in foto)
{
fotoFinal[contador] = Convert.ToByte(s);
counter++;
}
str.Split(new char[]{';'},
StringSplitOptions.RemoveEmptyEntries).Select(s => byte.Parse(s)).ToArray();
Simply :)
public static byte[] Bytes ( this string Key )
{
return Enumerable.Range(0, Key.Binary().Length / 8 )
.Select(Index => Convert.ToByte(
Key.Binary().Substring(Index * 8, 8), 2))
.ToArray();
}
string[] sbytes = sl.Split(',');
byte[] b = new byte[sbytes.Length];
for (int j = 0; j < sbytes.Length; j++)
{
byte newByte = byte.Parse(sbytes[j], System.Globalization.NumberStyles.HexNumber);
b[j] = newByte;
}
I like using number styles hex number.
I'm trying to create a binary file from a intelHex file. Iside the intelHex file I have data and address to which I should write the data inside the binary file.
IntelHex file looks like that
:10010000214601360121470136007EFE09D2190140
:100110002146017EB7C20001FF5F16002148011988
:10012000194E79234623965778239EDA3F01B2CAA7
:100130003F0156702B5E712B722B732146013421C7
:00000001FF
So I have 4 lines here with data since the last one tells us thats the end of file.
Here is what I'm doing to create the file
while (!streamReader.EndOfStream)
{
string temp = String.Empty;
int address = 0;
line = streamReader.ReadLine();
// Get address for each data
address = Convert.ToInt32(line.Substring(3, 4), 16);
// Get data from each line
temp = line.Substring(7, 2);
if (temp == "01")
break;
else
{
temp = line.Substring(9, line.Length - 11);
string[] array = new string[(temp.Length / 2)];
int j = 0;
for (int i = 0; i < array.Length; ++i)
{
array[i] = temp[j].ToString() + temp[j + 1].ToString();
j = j + 2;
}
temp = String.Empty;
for (int i = 0; i < array.Length; ++i)
{
temp = temp + Convert.ToChar(Convert.ToInt32(array[i], 16));
}
}
binaryWriter.Seek(address, SeekOrigin.Begin);
binaryWriter.Write(temp);
binaryWriter.Flush();
}
Console.WriteLine("Done...\nPress any key to exit...");
The problem here is, that data in binary file in some places is not equal to data from the intelHex file. Looks like there is some random data added to the file and I do not know from where. First time I saw that there is an additional data before the data from the intelHex file. For instance first data line starts with 21, but in binary file I have a number 12 before the 21. I do not know what is wrong here. Hope someone can help me or guide me where I can find some usefull informations about creating binary files in C#
<Generic answer pointing out that a Unicode character (char) is not an octet (byte), and that the code produces the wrong output because binary data is written as Unicode string to the file.>
Hint: use a byte[] for binary data, not a string.
Also: In before answers suggesting to use a StringBuilder for the loop.
Basically, I'm building a small tracker for experimental purposes. I've gotten quite far, and am now working on the announce part.
What I really can't figure out is how I should decode the info_hash query string provided.
From the specification, it is a urlencoded 20-byte SHA1 hash, which made me write this code,
byte[] foo = Encoding.Default.GetBytes(HttpUtility.UrlDecode(infoHash));
string temp = "";
foreach (byte b in foo)
{
temp += b.ToString("X");
}
Which gives 'temp' the following value,
5D3F3F3F3F5E3F3F3F153FE4033683F55693468
The first and last few characters are correct. This is the raw info_hash,
%5d%96%b6%f6%84%5e%ea%da%c5%15%c4%0e%403h%b9Ui4h
And this is what both uTorrent and my own tracker gives me as info_hash when generating it from the torrent file,
5D96B6F6845EEADAC515C40E403368B955693468
What am I doing wrong?
UrlDecode returns a string, but a SHA1 hash doesn't make sense if interpreted as (ANSI) string.
You need to decode the input string directly to an byte array, without the roundtrip to a string.
var s = "%5d%96%b6%f6%84%5e%ea%da%c5%15%c4%0e%403h%b9Ui4h";
var ms = new MemoryStream();
for (var i = 0; i < s.Length; i++)
{
if (s[i] == '%')
{
ms.WriteByte(
byte.Parse(s.Substring(i + 1, 2), NumberStyles.AllowHexSpecifier));
i += 2;
}
else if (s[i] < 128)
{
ms.WriteByte((byte)s[i]);
}
}
byte[] infoHash = ms.ToArray();
string temp = BitConverter.ToString(infoHash);
// "5D-96-B6-F6-84-5E-EA-DA-C5-15-C4-0E-40-33-68-B9-55-69-34-68"
HttpUtility.UrlDecodeToBytes