Tengo una bastante grande .mdb
base de datos de acceso Quiero convertir a SQLite3 para usarlo bajo Linux.
Soy incapaz de transferir cualquiera de los BLOB
s (en su mayoría contienen imágenes) que tengo. Aquí es un programa de prueba de muestra:
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();
}
}
}
El programa se ejecuta sin errores, pero los archivos son producidos "extraño" (seguramente no imágenes):
$ 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
Mirando int ellos me parece esto:
....sr..net.ucanaccess.jdbc.BlobKey...........L.
columnNamet..Ljava/lang/String;L..keyt..Ljava/util/HashMap;L. tableNameq.~..xpt..Imagesr..java.util.HashMap......`....F.
loadFactorI. [email protected].⠤...8...I..valuexr..java.lang.Number...........xp...
Ht..Indexsr..java.lang.ShorthM7.4`.R...S..valuexq.~. ..xt..PersonImage
¿Qué estoy haciendo mal?
Actualización: Desde mi objetivo es convertir una base de datos de libros (mantenida en la red como .mdb utilizando el programa obsoleto BookCAT por razones históricas) encontré AccessConverter que parece ajustarse a la ley; por desgracia, hay esencialmente dos problemas con eso:
- En mi base de datos de algunas columnas se denominan "índice", que es una palabra reservada para SQLite (y otros, pero al parecer no para MS-Access); este se fija trivialmente la inserción de un filtro "Índice" -> "Idx".
- Hay una traducción
switch (type) { case xxx: ...
para convertir los diversos tipos de MS-Access a tipos SQLite3 más convencionales; breakpointing en ladefault:
etiqueta descubrí (como @ErikvonAsmuth supuso correctamente) hay no controladasOLE
tipos. No tengo ni idea de cómo manejar los.
En el programa (BookCAT) esos campos contienen dos tipos de datos:
- imágenes
- texto con formato
Este último es menos importante porque siempre hay un duplicado "texto plano" versión (que sería bueno para recuperar también la versión con formato, pero ...).
Realmente me gustaría ser capaz de extraer las imágenes, sin embargo.
En los datos de imagen hay una columna compañera "ImageType" siempre se ajusta a "2", que (si no me equivoco) significa que deben ser .jpeg
imágenes.
¿Qué puedo hacer para recuperar los OLE
datos en un formato utilizable?
Nota: AccessConverter
no utiliza ucanaccess
, se usa directamente el subyacente com.healthmarketscience.jackcess
lib lugar.
Nota 2: parece que BookCAT
se construye a partir de Delphi, si eso es relevante.
Resulta que, en mi caso concreto, todos los campos "OLE" son en realidad BLOB, irreconocible como objetos OLE2.
En esta condición Jackcess devuelve un Enum OleBlob.ContentType.UNKNOWN
tipo y, en este caso, que se niegan a acceder al contenido BLOB ( OleBlob.content.getBytes()
retornos null
).
Con el fin de acceder a los datos almacenados es necesario utilizar directamente Column.getBytes(name)
(sin pasar por completo subsistema de OLE).
Por eso, en esta condición, ucanaccess
devuelve un valor no válido, en lugar de fracaso, está más allá de mí (que probablemente debería presentar un informe de error; los comentarios son bienvenidos).
Los datos de imagen es un archivo sin formato JPEG con formato, mientras que el "texto con formato" parece que algunos de serialización personalizado de Delphi TRichText
Widget No sé cómo analizar, pero eso es otro tema.
Utilizando jackcess
Column.getBytes(name)
yo era capaz de recuperar los datos que necesitaba.