GDAL GDALRATSetValueAsString() как сохранить иероглифы (С#)?

Мне нужна помощь с GDAL. Строковое значение с китайскими символами не корректно считывается/сохраняется (С#).

Для сохранения значения сетки мы используем:
  private static extern void GDALRATSetValueAsString (дескриптор IntPtr, int row, int field, [In] [MarshalAs (UnmanagedType.LPStr)] строковое значение); метод (С#), чтобы сохранить строковое значение, кажется, что этот метод сохраняет строку как строку ANSI.

ДЛЯ ЧТЕНИЯ:

private static extern IntPtr GDALRATGetValueAsString(IntPtr handle, int row, int field);

В. Пример моей строки "银行 Flamwood C2" Существует метод для получения значения по указателю (использование в методе GDALRATGetValueAsString):

var pointer = GDALRATGetValueAsString(GDALRasterAttributeTableH, row, field);
    a)    var b = Marshal.PtrToStringUni(pointer);       // value: "㼿汆浡潷摯䌠2"
    b)    var a = Marshal.PtrToStringAnsi(pointer);      // value: "??Flamwood C2"
    c)    var c = Marshal.PtrToStringAuto(pointer);      // value: "㼿汆浡潷摯䌠2"
    d)    var d = Marshal.PtrToStringBSTR(pointer);       //Throws an error out of memory.

Q: Так как я могу получить строку Unicode с сохраненным (так что я могу использовать этот Marshal.PtrToStringUni(указатель)) или, скорее всего, , как сохранить строку Unicode в GDALRAT (GDAL RAT - Таблица атрибутов растра GDAL)?

Версия GDAL: 1.11.1

Я попытался установить CharSet = CharSet.Unicode, но id не помог, все равно получить неправильную строку:

[DllImport(GdalWrapper.GdalDLL, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)] 
private static extern void GDALRATSetValueAsString(IntPtr handle, int row, int field, [In][MarshalAs(UnmanagedType.LPStr)] string value); 

Спасибо за любую помощь.

P.S. Если исходные файлы GDAL необходимо снова построить для сохранения строки в виде строки в Юникоде, то какие параметры сборки и где должны быть установлены?

Ответ 1

GDAL использует внутреннюю кодировку UTF-8 при работе со строками. Это означает, что строки должны быть преобразованы в UTF-8, прежде чем передавать их в GDAL. То же самое верно для строк вывода GDAL - перед использованием следует преобразовать из UTF-8 в локальную кодировку.

С# использует строки UTF-16, поэтому необходимо ввести преобразования в UTF-8 и обратно:

public class EncodingConverter
{
    public static string Utf16ToUtf8(string utf16String)
    {
        byte[] utf16Bytes = Encoding.Unicode.GetBytes(utf16String);
        byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes);
        return Encoding.Default.GetString(utf8Bytes);
    }

    public static string Utf8ToUtf16(string utf8String)
    {
        byte[] utf8Bytes = Encoding.Default.GetBytes(utf8String);
        byte[] utf16Bytes = Encoding.Convert(Encoding.UTF8, Encoding.Unicode, utf8Bytes);
        return Encoding.Unicode.GetString(utf16Bytes);
    }
}

Возвращаясь к вашей проблеме, японские символы будут обработаны правильно, если будет применено преобразование кодировки.

    public void SetValueAsString(int row, int field, string value)
    {
        string utf8Value = EncodingConverter.Utf16ToUtf8(value);
        GDALRATSetValueAsString(GDALRasterAttributeTableH, row, field, utf8Value);
    }

    public string GetValueAsString(int row, int field)
    {
        string value = null;

        var pointer = GDALRATGetValueAsString(GDALRasterAttributeTableH, row, field);
        if (pointer != IntPtr.Zero)
        {
            string utf8Value = Marshal.PtrToStringAnsi(pointer);
            value = EncodingConverter.Utf8ToUtf16(utf8Value);
        }
        return value;
    }

Ответ 2

Прочитайте это сначала Указание набора символов. Убедитесь, что существует версия Unicode для GDALRATGetValueAsString. Версия Unicode заканчивается символом W, например. GDALRATGetValueAsStringW. Версия ANSI заканчивается буквой A, например. GDALRATGetValueAsStringA. Если вы импортируете GDALRATGetValueAsString, кодировка будет автоматической. Неясно, к какой версии функции вы обращаетесь.