使用System.Data.SQLite支持长的unicode文件路径

时间:2012-01-13 21:05:45

标签: sqlite unicode system.data.sqlite

我正在开发一个需要能够创建和创建的应用程序。在用户定义的路径中操作SQLite数据库。我遇到了一个我不太懂的问题。我正在使用庞大的笨拙的unicode路径测试我的东西与一些非常粗略的样本数据,因为大多数问题都没有问题,但是对于其中的一个问题。

工作连接字符串的示例是:

Data Source="c:\test6\意外な高価で売れるかも? 出品は手順を覚えれば後はかんたん!\11オークションストアの出品は対象外とさせていただきます。\test.db";Version=3;

虽然失败的是

Data Source="c:\test6\意外な高価で売れるかも? 出品は手順を覚えれば後はかんたん!\22今やPCライフに欠かせないのがセキュリティソフト。そのため、現在何種類も発売されているが、それぞれ似\test.db";Version=3;

由于我无法控制的原因,我使用的是System.Data.SQLite v1.0.66.0,但我很快使用最新的v1.0.77.0进行了测试,并遇到了同样的问题。

当尝试新创建test.db文件或者我手动将其放在那里而且它试图打开时,SQLiteConnection.Open抛出一个异常只说"无法打开数据库文件&# 34;,堆栈跟踪显示它实际上是System.Data.SQLite.SQLite3.Open抛出。

有什么方法可以让System.Data.SQLite很好地使用这些路径?解决方法可能是在临时位置创建和操作我的数据库,然后将它们移动到实际存储位置,因为我可以正常创建和操作文件。这是最后的手段。

谢谢。

1 个答案:

答案 0 :(得分:4)

我猜你是在日语语言环境机器上,默认系统编码(ANSI代码页)是cp932 Japanese(≈Shift-JIS)。

第二条路径包含:

编码为字节序列:

0x83 0x5C

Shift-JIS是一种多字节编码,有时会在跟踪字节中重复使用ASCII代码单元。在这种情况下,它使用了字节0x5C,它对应于反斜杠\。 (虽然由于历史原因,这通常显示为日文字体的日元符号。)

因此,如果将此路径名传递给基于字节的API,它将在ANSI代码页中进行编码,并且您将无法区分作为目录分隔符的反斜杠与作为目录分隔符的反斜杠之间的区别。多字节编码的副作用。因此,当使用基于字节的IO方法访问时,具有以下某个字符的任何路径都将失败:

―ソЫⅨ噂浬欺圭構蚕十申曾箪貼能表暴予禄兔喀媾彌拿杤歃畚秉綵臀藹觸軆鐔饅鷭偆砡纊犾

(此外,任何包含cp932中不存在的Unicode字符的路径名都会自然失败。)

看来幕后的SQLite正在使用基于字节的IO方法来打开它所给出的文件名。这是不幸的,但在跨平台代码中非常常见,因为POSIX C标准库被定义为对文件open()等操作使用基于字节的文件名。

因此,使用C stdlib函数无法可靠地访问具有非ASCII名称的文件。这种悲惨的情况继承了使用stdlib编写的各种跨平台库和语言;只有使用特定支持Win32 Unicode文件名(例如Python)编写的工具才能可靠地访问Windows下的所有文件。

您的选择是:

  1. 根据移动/重命名建议,避免在数据库的路径名中使用非ASCII字符;

  2. 继续依赖日语系统区域设置(ANSI代码页= 932),只需重命名文件以避免上面列出的任何字符;

  3. 获取相关文件的短(8.3)文件名,并使用它而不是像c:\test6\85D0~1\22PC~1\test.db这样的真实文件。您可以使用dir /x查看短文件名。它们始终是纯ASCII,避免了编码问题;

  4. 使用GetShortPathName添加一些代码以从真实文件中获取短文件名。这是一个Win32 API,因此您需要一点help来从.NET调用它。另请注意,如果在禁用短文件名生成功能的计算机上运行,​​短文件名仍将失败;

  5. 说服SQLite添加对Windows Unicode文件名的支持;

  6. 说服微软通过对字节接口UTF-8进行默认编码来一劳永逸地解决这个问题,就像在所有其他现代操作系统上一样。