java - UCanAccess 似乎无法使用 getBytes() 读取 OLE 对象列
问题描述
我有一个非常大的.mdb
访问数据库,我想将其转换为 SQLite3 以在 Linux 下使用它。
我无法转移BLOB
我拥有的任何 s(主要包含图像)。这是一个示例测试程序:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class prova {
public static void main(String[] args) {
String url = "jdbc:ucanaccess://data/BookDB-201810.mdb";
try {
Connection c = DriverManager.getConnection(url);
PreparedStatement ps;
ResultSet rs;
String q = "SELECT * FROM PersonImage";
ps = c.prepareStatement(q);
rs = ps.executeQuery();
while (rs.next()) {
byte[] i = rs.getBytes("Image");
String fn = String.format("data/img/i%05d.%d.jpg", rs.getInt("PersonId"), rs.getInt("Index"));
try (FileOutputStream fos = new FileOutputStream(fn)) {
fos.write(i);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
程序运行没有错误,但生成的文件是“奇怪的”(肯定不是图像):
$ ls -l i00072.1.jpg
-rw-r--r-- 1 mcon mcon 369 Nov 23 11:38 i00072.1.jpg
$ file i00072.1.jpg
i00072.1.jpg: Java serialization data, version 5
看着他们,我发现:
....sr..net.ucanaccess.jdbc.BlobKey...........L.
columnNamet..Ljava/lang/String;L..keyt..Ljava/util/HashMap;L. tableNameq.~..xpt..Imagesr..java.util.HashMap......`....F.
loadFactorI. thresholdxp?@......w.........t..PersonIDsr..java.lang.Integer.⠤...8...I..valuexr..java.lang.Number...........xp...
Ht..Indexsr..java.lang.ShorthM7.4`.R...S..valuexq.~. ..xt..PersonImage
我究竟做错了什么?
更新: 由于我的目标是转换书籍数据库(由于历史原因,使用过时的程序BookCAT在网上以 .mdb 形式维护)我发现AccessConverter似乎符合要求;不幸的是,这基本上有两个问题:
- 在我的数据库中,一些列被命名为“索引”,这是 SQLite(和其他,但显然不是 MS-Access)的保留字;插入过滤器“Index”->“Idx”可以轻松解决这个问题。
- 有一个转换
switch (type) { case xxx: ...
可以将各种 MS-Access 类型转换为更传统的 SQLite3 类型;我发现的标签上的断点default:
(正如@ErikvonAsmuth 正确猜测的那样)有未处理的OLE
类型。我不知道如何处理这些。
在程序 (BookCAT) 中,这些字段包含两种数据:
- 图片
- 格式化文本
后者不太重要,因为总是有一个重复的“纯文本”版本(最好也检索格式化版本,但是......)。
不过,我真的很希望能够提取图像。
在图像数据中有一个伴随的“ImageType”列总是设置为“2”(如果我没记错的话)意味着它们应该是.jpeg
图像。
如何以OLE
可用格式检索数据?
注意: AccessConverter
不使用ucanaccess
,而是直接使用底层com.healthmarketscience.jackcess
库。
注意2:它似乎BookCAT
是使用 Delphi 构建的,如果相关的话。
解决方案
事实证明,在我的具体情况下,所有“OLE”字段实际上都是 BLOB,无法识别为 OLE2 对象。
在这种情况下,jackcess 返回一个Enum OleBlob.ContentType.UNKNOWN
类型,在这种情况下,它将拒绝访问 BLOB 内容(OleBlob.content.getBytes()
返回null
)。
为了访问存储的数据必须直接使用Column.getBytes(name)
(完全绕过OLE子系统)。
为什么在这种情况下ucanaccess
返回无效值而不是失败,这超出了我的理解(可能我应该提交错误报告;欢迎评论)。
图像数据是纯 jpeg 格式的文件,而“格式化文本”似乎是 DelphiTRichText
小部件的一些自定义序列化,我不知道如何解析,但这是另一个问题。
使用jackcess
Column.getBytes(name)
我能够检索我需要的数据。
推荐阅读
- .net - 通过代码调整控件大小时避免控件闪烁 (.NET 4.6.1)
- scala - 为什么我的 Alpakka SFTP 连接器从不连接?
- sql - “批量查询”属于单个对象的一组孙子(has_many,has_many)的最快、最标准的方法是什么?
- php - 获取即将到来的 Stripe 发票以按比例更改数量
- .net-core - `dotnet new` 在包名称上抛出 401 未经授权而没有版本
- r - 从R中的字符串中提取数字(十进制和形式)
- python - 解析后从嵌套的 JSON 输出创建新字典
- azure - 在向 FQDN 发出 Web 请求时启动容器实例
- c - CS50“模糊”PSET 4
- c# - 使用互斥锁确保异步应用程序的单一实例