Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.NET存在字符串到字节[]转换的缺陷?_.net_String_Bytearray - Fatal编程技术网

.NET存在字符串到字节[]转换的缺陷?

.NET存在字符串到字节[]转换的缺陷?,.net,string,bytearray,.net,String,Bytearray,我在从SQL Server(2008R2)数据库中的NVARCHAR字段检索加密数据时遇到一个问题,对于某些记录,我的C#.NET应用程序中的数据字符串值与数据库记录中的数据字符串值不同。这很难证明,但我最终发现,通过查看字符串的byte[]表示,确实存在差异 再进一步,我能够生成这个让我有点担心的测试应用程序。我获取了一个字节数组(为了简化设置,从十六进制转换而来),使用Unicode编码器将其转换为字符串,然后返回到一个字节数组,并发现生成的字节数组与原始数组不同!在下面的代码中,第一个十六

我在从SQL Server(2008R2)数据库中的NVARCHAR字段检索加密数据时遇到一个问题,对于某些记录,我的C#.NET应用程序中的数据字符串值与数据库记录中的数据字符串值不同。这很难证明,但我最终发现,通过查看字符串的byte[]表示,确实存在差异

再进一步,我能够生成这个让我有点担心的测试应用程序。我获取了一个字节数组(为了简化设置,从十六进制转换而来),使用Unicode编码器将其转换为字符串,然后返回到一个字节数组,并发现生成的字节数组与原始数组不同!在下面的代码中,第一个十六进制字符串失败,而第二个字符串工作

这里我的方法是否有问题(我不是指试图将字节数组转换为字符串),或者.NET framework中是否存在潜在的问题

using System;

namespace ByteArrayTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WindowWidth = 80;
            Console.Clear();

            foreach (string s in new string[]
                {
                    "00CD6C8300C2A2C09B9E6B1F258F7B1101000000AB4CB23EBE32F0DD",
                    "00CD6C8300C2A2C09B9E6B1F258F7B1101000000E12617F83C3F7F6A"
                }
            )
            {
                byte[] b1 = System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary.Parse(s).Value;
                string tmp = System.Text.Encoding.Unicode.GetString(b1);

                byte[] b2 = System.Text.Encoding.Unicode.GetBytes(tmp);

                Console.WriteLine("Orig: {0}", s);

                string s2 = BitConverter.ToString(b2).Replace("-", "");
                Console.WriteLine("Conv: {0}", s2);

                Console.WriteLine(s == s2 ? "EQUAL :-)" : "** NOT EQUAL **");
                Console.WriteLine();
            }

            Console.WriteLine("Press ENTER to exit...");
            Console.ReadLine();
        }
    }
}
我正在使用VS2010,并在.NET Framework 4和3.5下对此进行了测试,结果如下:

Orig: 00CD6C8300C2A2C09B9E6B1F258F7B1101000000AB4CB23EBE32F0DD
Conv: 00CD6C8300C2A2C09B9E6B1F258F7B1101000000AB4CB23EBE32FDFF
** NOT EQUAL **

Orig: 00CD6C8300C2A2C09B9E6B1F258F7B1101000000E12617F83C3F7F6A
Conv: 00CD6C8300C2A2C09B9E6B1F258F7B1101000000E12617F83C3F7F6A
EQUAL :-)

关于,

如果您试图在NVARCHAR字段中存储并非真正文本的任意不透明二进制数据,则应使用base64编码对其进行编码。试图在UTF-16中将其视为文本编码(这就是您在这里所做的)从根本上说是个坏主意,而且很可能会丢失数据。作为一个可能发生这种情况的示例,您可能会得到一个字符串,其中包含a的一半,而不包含另一半

我假设您的“加密数据”是通过调用
Encoding.Unicode.GetString(bytes)
存储的,其中
bytes
是加密数据吗?如果是这样的话,那肯定不是办法。使用:

string text = Convert.ToBase64String(bytes);
相反,在检索数据时,使用

byte[] bytes = Convert.FromBase64String(text);

或者,首先使用为二进制数据设计的数据库字段

编辑:(从我的评论中复制)您给出的示例最后失败,将U+DDF0转换为U+FFFD。这实际上正是我上面提到的场景-U+DDF0是一个“低代理项”,但它没有相应的“高代理项”,因此Encoding.GetString将该字符转换为U+FFFD,即“替换字符”,即(从)

用于替换在Unicode中值未知或不可表示的传入字符


IIRC,您可以指定
编码
在遇到错误的二进制数据(实际上就是您提供的数据)时所做的操作,并可能使其引发异常。

“或者,首先使用为二进制数据设计的数据库字段。”-听起来不错的建议!谢谢Jon,是的,我们意识到保存加密数据的数据库字段可能应该是VARBINARY类型,但话虽如此,我想我还是想知道更多关于我上面发布的具体示例的信息。@Mitch:有时使用字符串表示法会使生活更轻松-例如,剪切和粘贴很简单。但是,是的,让存储反映您试图存储的内容通常是一个很好的计划:)@MattA:我现在不在安装了.NET的机器上,所以我很难判断。如果你能将示例简化为一个数据样本,理想情况下是一个较小的样本(初始化为一个直字节数组,以便在ideone.com之类的环境下更容易进行测试),这会有所帮助。@MattA:我刚刚在ideone.com环境下试过你的测试,结果显示相等两次。你的机器上显示了什么?