C# convert byte[] containing a c-style string to string - NOT Encoding.GetString(byte[])
stupid me tries to convert a byte-array received from an external source not unter my control to a string. (And yes, I do know about Encoding.GetString(byte[])
.
What I have so far:
void myfunc()
{
byte[] rawData = new byte[ 128 ];
for( int i = 0; i < rawData.Length; ++i )
{
rawData[ i ] = 0;
}
rawData[ 0 ] = (byte)'H';
rawData[ 1 ] = (byte)'e';
rawData[ 2 ] = (byte)'l';
rawData[ 3 ] = (byte)'l';
rawData[ 4 ] = (byte)'o';
string asString = Encoding.UTF8.GetString( rawData, 0, rawData.Length );
string asRealString = Encoding.UTF8.GetString( ra开发者_如何学PythonwData );
}
Both strings do contain the Hello part but also a lot of \0's afterwards - which is not the thing I expected. The output from the debugger: asRealString =
"Hello\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
Is there any way that would geive me a string like "Hello" ?
I did goolge,but all I got was Encoding.GetString(byte[])
...
EDIT: The creatin of the byte array is outside my scope! I do get it as part of a larger, C-Style struct. And there is no leading length of the string. Also I was hoping there iss ome built in way to tdo it and I did not have to find the first \o and tehn convert knowing the length....
EDIT Here is what I used in the end:
private static string convertCString( byte[] buffer, int maxLength, Encoding targetEncoding )
{
int length = 0;
int realMax = buffer.Length < maxLength ? buffer.Length : maxLength;
for(
; 0 != buffer[length] && length < realMax
; ++length )
{}
return targetEncoding.GetString( buffer, 0, length );
}
Just find the first 0
:
int len = Array.IndexOf(rawData, (byte)0); // maybe some bounds check too
string asString = Encoding.UTF8.GetString(rawData, 0, len);
Try
Encoding.UTF8.GetString( rawData ).Trim();
The creatin of the byte array is outside my scope! I do get it as part of a larger, C-Style struct. And there is no leading length of the string.
It may be possible to do this in a built-in way by having the marshaller do it for you.
I'm assuming that what you have now is like:
struct CStruct
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=128)]
public byte[] data;
}
Try changing it to:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
struct CStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string data;
}
Why didn't you expect that? You explicitly told it to do that to start with:
byte[] rawData = new byte[ 128 ];
for( int i = 0; i < rawData.Length; ++i )
{
rawData[ i ] = 0; // RIGHT HERE
}
The above code creates a 128 item byte array and the for loop populates it. Then your code explicitly changes the value of the first 5 bytes. If you don't want to see the \0, then you need either not to put it there or exclude it from the array before sending it to GetString
.
When you do
string asString = Encoding.UTF8.GetString( rawData, 0, rawData.Length );
Instead of passing in rawData.Length
, can you not just pass in the actual length of the string?
new string(Array.ConvertAll(rawData, x => (char)x))
The string constructor will terminate the string at the first \0.
void myfunc()
{
byte[] rawData = new byte[ 128 ];
//CLR will initialize each elemnet in arry to the 0
//for( int i = 0; i < rawData.Length; ++i )
//{
// rawData[ i ] = 0;
//}
rawData[ 0 ] = (byte)'H';
rawData[ 1 ] = (byte)'e';
rawData[ 2 ] = (byte)'l';
rawData[ 3 ] = (byte)'l';
rawData[ 4 ] = (byte)'o';
// you should know length of the received string (each IO read method return number of read bytes), if you don't know it you can try to search 0 as the EOS
var receivedBytes = Array.IndexOf(rawData, 0);
string asString = Encoding.ASCII.GetString( rawData, 0, receivedBytes );
}
精彩评论