我有一个非常痛苦的库,目前正在接受一个C#字符串作为获取数据数组的方法;显然,这使得针对pinvokes的编组更容易。
那么如何按字节将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 ++中的char *,那么这将更加容易......
编辑:函数调用是
DataElement.SetByteValue(string inArray, VL Length);
其中VL是'值长度',DICOM类型,并且函数本身是由SWIG生成的C ++库的包装器。似乎选择的表示是字符串,因为它可以相对容易地跨越托管/非托管边界,但是在项目的整个C ++代码中(这是GDCM),char *只是用作字节缓冲区。所以,当你想设置图像缓冲区指针时,在C ++中它很简单,但在C#中,我遇到了这个奇怪的问题。
这是hackeration,我知道最好的办法是让SWIG库正常工作。我真的不知道该怎么做,而是宁愿在C#方面快速解决,如果存在的话。
答案 0 :(得分: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 *的形式获取数组的开头,并将其强制转换为char *,然后将其传递给字符串构造函数,如下所示:
string asString;
unsafe
{
fixed (ushort *dataPtr = &data[0])
asString = new string((char *) dataPtr, 0, data.Length);
}
答案 1 :(得分:1)
你可以做的一件事就是从使用字符串切换到stringBuilder,它将极大地提高性能。
如果您愿意使用不安全的代码,您可以使用指针并像c ++一样实现您的c#代码。或者您可以编写一个实现此功能的小型c ++ \ cli dll。
答案 2 :(得分:1)
仅供参考,这已在后期修订版(gdcm 2.0.10)中修复。看这里:
- &GT; http://apps.sourceforge.net/mediawiki/gdcm/index.php?title=GDCM_Release_2.0
答案 3 :(得分:0)
我不喜欢这么多,但似乎有以下假设:
1。每个ushort都是0到127之间的ASCII字符
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);
我确信有更好的方法可以做到这一点,但这是我能够快速提出来的。
答案 4 :(得分: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);
答案 5 :(得分:0)
您可以通过这种方式避免不必要的复制:
public static class Helpers
{
public static string ConvertToString(this ushort[] uSpan)
{
byte[] bytes = new byte[sizeof(ushort) * uSpan.Length];
for (int i = 0; i < uSpan.Length; i++)
{
Unsafe.As<byte, ushort>(ref bytes[i * 2]) = uSpan[i];
}
return Encoding.Unicode.GetString(bytes);
}
}