C#ushort []到字符串转换;这可能吗?

时间:2008-11-08 01:18:09

标签: c# string dicom ushort

我有一个非常痛苦的库,目前正在接受一个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#方面快速解决,如果存在的话。

6 个答案:

答案 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)中修复。看这里:

http://gdcm.sourceforge.net/

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