2008-11-08 4 views
2

У меня очень болезненная библиотека, которая в данный момент принимает строку C# как способ получения массивов данных; по-видимому, это упрощает сортировку для pinvokes.C# ushort [] преобразование строки; Это возможно?

Так как я могу сделать массив ushort в строку байтами? Я пробовал:

int i; 
String theOutData = ""; 
ushort[] theImageData = inImageData.DataArray; 
//this is as slow like molasses in January 
for (i = 0; i < theImageData.Length; i++) { 
    byte[] theBytes = System.BitConverter.GetBytes(theImageData[i]); 
    theOutData += String.Format("{0:d}{1:d}", theBytes[0], theBytes[1]); 
} 

я могу сделать это так, но это не заканчивается ничем отдаленно близко к здравому количеству времени.

Что мне здесь делать? Небезопасно? Пройти через какой-то промежуток между IntPtr?

Если бы это был символ * в C++, это было бы значительно проще ...

редактирования: вызов функции является

DataElement.SetByteValue(string inArray, VL Length); 

где VL является 'Value Length', тип DICOM , а сама функция создается как оболочка для библиотеки C++ с помощью SWIG. Кажется, что выбранное представление является строковым, потому что это может легко пересекать управляемые/неуправляемые границы, но на протяжении всего кода C++ в проекте (это GDCM) char * просто используется в качестве байтового буфера. Итак, когда вы хотите установить указатель на буфер изображения, на C++ это довольно просто, но на C# я застрял в этой странной проблеме.

Это хакерство, и я знаю, что, вероятно, лучше всего сделать библиотеку SWIG правильной. Я действительно не знаю, как это сделать, и предпочел бы быстрое обходное решение на стороне C#, если таковое существует.

ответ

6

P/Invoke может фактически обрабатывать то, что вы используете большую часть времени, используя StringBuilder для создания перезаписываемых буферов, например см. pinvoke.net on GetWindowText and related functions.

Однако, что в стороне, с данными как ushort, я предполагаю, что он закодирован в UTF-16LE. Если это так, вы можете использовать Encoding.Unicode.GetString(), но это будет вызывать массив байтов, а не массив ushort. Для того, чтобы превратить ваш ushorts в байтах, вы можете выделить отдельный массив байтов и использовать Buffer.BlockCopy, что-то вроде этого:

ushort[] data = new ushort[10]; 
for (int i = 0; i < data.Length; ++i) 
    data[i] = (char) ('A' + i); 

string asString; 
byte[] asBytes = new byte[data.Length * sizeof(ushort)]; 
Buffer.BlockCopy(data, 0, asBytes, 0, asBytes.Length); 
asString = Encoding.Unicode.GetString(asBytes); 

Однако, если небезопасный код ОК, у вас есть еще один вариант. Получите начало массива в качестве UShort *, и жесткий литой это символ *, а затем передать его в строку конструктора, например:

string asString; 
unsafe 
{ 
    fixed (ushort *dataPtr = &data[0]) 
     asString = new string((char *) dataPtr, 0, data.Length); 
} 
+0

, что получил его! Благодаря! (первая часть кажется достаточно быстрой, даже с дополнительной копией). – mmr 2008-11-08 02:29:05

+0

Использовал первый пример, и он отлично поработал. Спасибо!!! – 2016-01-27 20:08:38

1

Единственное, что вы можете сделать, это перейти от использования строки к stringBuilder, это значительно улучшит производительность.

Если вы хотите использовать небезопасный код, вы можете использовать указатели и реализовать свой код C# так же, как ваш C++. Или вы можете написать небольшую библиотеку C++ \ cli, которая реализует эту функциональность.

0

мне не нравится это много, но это, кажется, к работе с учетом следующих допущений:

1. Каждый USHORT представляет собой ASCII символ между 0 и 127

2. (Хорошо, я предполагаю, что есть только одно предположение)

 ushort[] data = inData; // The ushort array source 

     Byte[] bytes = new Byte[data.Length]; // Assumption - only need one byte per ushort 

     int i = 0; 
     foreach(ushort x in data) { 
      byte[] tmp = System.BitConverter.GetBytes(x); 
      bytes[i++] = tmp[0]; 
      // Note: not using tmp[1] as all characters in 0 < x < 127 use one byte. 
     } 

     String str = Encoding.ASCII.GetString(bytes); 

Я уверен, что есть лучшие способы сделать это, но это все, что я мог придумать быстро.

0

Посмотрите в Buffer класс:

ushort[] theImageData = inImageData.DataArray; 

byte[] buf = new byte[Buffer.ByteLength(theImageData)]; // 2 bytes per short 
Buffer.BlockCopy(theImageData, 0, buf, 0, Buffer.ByteLength(theImageData)); 

string theOutData = System.Text.Encoding.ASCII.GetString(buf); 
Смежные вопросы