0

An external DLL that I'm using in my C# program gives me a pointer to a location in memory. From there, I read in the following 200 bytes at that location to a byte array, and then convert it to a String.

Problem: For the most part my code works but it also reads in the values that the DLL used as padding (seems to be 205).

Attempt: I tried trimming the string by using examples from this Stack Overflow post, but the padding remained. My code is as follows:

const int BYTES_PER_DEVICE_NAME = 200;
const char PADDING_VALUE = (char)205;
const char NULL_VALUE = (char)0;

IntPtr nameAddress = (IntPtr)myDLL.GetPointer();

// Only run if the pointer is not to a null value
if (nameAddress != IntPtr.Zero)
{
    byte[] nameAsBytes = new byte[BYTES_PER_DEVICE_NAME];
    Marshal.Copy(nameAddress, nameAsBytes, 0, BYTES_PER_DEVICE_NAME);
    string nameAsString = System.Text.Encoding.UTF8.GetString(nameAsBytes).TrimEnd(new char[] { PADDING_VALUE, NULL_VALUE });

    // Add the string to deviceNames, a string array
    deviceNames[n] = nameAsString;
}

As seen below, even though I used TrimEnd() the string nameAsString still ended up containing the null and padded values.

Padded values in a String


I'm currently trying to see if I can find the index of \0 in my nameAsBytes byte array, and only parse the bytes up until that index. But still, what am I doing wrong with TrimEnd()?

0

2 Answers 2

2

Once the byte array is converted to a .NET string it is in UTF16 encoding, and char(205) won't have the effect you are looking for. Any value greater than 127 may end up mapping to a different code point post-conversion.

Try removing the 205's before converting to a string.

const int BYTES_PER_DEVICE_NAME = 200;
const char PADDING_VALUE = (char)205;
const char NULL_VALUE = (char)0;

IntPtr nameAddress = (IntPtr)myDLL.GetPointer();

// Only run if the pointer is not to a null value
if (nameAddress != IntPtr.Zero)
{
    byte[] nameAsBytes = new byte[BYTES_PER_DEVICE_NAME];
    Marshal.Copy(nameAddress, nameAsBytes, 0, BYTES_PER_DEVICE_NAME);
    byte[] cleanedBytes = nameAsBytes.Where(a => a != PADDING_VALUE); //Filter out the bad bytes
    string nameAsString = System.Text.Encoding.UTF8.GetString(cleanedBytes);

    // Add the string to deviceNames, a string array
    deviceNames[n] = nameAsString;
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can use the UTF8Encoding.GetString Method (Byte[], Int32, Int32) method : https://msdn.microsoft.com/en-us/library/kzb9f993(v=vs.110).aspx

byte[] nameAsBytes = new byte[BYTES_PER_DEVICE_NAME];
Marshal.Copy(nameAddress, nameAsBytes, 0, BYTES_PER_DEVICE_NAME);
int strlen;
for (strlen = 0; strlen < nameAsBytes.Length;strlen++)
{
  if (nameAsBytes[strlen] == 0)
    break;
}
string nameAsString = System.Text.Encoding.UTF8.GetString(nameAsBytes, 0, strlen);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.