简体   繁体   English

SQL Server VARBINARY(max) 到 c# byte[]

[英]SQL Server VARBINARY(max) to c# byte[]

I am querying the table (one of the columns is a VARBINARY(MAX) ) which returns some records.我正在查询返回一些记录的表(其中一列是VARBINARY(MAX) )。

Then I save that as.dat.csv then I parse through that.dat file and get that varbinary value into a string by splitting the file based on commas.然后我将其保存为 as.dat.csv,然后我解析 that.dat 文件并通过基于逗号拆分文件来将该 varbinary 值转换为字符串。 Now I need to convert this varbinary to byte array.现在我需要将这个 varbinary 转换为字节数组。 How can I do that?我怎样才能做到这一点?

Good question.好问题。 Technically, you can do this by first converting to a character array, then converting to bytes.从技术上讲,您可以先转换为字符数组,然后再转换为字节。 However, strings in .NET are Unicode-encoded by default (instead of ASCII), so it gets tricky.但是,.NET 中的字符串默认采用 Unicode 编码(而不是 ASCII),因此它变得棘手。

If at all possible, you should try to pull the varbinary out of the file as a byte array, using the FileStream you're reading from instead of the StreamReader which performs encoding conversions to and from the file encoding type.如果可能的话,您应该尝试将 varbinary 作为字节数组从文件中提取出来,使用您正在读取的 FileStream 而不是执行与文件编码类型之间的编码转换的 StreamReader。

The problem with this byte-to-string-to-byte babelfishing is that certain bytecodes have special meaning in each Unicode encoding, giving information to the decoder about the number of bytes it should pull to decode the next character.这种字节到字符串到字节的 babelfishing 问题在于某些字节码在每种 Unicode 编码中具有特殊含义,向解码器提供有关解码下一个字符应该提取的字节数的信息。 When converting between various Unicode encodings and the .NET-native UTF-8 encoding for strings, bytes will be gained, lost, and changed.在各种 Unicode 编码和字符串的 .NET 原生 UTF-8 编码之间进行转换时,将获得、丢失和更改字节。 When it's a string, no biggie;当它是一个字符串时,没什么大不了的; the encoding information stays with the string.编码信息保留在字符串中。 When it's binary data, the encoding and decoding can garble it unless it's done in a very specific way.当它是二进制数据时,除非以非常特定的方式完成,否则编码和解码可能会产生乱码。

The only way this will work flawlessly is if you write the file out using ASCII encoding, then read it back in as such, which will cause each individual byte to be treated as a single character.这将完美工作的唯一方法是,如果您使用 ASCII 编码写出文件,然后将其读回,这将导致每个单独的字节被视为单个字符。 You can then simply convert each char back to a byte, and the more significant byte of the UInt16 behind the scenes of the Syetem.Char, which is just zero-padding for the byte fed in to that char, will be discarded.然后,您可以简单地将每个 char 转换回一个字节,并且在 Syetem.Char 的幕后 UInt16 的更重要的字节,它只是为输入该 char 的字节填充零,将被丢弃。

var reader = new StreamReader(new FileStream("test.csv"), Encoding.ASCII);
var varBinaryString = reader.Read(<wherever the varbinary is in the file/line>);

var byteArray = varBinaryString.ToCharArray().Select(c=>(byte)c).ToArray();

Technically, you could pull it in using any Unicode encoding as well, but you need to know a lot of specifics about how you wrote out those bytes and how the reader is reading them back in, so that you can perform the correct encoding and expansion (or deflation) as necessary to get the original bytestream.从技术上讲,您也可以使用任何 Unicode 编码将其拉入,但您需要了解很多有关如何写出这些字节以及读者如何读回它们的细节,以便您可以执行正确的编码和扩展(或通缩)以获取原始字节流。

EDIT: The .NET 2.0 version - no Linq:编辑: .NET 2.0 版本 - 无 Linq:

StreamReader reader = new StreamReader(new FileStream("test.csv"), Encoding.ASCII);
string varBinaryString = reader.Read(<wherever the varbinary is in the file/line>);

char[] charArray = varBinaryString.ToCharArray();
byte[] byteArray = new byte[charArray.Length];

for(int i=0; i< charArray.Length; i++)
{
    byteArray[i] = (byte)charArray[i];
}

I have founded more simple solution for the case when you have only one or serveral values in SQL resultset and don't want to convert it to *.csv and so on.当您在 SQL 结果集中只有一个或多个值并且不想将其转换为 *.csv 等时,我已经找到了更简单的解决方案。

The case when copy-pasting the SQL-varbinary-values is acceptable.复制粘贴 SQL-varbinary-values 的情况是可以接受的。

using System;
using System.Text;

namespace TestProj
{
    class Program
    {
        static void Main(string[] args)
        {
            //the value from database (Ctrl+C & Ctrl+V)
            string varbinaryStr = "0x7B2255";  

            //remove '0x' prefix AND trailing spaces
            var no_0x_varbinary_str = varbinaryStr.Replace("0x", "").Trim();

            //the bytes
            byte[] bytes = StrToByteArray(no_0x_varbinary_str);
            
            //now you can work with the bytes as you need
            //in my case there was an UTF8-string that have been saved in SQL as varbinary
            //so I am just decode it like this
            var string_from_database = Encoding.UTF8.GetString(bytes);
            
            Console.ReadKey();
        }
        
        static byte[] StrToByteArray(string str)
        {
            Dictionary<string, byte> hexindex = new Dictionary<string, byte>();
            for (int i = 0; i <= 255; i++)
                hexindex.Add(i.ToString("X2"), (byte)i);

            List<byte> hexres = new List<byte>();
            for (int i = 0; i < str.Length; i += 2)
                hexres.Add(hexindex[str.Substring(i, 2)]);

            return hexres.ToArray();
        }
    }
}

The example of string to byte[] convertion that have been used in StrToByteArray I found in this question where you can find other refference to the discussion of the fastest convertion way (with examples and tests).我在这个问题中找到了在StrToByteArray中使用的stringbyte[]转换的示例,您可以在其中找到对最快转换方式(带有示例和测试)的讨论的其他参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM