UCanAccess, похоже, не может прочитать столбец OLE Object с помощью getBytes () - PullRequest
0 голосов
/ 23 ноября 2018

У меня довольно большая база данных .mdb доступа, которую я хочу преобразовать в SQLite3 для использования в Linux.

Я не могу передать ни одну из BLOB (в основном содержащих изображения), которые у меня есть,Вот пример тестовой программы:

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

Что я делаю не так?

Обновление: Поскольку моя цель - преобразовать базу данных книг (поддерживается в сети как .mdb с использованием устаревшейпрограмма BookCAT по историческим причинам) Я нашел AccessConverter , который, кажется, отвечает всем требованиям;к сожалению, с этим, по сути, связаны две проблемы:

  • В моей базе данных некоторые столбцы называются «Index», что является зарезервированным словом для SQLite (и других, но, очевидно, не для MS-Access);это легко исправить, вставив фильтр «Индекс» -> «Idx».
  • Существует преобразование switch (type) { case xxx: ... для преобразования различных типов MS-Access в более традиционные типы SQLite3;Точка останова на метке default:, которую я обнаружил (как правильно догадался @ErikvonAsmuth), есть необработанные типы OLE.Я понятия не имею, как с ними обращаться.

В программе (BookCAT) эти поля содержат два вида данных:

  • images
  • отформатированыtext

Последнее менее важно, потому что всегда есть дублирующая версия в виде открытого текста (было бы неплохо получить также отформатированную версию, но ...).

Я быочень хотелось бы иметь возможность извлекать изображения.

В данных изображения есть столбец «ImageType» для компаньона, неизменно установленный в «2», что (если я не ошибаюсь) означает, что они должны быть .jpeg images.

Что я могу сделать, чтобы извлечь OLE данные в удобном для использования формате?

Примечание: AccessConverter не использует ucanaccess, он используетнепосредственно базовый com.healthmarketscience.jackcess lib.

Примечание2: кажется, BookCAT создается с использованием Delphi, если это уместно.

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

С UCanAccess вам нужно использовать ResultSet#getBlob:

String q = "SELECT * FROM PersonImage";
ps = conn.prepareStatement(q);
rs = ps.executeQuery();
while (rs.next()) {
    java.sql.Blob image = rs.getBlob("Image");
    String fn = String.format("C:/Users/Gord/Pictures/i%05d.%d.jpg", rs.getInt("PersonId"), rs.getInt("Index"));
    try (FileOutputStream fos = new FileOutputStream(fn)) {
            fos.write(image.getBytes(1, (int) image.length()));
    } catch (FileNotFoundException e) {
            e.printStackTrace();
    } catch (IOException e) {
            e.printStackTrace();
    }
}
0 голосов
/ 25 ноября 2018

Оказывается, что в моем конкретном случае все поля "OLE" на самом деле являются BLOB-объектами, не распознаваемыми как объекты OLE2.

В этом состоянии jackcess возвращает тип Enum OleBlob.ContentType.UNKNOWN и, в данном случае, этооткажется от доступа к содержимому BLOB (OleBlob.content.getBytes() возвращает null).

Для доступа к хранимым данным необходимо напрямую использовать Column.getBytes(name) (полностью обходя подсистему OLE).

Почему, в этом состоянии ucanaccess возвращает недопустимое значение, а не сбой, за мной (вероятно, я должен подать отчет об ошибке; комментарии приветствуются).

Данные изображения представляют собой обычный файл в формате jpeg, в то время как«отформатированный текст» кажется некоторой пользовательской сериализацией виджета Delphi TRichText. Я не знаю, как анализировать, но это другая проблема.

Использование jackcess Column.getBytes(name) Я смог получить данные, которые янеобходимо.

...