I need to run a stored procedure from code. One of the input parameters is rowVersion of the table. rowVersion is a byte array ( {0, 0, 0, 0, 0, 0, 13, 191} that's 0x0000000000000DBF in db). So if to add rowVersion this way :
cmd.Parameters.AddWithValue("#myPKRowversion", 0x0000000000000DBF);
my sp is working. But when I'm adding it like here:
uint a = 0x0000000000000DBF;
cmd.Parameters.AddWithValue("#myPKRowversion", a);
or if I convert byte Array to string like:
string a = "0x0000000000000DBF";
cmd.Parameters.AddWithValue("#myPKRowversion", a);
my sp is not working.
What should I do to make my sp work?
I suggest you add it as a byte array. For example:
byte[] bytes = new byte[] { 0, 0, 0, 0, 0, 0, 13, 191 };
cmd.Parameters.Add("#myPKRowVersion", SqlDbType.Binary).Value = bytes;
If you're trying to specify bytes, the most natural type is a byte array...
Related
I am decoding a byte array from a derived class to string in the main class.
I get the original value in the derived class in hex
Copy all the elements to a different array in the main class
Decode the elements into strings and assign them to the elements of a new array like in the code
I am trying to apply GetString (byte[] bytes, int byteIndex, int byteCount);
Is there any simpler way to do it?
//Derived class byte:
byte[] msg = new byte[8] { 0x01, 0x08, 0x1A, 0x0B, 0xFF, 0x03, 0x31, 0x2C };
//Main Class
byte[] mainClassArray = new byte[8];
string[] ArrayToStr = new string[6];
Array.Copy(MyClass.msg, 0, mainClassArray, 0, 8);
ArrayToStr[0] = ASCIIEncoding.ASCII.GetString(mainClassArray , 0, 4); //decode first 4 and assign to the 1st element of ArrayToStr
ArrayToStr[1] = ASCIIEncoding.ASCII.GetString(mainClassArray , 4, 4); //decode last 4 and assign to the 2nd element of ArrayToStr
ArrayToStr[2] = ASCIIEncoding.ASCII.GetString(mainClassArray , 0, 4); //decode first 4 and assign to the 3rd element of ArrayToStr
ArrayToStr[3] = ASCIIEncoding.ASCII.GetString(mainClassArray , 4, 4); //decode last 4 and assign to the 4th element of ArrayToStr
ArrayToStr[4] = ASCIIEncoding.ASCII.GetString(mainClassArray , 0, 4); //decode first 4 and assign to the 5th element of ArrayToStr
ArrayToStr[5] = ASCIIEncoding.ASCII.GetString(mainClassArray , 4, 4); //decode last 4 and assign to the 6th element of ArrayToStr
I collect some large log infos using a C# tool. Therefore I searched for a way to compress that giant string and I found this snippet to do the trick:
public static string CompressString(string text)
{
byte[] buffer = Encoding.UTF8.GetBytes(text);
var memoryStream = new MemoryStream();
using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true))
{
gZipStream.Write(buffer, 0, buffer.Length);
}
memoryStream.Position = 0;
var compressedData = new byte[memoryStream.Length];
memoryStream.Read(compressedData, 0, compressedData.Length);
var gZipBuffer = new byte[compressedData.Length + 4];
Buffer.BlockCopy(compressedData, 0, gZipBuffer, 4, compressedData.Length);
Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4);
return Convert.ToBase64String(gZipBuffer);
}
After my logging action the C# tool sends this compressed String to a node.js REST interface which writes it into a database.
Now (in my naive understanding of compression) I thought that I could simply use something like the follwoing code on nodejs side to uncompress it:
zlib.gunzip(Buffer.from(compressedLogMessage, 'base64'), function(err, uncompressedLogMessage) {
if(err) {
console.error(err);
}
else {
console.log(uncompressedLogMessage.toString('utf-8'));
}
});
But I get the error:
{ Error: incorrect header check
at Zlib._handle.onerror (zlib.js:370:17) errno: -3, code: 'Z_DATA_ERROR' }
It seems that the compression method does not match with the uncompression function. I expect that anyone with compression/uncompression knowledge could maybe see the issue(s) immediately.
What could I change or improve to make the uncompression work?
Thanks a lot!
========== UPDATE ===========
It seems that message receiving and base64 decoding works..
Using CompressString("Hello World") results in:
// before compression
"Hello World"
// after compression before base64 encoding
new byte[] { 11, 0, 0, 0, 31, 139, 8, 0, 0, 0, 0, 0, 0, 3, 243, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73, 1, 0, 86, 177, 23, 74, 11, 0, 0, 0 }
// after base64 encoding
CwAAAB+LCAAAAAAAAAPzSM3JyVcIzy/KSQEAVrEXSgsAAAA=
And on node js side:
// after var buf = Buffer.from('CwAAAB+LCAAAAAAAAAPzSM3JyVcIzy/KSQEAVrEXSgsAAAA=', 'base64');
{"buf":{"type":"Buffer","data":[11,0,0,0,31,139,8,0,0,0,0,0,0,3,243,72,205,201,201,87,8,207,47,202,73,1,0,86,177,23,74,11,0,0,0]}}
// after zlib.gunzip(buf, function(err, dezipped) { ... }
{ Error: incorrect header check
at Zlib._handle.onerror (zlib.js:370:17) errno: -3, code: 'Z_DATA_ERROR' }
=============== Update 2 ==================
#01binary's answer was correct! That's the working solution:
function toArrayBuffer(buffer) {
var arrayBuffer = new ArrayBuffer(buffer.length);
var view = new Uint8Array(arrayBuffer);
for (var i = 0; i < buffer.length; ++i) {
view[i] = buffer[i];
}
return arrayBuffer;
}
// Hello World (compressed with C#) => CwAAAB+LCAAAAAAAAAPzSM3JyVcIzy/KSQEAVrEXSgsAAAA=
var arrayBuffer = toArrayBuffer(Buffer.from('CwAAAB+LCAAAAAAAAAPzSM3JyVcIzy/KSQEAVrEXSgsAAAA=', 'base64'))
var zlib = require('zlib');
zlib.gunzip(Buffer.from(arrayBuffer, 4), function(err, uncompressedMessage) {
if(err) {
console.log(err)
}
else {
console.log(uncompressedMessage.toString()) // Hello World
}
});
The snippet you found appears to write 4 extra bytes to the beginning of the output stream, containing the "uncompressed" size of the original data. The original author must have assumed that logic on the receiving end is going to read those 4 bytes, know that it needs to allocate a buffer of that size, and pass the rest of the stream (at +4 offset) to gunzip.
If you are using this signature on the Node side:
https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length
...then pass a byte offset of 4. The first two bytes of your gzip stream should be { 0x1F, 0x8b }, and you can see in your array that those two bytes start at offset 4. A simple example of the zlib header can be found here:
Zlib compression incompatibile C vs C# implementations
Is there a way in C# to convert a plain byte array to an object?
e.g given this class:
class Data
{
public int _int1;
public int _int2;
public short _short1;
public long _long1;
}
I want to basically be able to do something like this:
var bytes = new byte[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0 };
var obj = (Data)bytes;
You could try marshalling:
Declare the layout of your class as Sequential (and note that you will need to use Pack = 1):
[StructLayout(LayoutKind.Sequential, Pack = 1)]
class Data
{
public int _int1;
public int _int2;
public short _short1;
public long _long1;
}
Marshal the bytes into a new instance of the Data class:
var bytes = new byte[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0 };
GCHandle gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var data = (Data)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(Data));
gcHandle.Free();
// Now data should contain the correct values.
Console.WriteLine(data._int1); // Prints 1
Console.WriteLine(data._int2); // Prints 2
Console.WriteLine(data._short1); // Prints 3
Console.WriteLine(data._long1); // Prints 4
For convenience you could write a static method on Data to do the conversion:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
class Data
{
public int _int1;
public int _int2;
public short _short1;
public long _long1;
public static Data FromBytes(byte[] bytes)
{
GCHandle gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var data = (Data)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(Data));
gcHandle.Free();
return data;
}
}
...
var data = Data.FromBytes(new byte[] {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0});
If you really wanted to you could write an explicit operator to convert from an array of bytes, to get the syntax in your OP. I would suggest just using Data.FromBytes() which is going to be a lot clearer IMO.
Still, just for completeness:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
class Data
{
public int _int1;
public int _int2;
public short _short1;
public long _long1;
public static explicit operator Data(byte[] bytes)
{
GCHandle gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var data = (Data)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(Data));
gcHandle.Free();
return data;
}
}
...
var data = (Data)new byte[] {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0};
Use BitConverter.ToInt32/Int16/Int64 methods. You have only have to specify the starting index like:
Data data = new Data();
data._int1 = BitConverter.ToInt32(bytes, 0);
data._int2 = BitConverter.ToInt32(bytes, 4);
data._short1 = BitConverter.ToInt16(bytes, 8);
data._long1 = BitConverter.ToInt64(bytes,10);
Just remember:
BitConverter.ToInt32
The order of bytes in the array must reflect the endianness of the
computer system's architecture;
Here is a way to convert a byte array into an object.
var binaryFormatter = new BinaryFormatter();
using (var ms = new MemoryStream(bytes))
{
object obj = binaryFormatter.Deserialize(ms);
return (Data)obj;
}
There is nothing that will do the conversion in one go.
But you can build on top of BitConverter:
var d = new Data();
var sI32 = sizeof(Int32);
d._int1 = BitConverter.ToInt32(bytes, 0);
d._int2 = BitConverter.ToInt32(bytes, sI32);
d._short1 = BitConverter.ToInt16(bytes, 2*sI32);
…
I am reading a file into a byte array and converting the byte array into a string to pass into a method(I cant pass the byte array itself) and in the function definition I am reconverting the string to byte array. but both the byte arrays( before and after conversion are different)
I am using the following pilot code to test if byte arrays are same.
byte[] bytes = File.ReadAllBytes(#"C:\a.jpg");
string encoded = Convert.ToBase64String(bytes);
byte[] bytes1 = Encoding.ASCII.GetBytes(encoded);
When I use bytes in the api call, it succeds and when I use bytes1 it throws an exception. Please tell me how can I safely convert the byte array to string and back such that both arrays reman same.
Use this:
byte[] bytes = File.ReadAllBytes(#"C:\a.jpg");
string encoded = Convert.ToBase64String(bytes);
byte[] bytes1 = Convert.FromBase64String(encoded);
I'll post a response from another thread:
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
full thread here: How do I get a consistent byte representation of strings in C# without manually specifying an encoding?
This is my code:
byte[] base64String = //this is being set properly
var base64CharArray = new char[base64String.Length];
Convert.ToBase64CharArray(base64String,
0,
base64String.Length,
base64CharArray,
0);
var Base64String = new string(base64CharArray);
When i run this, I get the following error when calling Convert.ToBase64CharArray:
Either offset did not refer to a position in the string, or there is an insufficient length of destination character array. Parameter name: offsetOut
How do i fix this, so i can convert my byte array to a string, or is there a better way to convert a byte array to a string?
Why do you need the char array? Just convert your byte[] directly to a Base64 string:
string base64String = Convert.ToBase64String(myByteArray);
base64 encoding needs 4 characters to encode 3 bytes of input. you have to enlarge your output array.
here is one way you can convert byte array to string
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
you don't really need to worry about encoding.
more details can be found here
This is a simple form of doing it
string System.Text.Encoding.UTF8.GetString(YourbyteArray)