如何使用 C# 从 Firebird 读取二进制 blob 到 byte[]?
How to read binary blob from Firebird to byte[] with C#?
我对 C# 的了解很差,但我需要编写代码,将二进制 blob 读取到 byte[]
。
我写了这段代码:
byte[] userBlob;
myCommand.CommandText = "SELECT id, userblob FROM USERS";
myCommand.Connection = myFBConnection;
myCommand.Transaction = myTransaction;
FbDataReader reader = myCommand.ExecuteReader();
try
{
while(reader.Read())
{
Console.WriteLine(reader.GetString(0));
userBlob = // what I should to do here??
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine("Can't read data from DB");
}
但是我应该放在这里什么?据我了解,我需要使用流,但我不知道该怎么做。
byte[] toBytes = Encoding.ASCII.GetBytes(string);
所以,在你的情况下;
userBlob = Encoding.ASCII.GetBytes(reader.GetString(0));
但是,我不确定您试图用您的代码实现什么,因为您正在撤回所有用户,然后一遍又一遍地创建 blob。
比赛有点晚了;我希望这是对的。
我假设您使用的是 Firebird .NET 提供程序,它是一个 C# 实现,不基于本机 fbclient.dll
。不幸的是,它没有为 BLOB 提供流接口,这将允许在不耗尽内存的情况下读取潜在的大数据块。
相反,您使用 FbDataReader.GetBytes()
方法读取数据,并且所有数据都必须适合内存。 GetBytes
获取用户提供的缓冲区并将 BLOB 数据填充到引用的位置,它 returns 它实际复制的字节数(可能小于完整大小)。
将 null
缓冲区传递给 GetBytes
returns BLOB 的完整大小(但没有数据!)以便您可以根据需要重新分配。
这里我们假设您有一个用于字段 #0 的 INT(不感兴趣)和用于 #1 的 BLOB,并且这个天真的实现应该会处理它:
// temp buffer for all BLOBs, reallocated as needed
byte [] blobbuffer = new byte[512];
while (reader.Read())
{
int id = reader.GetInt32(0); // read first field
// get bytes required for this BLOB
long n = reader.GetBytes(
i: 1, // field number
dataIndex: 0,
buffer: null, // no buffer = size check only
bufferIndex: 0,
length: 0);
// extend buffer if needed
if (n > blobbuffer.Length)
blobbuffer = new byte[n];
// read again into nominally "big enough" buffer
n = reader.GetBytes(1, 0, blobbuffer, 0, blobbuffer.Length);
// Now: <n> bytes of <blobbuffer> has your data. Go at it.
}
可以对此进行一些优化,但 Firebird .NET 提供程序确实需要像本机 fbclient.dll 提供的流式 BLOB 接口。
我对 C# 的了解很差,但我需要编写代码,将二进制 blob 读取到 byte[]
。
我写了这段代码:
byte[] userBlob;
myCommand.CommandText = "SELECT id, userblob FROM USERS";
myCommand.Connection = myFBConnection;
myCommand.Transaction = myTransaction;
FbDataReader reader = myCommand.ExecuteReader();
try
{
while(reader.Read())
{
Console.WriteLine(reader.GetString(0));
userBlob = // what I should to do here??
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine("Can't read data from DB");
}
但是我应该放在这里什么?据我了解,我需要使用流,但我不知道该怎么做。
byte[] toBytes = Encoding.ASCII.GetBytes(string);
所以,在你的情况下;
userBlob = Encoding.ASCII.GetBytes(reader.GetString(0));
但是,我不确定您试图用您的代码实现什么,因为您正在撤回所有用户,然后一遍又一遍地创建 blob。
比赛有点晚了;我希望这是对的。
我假设您使用的是 Firebird .NET 提供程序,它是一个 C# 实现,不基于本机 fbclient.dll
。不幸的是,它没有为 BLOB 提供流接口,这将允许在不耗尽内存的情况下读取潜在的大数据块。
相反,您使用 FbDataReader.GetBytes()
方法读取数据,并且所有数据都必须适合内存。 GetBytes
获取用户提供的缓冲区并将 BLOB 数据填充到引用的位置,它 returns 它实际复制的字节数(可能小于完整大小)。
将 null
缓冲区传递给 GetBytes
returns BLOB 的完整大小(但没有数据!)以便您可以根据需要重新分配。
这里我们假设您有一个用于字段 #0 的 INT(不感兴趣)和用于 #1 的 BLOB,并且这个天真的实现应该会处理它:
// temp buffer for all BLOBs, reallocated as needed
byte [] blobbuffer = new byte[512];
while (reader.Read())
{
int id = reader.GetInt32(0); // read first field
// get bytes required for this BLOB
long n = reader.GetBytes(
i: 1, // field number
dataIndex: 0,
buffer: null, // no buffer = size check only
bufferIndex: 0,
length: 0);
// extend buffer if needed
if (n > blobbuffer.Length)
blobbuffer = new byte[n];
// read again into nominally "big enough" buffer
n = reader.GetBytes(1, 0, blobbuffer, 0, blobbuffer.Length);
// Now: <n> bytes of <blobbuffer> has your data. Go at it.
}
可以对此进行一些优化,但 Firebird .NET 提供程序确实需要像本机 fbclient.dll 提供的流式 BLOB 接口。