1

At the first glance, my problem seems to be quite trivial. I have to read data from Firebird's database, but this database was created by someone else. Raw binary data (like pictures) is stored in BLOB SUB_TYPE TEXT instead of BLOB SUB_TYPE BINARY and this is the problem, because Firebird ADO.NET Data Provider (FirebirdSql.Data.FirebirdClient 7.10.1) converts binary data to a string and I cannot find a proper method in this driver that returns binary data as a byte array from BLOB SUB_TYPE TEXT.

I was trying to reverse binary data converted to a string by provider but without success. I use this provider in the following way (simplified example):

using var fbConnection = new FbConnection(connectionString);
fbConnection.Open();
var readCommand = new FbCommand(command, fbConnection);
var reader = readCommand.ExecuteReader();

while (reader.Read())
{
    // reader[0] contains data from column with BLOB SUB_TYPE TEXT type
    var rawData = Encoding.Default.GetBytes(reader[0].ToString());
    // ...
}

According to this post, this kind of conversion is not possible: https://stackoverflow.com/a/14168060/1281652

Theoretically, one of the workarounds is described here: https://stackoverflow.com/a/24821965 but I cannot modify this database, so in my case, it is not applicable.

How can I read this data correctly in c#?

rgb
  • 1,750
  • 1
  • 20
  • 35
  • 1
    Does `reader.GetBytes` not work? – Charlieface Feb 12 '21 at 16:37
  • @Charlieface reader.GetBytes works. I was trying to use this method before, but I did something wrong. Thank you for the answer. – rgb Feb 12 '21 at 17:33
  • 1
    If `reader.GetBytes` had not worked, you could also have explicitly cast the field to `BLOB SUB_TYPE BINARY` to ensure Firebird communicates its sub-type as BINARY. Unless a blob filter is defined, conversion from any blob type to sub-type binary will return the raw data. – Mark Rotteveel Feb 12 '21 at 19:14
  • 1
    @MarkRotteveel one would think making a connection with explicitly specifying charset a NONE or OCTETS should work too? This would be inferior solution, but just for completeness. Or would `reader[0].ToString()` fail then, falling back to UTF-8 -> UTF-16 transformation disregarding the said setting? – Arioch 'The Feb 13 '21 at 22:41
  • 2
    @Arioch'The No, that wouldn't work, because using `NONE` would still make it a BLOB SUB_TYPE TEXT, but then with its defined character set instead of the connection character set, and it is not possible to specify OCTETS as a connection character set. The point of my suggestion is to change the reported sub-type from TEXT to BINARY, in case a driver doesn't support `GetBytes` for a SUB_TYPE TEXT, but does support it for a SUB_TYPE BINARY. – Mark Rotteveel Feb 14 '21 at 08:28

1 Answers1

2

As indicated in the comments by Charlieface, you can use reader.GetBytes.

Alternatively, you can force Firebird to represent the type as binary by explicitly casting it:

cast(yourfield as BLOB SUB_TYPE BINARY)

Conversions from any blob sub-type to binary will result in the raw binary data, unless a blob filter has been defined to apply a different transformation.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197