开发者

C# convert byte[] containing a c-style string to string - NOT Encoding.GetString(byte[])

开发者 https://www.devze.com 2023-03-04 22:07 出处:网络
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[]).

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 );
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号