Assuming I have this Method.
private static void Example(string data)
{
Console.WriteLine("Initial : {0}", data);
data = data.PadRight(data.Length + 1, '0');
Console.WriteLine("Step 1 : {0}", data);
data = data.PadRight(data.Length + 4 - data.Length % 4, '=');
Console.WriteLine("Step 2 : {0}", data);
byte[] byteArray = Convert.FromBase64String(data);
string newData = Convert.ToBase64String(byteArray);
Console.WriteLine("Step 3 : {0}", newData);
}
I expect the output given the input string "1" to be as follows
Initial : 1
Step 1 : 10
Step 2 : 10==
Step 3 : 10==
Instead the output is this.
Initial : 1
Step 1 : 10
Step 2 : 10==
Step 3 : 1w==
And I have no idea why. I would expect the output to be the same as the input but it isn't.
I have tried replacing
data = data.PadRight(data.Length + 1, '0');
with
data = data + "0";
It appears with longer input strings too, for example strings with a length of 5 or 9. It works fine if I add "=" but then I exceed my padding limit with Convert.FromBase64String()
So my question is really what is going on and how can I get my expected output,?
What am I doing wrong?
Edit: For those confused as to why I'm using bas64 it is related to this PHP decrypting data with RSA Private Key
Basically, there's no byte array which would be encoded to 10==.
If a base64 string ends with ==, that means that the final 4 characters only represent a single byte. So only the first character and the first 2 bits of the second character are relevant. Looking at the Wikipedia table, 10 means values of:
'1' = 53 '0' = 52
110101 110100
So that's encoding a byte of 1101 0111, and then the final four bits (0100) are ignored. When you re-encode the data, it's using 0s for the final four bits instead, giving:
'1' = 53 'w' = 48
110101 110000
Fundamentally, it's not clear what you're trying to do - but if your input is part of a base64-encoded value, that's pretty odd. The code is behaving the way I'd expect it to - it's just not useful code...
Related
I convert my Hex to dump to get special character like symbol but when I try to convert my "0x18" i "\u0018" this value. Can anyone give me solution regarding this matter.
Here is my code:
public static string FromHexDump(string sText)
{
Int32 lIdx;
string prValue ="" ;
for (lIdx = 1; lIdx < sText.Length; lIdx += 2)
{
string prString = "0x" + Mid(sText, lIdx, 2);
string prUniCode = Convert.ToChar(Convert.ToInt64(prString,16)).ToString();
prValue = prValue + prUniCode;
}
return prValue;
}
I used VB language. I have a database that already encrypted text to my password and the value is BAA37D40186D like this so I loop it by step 2 and it will like this 0xBA,0xA3,0x7D,0x40,0x18,0x6D and the VB result getting like this º£}#m
You can use this code:
var myHex = '\x0633';
var formattedString += string.Format(#"\x{0:x4}", (int)myHex);
Or you can use this code from MSDN (https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/how-to-convert-between-hexadecimal-strings-and-numeric-types):
string hexValues = "48 65 6C 6C 6F 20 57 6F 72 6C 64 21";
string[] hexValuesSplit = hexValues.Split(' ');
foreach (string hex in hexValuesSplit)
{
// Convert the number expressed in base-16 to an integer.
int value = Convert.ToInt32(hex, 16);
// Get the character corresponding to the integral value.
string stringValue = Char.ConvertFromUtf32(value);
char charValue = (char)value;
Console.WriteLine("hexadecimal value = {0}, int value = {1}, char value = {2} or {3}",
hex, value, stringValue, charValue);
}
The question is unclear - what is the database column's type? Does it contain 6 bytes, or 12 characters with the hex encoding of the bytes? In any case, this has nothing to do with special characters or encodings.
First, 0x18 is the byte value of the Cancel Character in the Latin 1 codepage, not the pound sign. That's 0xA3. It seems that the byte values in the question are just the Latin 1 bytes for the string in hex.
.NET strings are Unicode (UTF16LE specifically). There's no UTF8 string or Latin1 string. Encodings and codepages apply when converting bytes to strings or vice versa. This is done using the Encoding class and eg Encoding.GetBytes
In this case, this code will convert the byte to the expected string form, including the unprintable character :
new byte[] {0xBA,0xA3,0x7D,0x40,0x18,0x6D};
var latinEncoding=Encoding.GetEncoding(1252);
var result=latinEncoding.GetString(dbBytes);
The result is :
º£}#m
With the Cancel character between # and m.
If the database column contains the byte values as strings :
it takes double the required space and
the hex values have to be converted back to bytes before converting to strings
The x format is used to convert numbers or bytes to their hex form and vice versa. For each byte value, ToString("x") returns the hex string.
The hex string can be produced from the original buffer with :
var dbBytes=new byte[] {0xBA,0xA3,0x7D,0x40,0x18,0x6D};
var hexString=String.Join("",dbBytes.Select(c=>c.ToString("x")));
There are many questions that show how to parse a byte string into a byte array. I'll just steal Jared Parson's LINQ answer :
public static byte[] StringToByteArray(string hex) {
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
With that, we can parse the hex string into a byte array and convert it to the original string :
var bytes=StringToByteArray(hexString);
var latinEncoding=Encoding.GetEncoding(1252);
var result=latinEncoding.GetString(bytes);
First of all u don't need dump but Unicode, I would recomend to read about unicode/encoding etc and why this is a problem with strings.
PS: solution : StackOverflow
I suspect that my decoding is not working properly. That is why I am testing it by encoding, decoding and the re-encoding to see if I am getting the same result. That is however not the case.
I encoded a byte[] named model.PDF to a base64 string.
Now, for decoding, I converted model.PDF to a decoded base64 string. However the output looks faulty or corrupted upon debugging and I suspect this is where something is going wrong.
To encode again, the decoded data is turned into byte[] again and then into an encoded base64 string. However base64EncodedData does not match plainTextEncodedData. Please help me create a flawless encode to decode to re-encode flow.
// ENCODING - Byte array -> base64 encoded string
string base64EncodedData = Convert.ToBase64String(model.PDF);
// DECODING - Byte array -> base64 decoded string
var base64DecodedData = Encoding.UTF8.GetString(model.PDF);
// ENCODING AGAIN
byte[] plainTextBytes = Encoding.UTF8.GetBytes(base64DecodedData);
var plainTextEncodedData = Convert.ToBase64String(plainTextBytes);
To elaborate, the re-encoding matches the initial encoding perfectly if executed like this.
var PDF = System.Text.Encoding.UTF8.GetBytes("redgreenblue");
string base64EncodedData = Convert.ToBase64String(PDF);
// DECODING - Byte array -> base64 decoded string
var base64DecodedData = Encoding.UTF8.GetString(PDF);
// ...
But, my model.PDF is fetched from the database as shown below, in which case the re-encoding does not match.
while (reader.Read()) {
model.PDF = reader["PDF"] == DBNull.Value ? null : (byte[])reader["PDF"];
}
On an online base64 decoder (https://www.base64decode.org/), decoding an example value of base64EncodedData shows the ideal and correct value.
%PDF-1.5
%
1 0 obj
<</Type/Catalog/Pages 2 0 R/Lang(en-IN) /StructTreeRoot 8 0 R/MarkInfo<</Marked true>>>>
endobj
2 0 obj
<</Type/Pages/Count 1/Kids[ 4 0 R] >>
endobj
3 0 obj
<</Author(admin) /CreationDate(D:20190724114817+05'30')
/ModDate(D:20190724114817+05'30') /Producer(Microsoft Excel 2013) /Creator(Microsoft Excel 2013) >>
endobj
4 0 obj
<</Type/Page/Parent 2 0 R/Resources<</Font<</F1 6 0 R>>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 612 792] /Contents 5 0 R/Group<</Type/Group/S/Transparency/CS/DeviceRGB>>/Tabs/S/StructParents 0>>
endobj
5 0 obj
<</Filter/FlateDecode/Length 171>>
stream
...
However, in my program, the value of base64DecodedData shows up in its entirety as:
%PDF-1.5
%����
1 0 obj
<</Type/Catalog/Pages 2 0 R/Lang(en-IN) /StructTreeRoot 8 0 R/MarkInfo<</Marked true>>>>
endobj
2 0 obj
<</Type/Pages/Count 1/Kids[ 4 0 R] >>
endobj
3 0 obj
<</Author(admin) /CreationDate(D:20190724114817+05'30')
/ModDate(D:20190724114817+05'30') /Producer(��
The 2 look similar in ways but my program seems to be producing a corrupt version of what the actual base64 decoded string should be.
A PDF is an ASCII file that can contain binary data (including strings in other encodings).
So you cannot read it as plain text.
If a PDF file contains binary data, as most do [...] the header line
shall be immediately followed by a comment line containing at least
four binary characters—that is, characters whose codes are 128 or
greater.
Taken from this answer, which has some more infos
You see exactly these four characters in your own output.
I have a String[] of hex values "10" "0F" "3E" "42" stored.
I found this method to convert to a Byte[]
public static byte[] ToByteArray(String HexString)
{
int NumberChars = HexString.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(HexString.Substring(i, 2), 16);
}
return bytes;
}
However this converts the values to the hex equivalent. But the values are already in the hex equivalent!
For example this makes "10" "0F" "3E" "42" into "16" "15" "62" "66".
I want it to directly copy the values as they are already the correct hex value.
Edit:
Basically...
I want a byte array with the literal characters in the String[] So say the second value in String[] is 0F. I want the first byte in Byte[] to be 0F and not 16
Any ideas?
Edit2
Let me clarify. I don't want to convert my String[] values into Hexadecimal, as they are already Hexadecimal. I want to directly copy them to a Byte[]
The problem is my string of values "10" "0F" "3E" 42" already has the hexadecimal value I want. I want the byte array to contain those exact values and not convert them, they are already hexadecimal form.
You have to convert (or parse) string in order to get byte since string and byte are different types:
// 10 == 10d
byte b = Convert.ToByte("10"); // if "10" is a decimal representation
// 16 == 0x10
byte b = Convert.ToByte("10", 16); // if "10" is a hexadecimal representation
If you want to process an array, you can try a simple Linq:
using System.Linq;
...
string[] hexValues = new string[] {
"10", "0F", "3E", "42"};
byte[] result = hexValues
.Select(value => Convert.ToByte(value, 16))
.ToArray();
If you want to print out result as hexadecimal, use formatting ("X2" format string - at least 2 hexadecimal digits, use captital letters):
// 10, 0F, 3E, 42
Console.Write(string.Join(", ", result.Select(b => b.ToString("X2"))));
Compare with same array but in a different format ("d2" - at least 2 decimal digits)
// 16, 15, 62, 66
Console.Write(string.Join(", ", result.Select(b => b.ToString("d2"))));
If no format provided, .Net uses default one and represents byte in decimal:
// 16, 15, 62, 66
Console.Write(string.Join(", ", result));
You're really confusing representation and numbers here.
A string like "0F" can be seen as a representation of a number in base 16, that is, in decimal representation, 16.
Which is the exact same thing as representing 16 as F or 0F or XVI or
IIIIIIIIIIIIIIII or whatever other representation you choose.
The string "0F" actually looks in memory like this
Hexadecimal representation:
0x30 0x46 0x00
Decimal representation:
48 70 0
Binary representation:
0b00110000 0b01000110 0b00000000
Byte is simply a data type which is infact a subset of an integer.
Byte takes interger values ranging from -2^7(-128) to 2^7-1$(127)
Calling Convert.ToByte(string, 16) simply converts your string to an equivalent hex value and then to an equivalent value in byte.
Note the byte data type is always an integer data but used in place of an integer just to save space in memory. As referenced above the byte datatype takes values from -128 to 127 thereby saving you more space in memory than the integer data type would.
Please Note that you are likely to run into an error if the hexadecimal value you wish to convert to byte is less than -128 or greater than 127
The link below shows an instance of this error when I try converting a string whose value when converted to hexadecimal is greater than 127.
Error when converting to Byte
You get an error whenever you do this.
I hope my answer and Dmitry Bychenko's sheds more light into your problem.
Please feel free to comment if it doesnt.
I saw this code example:
using (FileStream fStream = File.Open(#"C:\myMessage.dat", FileMode.Create))
{
string msg = "Helloo";
byte[] msgAsByteArray = Encoding.Default.GetBytes(msg);
foreach (var a in msgAsByteArray)
{
Console.WriteLine($"a: {a}");
}
// Write byte[] to file.
fStream.Write(msgAsByteArray, 0, msgAsByteArray.Length);
// Reset internal position of stream.
fStream.Position = 0;
// Read the types from file and display to console.
Console.Write("Your message as an array of bytes: ");
byte[] bytesFromFile = new byte[msgAsByteArray.Length];
for (int i = 0; i < msgAsByteArray.Length; i++)
{
bytesFromFile[i] = (byte)fStream.ReadByte();
Console.Write(bytesFromFile[i]);
}
// Display decoded messages.
Console.Write("\nDecoded Message: ");
Console.WriteLine(Encoding.Default.GetString(bytesFromFile));
And the result of Console.WriteLine($"a: {a}") is this:
a: 72
a: 101
a: 108
a: 108
a: 111
a: 111
1.
I thought byte[] is composed of many each unit of byte.
But each byte is represented in integer number.
That numbers must be corresponding ASCII characters.
In C#, byte array means data represented in ASCII?
2.
Is the file myMessage.dat composed of binary data composed of only 0 and 1?
But when I open myMessage.dat with the text editor, it's showing Helloo text string. What's the reason for this?
A byte is a 8bit integer with values from 0 to 255. The output to console outputs the normal number, by providing a format string (https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings) you can output as hex. You can use this answer to get the binary representation.
You explicitly converted the "Halloo" to bytes with Encoding.Default.GetBytes() - that is kindof like converting it to its ascii value but heeding the default encoding on your system.
Your texteditor interpretes the data of the file and displays it as it can. If you put a byte[] myBytes = new [] {0,7,12,3,9,30} into a file and open that with your textedit you will get nonreadable texts as "normal text" starts around 32 , before are f.e. tabs, bells, line feeds and other special non printable characters. See f.e. NonPrintableAscii
I have a windows form where you can input text in one textbox, and it outputs the conversion in the other textbox. I have various conversions.
say I input "hello world"
my ascii to bytes function gives me back: 10410110810811132119111114108100
all is good. now I need to use my bytes to ascii function to convert it back.
the problem is that
byte[] b;
b = ASCIIEncoding.ASCII.GetBytes(plaintext); //it is a string from the textbox
OK, MOSTLY SOLVED, BUT, the problem still remains, input "1101000 1100101" as a string, parse as bytes/ byte array, and then get a string out of it. (I know the last part)
UPDATE
From binary input string to ASCII string
using System;
using System.Linq;
public class Program
{
public static void Main()
{
string input = "1101000 1100101 1101100 1101100 1101111 100000 1110111 1101111 1110010 1101100 1100100";
string[] binary = input.Split(' ');
Console.WriteLine(String.Join("", binary.Select(b => Convert.ToChar(Convert.ToByte(b, 2))).ToArray()));
}
}
Results:
hello world
Demo
OLD ANSWER
So now it sounds like you want to convert your string to binary and then from binary back to a string. From my OLD ANSWER, you can use the Select() (LINQ) statement to convert your string to a binary string array.
Once you have a binary string array, to convert it back you have to convert each element to a byte from base 2, then convert the byte to a char resulting in a char[], from which can be converting back to a string. No padding is necessary.
using System;
using System.Linq;
using System.Text;
public class Program
{
public static void Main()
{
string input = "hello world";
byte[] inputBytes = ASCIIEncoding.ASCII.GetBytes(input);
// Decimal display
Console.WriteLine(String.Join(" ", inputBytes));
// Hex display
Console.WriteLine(String.Join(" ", inputBytes.Select(ib => ib.ToString("X2"))));
// Binary display
string[] binary = inputBytes.Select(ib => Convert.ToString(ib, 2)).ToArray();
Console.WriteLine(String.Join(" ", binary));
// Converting bytes back to string
Console.WriteLine(ASCIIEncoding.ASCII.GetString(inputBytes, 0, inputBytes.Length));
// Binary to ASCII (This is what you're looking for)
Console.WriteLine(String.Join("", binary.Select(b => Convert.ToChar(Convert.ToByte(b, 2)))));
}
}
Results:
104 101 108 108 111 32 119 111 114 108 100
68 65 6C 6C 6F 20 77 6F 72 6C 64
1101000 1100101 1101100 1101100 1101111 100000 1110111 1101111 1110010 1101100 1100100
hello world
hello world
Demo
The inverse to ASCIIEncoding.ASCII.GetBytes(string) is ASCIIEncoding.ASCII.GetString(bytes[]):
string plaintext = "hello world";
byte[] b = ASCIIEncoding.ASCII.GetBytes(plaintext);
Console.WriteLine(b); // new bytes[] { 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 }
string s = ASCIIEncoding.ASCII.GetString(b);
Console.WriteLine(s); // "hello world"
how the heck does ASCIIEncoding.ASCII.GetBytes("hello world") give me back 10410110810811132119111114108100?! that's not binary!
It does not give you that number. It gives you a byte array; an array of bytes. And a byte is a number between 0 and 255 (which can be stored in one byte, hence them name). What did you expect? A string containing only 1 and 0 characters? That’s not binary either; that’s a string.
You can use Convert.ToString to get a binary string from a single byte:
Console.WriteLine(Convert.ToString(104, 2)); // "1101000"
Note that you need to left-pad those strings to make them use 8 characters.