2

我需要从使用 InterBase 4.2.1 创建的一些旧的 interbase 数据库文件中提取数据。我正在使用 Firebird 的嵌入式版本(2.5.1 版)和 .NetProvider(2.7.0 版)。我以前从未使用过 interbase of firebird(但我对 SQL SERVER 和 SQLite 有一些经验),在浏览网络并试验了 2 天之后,我还没有找到解决方案。

数据库中的表格包含英语数据,但也包含希伯来语数据。尽管我很乐观,但我首先使用 UTF8 创建连接字符串:

FbConnectionStringBuilder builder = new FbConnectionStringBuilder();
builder.Database = m_DatabaseName;
builder.ServerType = FbServerType.Embedded;
builder.Charset = FbCharset.Utf8.ToString();

但这给了我以下例外:

bad parameters on attach or create database
CHARACTER SET Utf8 is not defined

我正确使用了 fbintl.dll。(请参阅下面我的应用程序目录和子目录中的文件)。我什至使用 ProcessMonitor 来检查 fbintl.dll 是否已加载。

fbembed.dll
firebird.log
firebird.msg
FirebirdSql.Data.FirebirdClient.dll
ib_util.dll
icudt30.dll
icuin30.dll
icuuc30.dll
MyApplication.exe
Microsoft.VC80.CRT.manifest
msvcp80.dll
msvcr80.dll
intl\fbintl.conf
intl\fbintl.dll
udf\fbudf.dll
udf\ib_udf.dll

因此,我尝试枚举FbCharset并尝试连接每个字符集,其中一半以上抛出了相同的异常,当我与其他字符集连接并查询其中一个希伯来字段(通过使用IDataReader.GetString())时,我总是得到与结果相同的垃圾. 我在连接字符串中指定什么字符集似乎并不重要,结果总是相同的,即使我根本没有指定任何字符集。

接下来,我查询了数据库中定义的字符集,SELECT RDB$CHARACTER_SET_NAME FROM RDB$CHARACTER_SETS并列举了这些字符集,尝试连接它们中的每一个,有些抛出异常,其他的给出与以前相同的结果。

我不知道创建数据库的字符集是什么,但我检查了数据库中每个字段的字符集,所有文本字段的字符集都设置为“NONE”。

SELECT r.RDB$RELATION_NAME, r.RDB$FIELD_NAME, f.RDB$FIELD_NAME, cset.RDB$CHARACTER_SET_NAME
FROM RDB$RELATION_FIELDS r
LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME
LEFT JOIN RDB$CHARACTER_SETS cset ON f.RDB$CHARACTER_SET_ID = cset.RDB$CHARACTER_SET_ID
ORDER BY r.RDB$RELATION_NAME ASC, r.RDB$FIELD_POSITION ASC

但我注意到一些系统表的文本字段具有 UNICODE_FSS 作为字符集。我已经在连接字符串中尝试过该字符集,但对于请求的文本字段,我仍然得到垃圾。

我最后一次尝试是检索字节(通过使用IDataReader.GetBytes())并自己编码字符串,但这给了我一个强制转换异常(Unable to cast object of type 'System.String' to type 'System.Byte[]'.

有人对如何读取这些数据有任何想法吗?我不需要永久转换数据库,因为一旦我提取了数据,它们将不再使用。

编辑:顺便说一句,是否有任何免费的轻量级 interbase/firebird 数据库查看器,我似乎找不到任何好的(与SQLiteSpy 相比)?

马克

4

1 回答 1

3

我找到了解决方案。

原始数据库是在代码页 1255 的 Windows 上编写的。当我现在读取数据时,c# 使用默认编码(不是 1255)生成一个 unicode 字符串。所以我只是使用默认编码将字符串解码为字节,然后使用正确的编码将字节转换为字符串。

Encoding encoding = Encoding.GetEncoding(1255);
...
if (!datareader.IsDBNull(i))
{
    string value = dataReader.GetString(i);
    if (value.Length > 0)
    {
        byte[] bytes = Encoding.Default.GetBytes(value);
        value = encoding.GetString(bytes);
    }
    // store value
 }

这个解决方案对我来说很好,但我仍然不明白为什么我不能在我的连接字符串中将“WIN1255”指定为字符集而不出现异常bad parameters on attach or create database - CHARACTER SET WIN1255 is not defined?(我什至尝试过字符集“WINDOWS1255”,但后来我得到了异常Invalid character set specified)。

于 2012-02-16T15:40:55.993 回答