【问题标题】:BCP queryout images stored in varbinary(max)BCP 查询存储在 varbinary(max) 中的图像
【发布时间】:2016-03-25 21:20:19
【问题描述】:

我正在替换一个 .net 应用程序,该应用程序使用 SqlDataReader 从数据库中提取记录。我将其替换为两部分过程,其中 SQL Server 将 BCP queryout 将来自 varbinary(max) 列的数据转换为平面文件,而 .net 应用程序将使用平面文件从 byte[] 的每一行创建 .jpg 图像那是在varbinary(max) 列中。

现有代码只是使用以下方法将该列转换为字节数组:

(byte[])reader[field];

就我而言,我正在尝试使用:

System.Encoding.Default.GetBytes(stringFromFlatFile)

但无法在 Windows 机器上查看生成的文件(错误已损坏/损坏或太大)

我已经尝试过 System.Encoding 下的每一种编码类型(Ascii、UTFX 等),但没有成功。

BCP queryout 中是否有额外的步骤,我需要在varbinary(max) 列中保留字节数组? SqlDataReader 有什么特别的事情要返回我需要添加到 .net 应用程序的字节数组吗?

【问题讨论】:

  • 查看将二​​进制 jpg 放入文件的代码。这可能会给你一个线索。 BCP 查询是否创建字节的字符串表示。所以它会有一个字符串 "0x659671" 而不是数值 65 96 71 的字节。此外,如果您有从该字段读取的现有代码,请查看它。
  • 我无权了解数据是如何放入表中的,但我同意您的做法是正确的。我创建了一个测试方法,它使用数据读取器将图像从 varbinary 字段拉入字节数组。然后我将字节数组的内存流用于系统。然后我使用 System.Drawing.Image 保存为 jpg。该图像可在 Windows 中查看。然后我使用了所有可用的编码方法从字节数组创建一个字符串。它们都不像 bcp 创建的字符串。
  • Bcp 创建一个类似于“FFD8FFE000104A46494600010100000100010000FFDB00430....”的字符串。
  • 启动了一个相关但更具体的线程:stackoverflow.com/questions/36266451/…
  • 找到了一种可行的方法.. 但一次只有一个图像/行:madhuottapalam.blogspot.com/2008/08/… 我仍然希望能够执行一系列行而不是使用光标。

标签: c# sql-server image encoding bcp


【解决方案1】:

我将其发布更多作为参考,可能会在您的特定情况下为您提供解决方案。

这已经为我 24x7x365 工作了 8 年。

我想指出从未使用过字符串转换或编码。字节始终保持为字节。

这是 VB.Net 代码

' The following code has run untouched for 6 years and gets images for me from the DB
' You may be able to see a detail that is relavent to you 
' NOTE The field binary read is by numeric field number - not by field name string
'      Notice the the buffer is grabbed in chunks into the buffer - not all at once 
'      Notice the CommandBehavior.SequentialAccess modifier
'
' There is no "conversion" of bytes thorugh any casting going on with encoding
' The bytes are left untouched 
'
' At the end is the snippit I use to write out the file to disk


Dim filledByteArray As Byte()
    filledByteArray = Nothing

Dim cn As New SqlConnection
Dim cmd As New SqlCommand 
Dim drNewPdf As SqlDataReader

            cn.ConnectionString = "MyConnectionStringHere"

            cmd.Connection = cn
            cmd.CommandText = "myStoredProcWithOneOftheFieldsIsBinary"
            cmd.CommandType = CommandType.StoredProcedure

            ' notice the command behavior argument
            cn.Open()
            drNewPdf = cmd.ExecuteReader(CommandBehavior.SequentialAccess)

            If drNewPdf.HasRows Then

                While drNewPdf.Read

            imgIdInt = drNewPdf.Item("FldNameOfInternalIntegerIdField")

                    ' - - - - - - - - - - - -  - - - - - -  -
                    ' Read the Binary Field Here
                    ' - - - - - - - - - - - -  - - - - - -  -


                    Dim ms As MemoryStream                 ' Writes the BLOB to a file (*.bmp).
                    Dim bw As BinaryWriter               ' Streams the binary data to the FileStream object.

                    Dim bufferSize As Integer = 100      ' The size of the BLOB buffer.
                    Dim outbyte(bufferSize - 1) As Byte  ' The BLOB byte() buffer to be filled by GetBytes.
                    Dim retval As Long                   ' The bytes returned from GetBytes.
                    Dim startIndex As Long = 0           ' The starting position in the BLOB output.



                    ' Create a stream to hold the output.
                    ms = New MemoryStream()
                    bw = New BinaryWriter(ms)

                    ' Reset the starting byte for a new BLOB.
                    startIndex = 0

                    ' READ THE FIELD HERE !!!! And Below in the loop
                    '5  '"ImageFieldBLOB"

                    ' Read bytes into outbyte() and retain the number of bytes returned.
                    retval = drNewPdf.GetBytes(5, startIndex, outbyte, 0, bufferSize)

                    ' Continue reading and writing while there are bytes beyond the size of the buffer.
                    Do While retval = bufferSize
                        bw.Write(outbyte)
                        bw.Flush()

                        ' Reposition the start index to the end of the last buffer and fill the buffer.
                        startIndex += bufferSize

                        ' READ THE FIELD HERE !!!!  And Above in the loop
                        '5 is the field index into the recordset - use field id 5 in this case 
                        ' Read bytes into outbyte() and retain the number of bytes returned.
                        retval = drNewPdf.GetBytes(5, startIndex, outbyte, 0, bufferSize)
                    Loop

                    ' Write the remaining buffer.
                    bw.Write(outbyte, System.Convert.ToInt32(0L), System.Convert.ToInt32(retval))
                    bw.Flush()


                    streamLEN = System.Convert.ToInt32(ms.Length)

                    filledByteArray = New Byte(streamLEN - 1) {}
                    ms.Seek(0, SeekOrigin.Begin)
                    ms.Read(filledByteArray, 0, streamLEN)


                    ' Close the output file.
                    bw.Close()
                    ms.Close()


                    ' - - - - - - - - - - - -  - - - - - -  -
                    ' End the Binary Field Read - Loop to next record -
                    ' - - - - - - - - - - - -  - - - - - -  -
                End While
            Else
                'No Rows ?

            End If


            cn.Close()
            cn.Dispose()





 ' A COMPLETELY DIFFERENT CHUNK OF CODE FOR PHYSICALLY WRITING TO DISK
            Dim outFileStream As FileStream

            outFileStream = New FileStream(selectedFileInfo.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite)

            outFileStream.Write(byteArrayFromDb, 0, byteArrayFromDb.Length)

            outFileStream.Flush()

            outFileStream.Close()

我的主要观点是,从来没有将字符串转换为字节。

【讨论】:

  • 感谢您的发帖,但我已经在 c# 中有类似的工作。我希望使用 bcp 来加快进程,结果可能不是理想的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-26
  • 1970-01-01
  • 1970-01-01
  • 2011-01-29
  • 1970-01-01
相关资源
最近更新 更多