2013-11-27 2 views
2

Я пишу скрипт миграции Java (ok, Groovy, но это не имеет значения) для копирования полей BLOB из базы данных Oracle10g в другую. Данные были созданы приложением MS Access. У файлов, похоже, есть некорректная кодировка, и я предполагаю, что MS Access или драйвер ODBC каким-то образом управляют файлом.Доступ к BLOBS в базе данных Oracle10g, созданной с помощью MS Access

Использование запроса SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_CHARACTERSET'; Я узнал, что исходная база данных имеет набор символов WE8MSWIN1252.

Таблица источника определяется как:

CREATE TABLE CTR_DOCUMENTS (
    CTR_ID  NUMBER(11)   NOT NULL, 
    CTR_A_ID  NUMBER(11), 
    CTR_FILENAME VARCHAR2(260 Char) NOT NULL, 
    CTR_COMMENT VARCHAR2(255 Char), 
    CTR_DATE  DATE, 
    CTR_DATA  BLOB 
) 

я получить доступ к сгустки так:

def blob = sourceDB.firstRow("SELECT CTR_DATA FROM CTR_DOCUMENTS WHERE CTR_ID = ?", 
    [id]).CTR_DATA 
def blobSize = blob.length() 
def blobStream = blob.getBinaryStream() 
byte[] byteArray = new byte[blobSize] 
blobStream.read(byteArray) 

я сохранил некоторые из сгустков в виде файлов, и кодирование выглядит странно и файлы не могут открываться их программами. Второй байт всегда 00:

0000000: 2500 5000 4400 4600 2d00 3100 2e00 3500 %.P.D.F.-.1...5. 

Я также наблюдать такое же поведение доступа к BLOBS с SQL Client (SQL Инструментальные средства/J, SQLDeveloper, ЖАБЫ).

Для меня это похоже на то, что мне нужно преобразовать файл из Windows-1252 в UTF8, но это не сработает. Я что-то упустил?

+4

BLOB, которые являются двоичными файлами, не должны иметь кодировку символов. CLOB, которые представляют текст, могут иметь кодировку. – GriffeyDog

+0

Можете ли вы добавить определение таблицы Oracle на свой вопрос? – ThinkJet

+0

Скопировали файлы в другую базу данных Oracle? Если да, почему бы не использовать ссылку базы данных? См. Http://stackoverflow.com/questions/6022706/is-there-a-way-to-copy-blob-records-between-databases-in-oracle-10g –

ответ

2

Где бы я начал, для диагностических целей, если не что иное, было бы сканирование массивов байтов из образца входных BLOB, чтобы увидеть, был ли каждый второй байт фактически 0x00 и записывал каждый другой (ненулевой) байт к массиву байтов bytesOut. В случае успеха я буду писать массивы bytesOut в файлы и посмотреть, действительно ли они являются действительными документами PDF. Например:

public static void main(String[] args) { 
    try { 
     String connectionUrl = ""; 
     connectionUrl = 
       "jdbc:sqlserver://localhost;" + 
       "instanceName=SQLEXPRESS;" + 
       "databaseName=myDb;" + 
       "integratedSecurity=true"; 
     Connection con = DriverManager.getConnection(connectionUrl); 

     String SQL = 
       "SELECT CTR_ID, CTR_FILENAME, CTR_DATA " + 
       "FROM CTR_DOCUMENTS " + 
       "WHERE CTR_ID BETWEEN 1 AND 5"; 
     Statement stmt = con.createStatement(); 
     ResultSet rs = stmt.executeQuery(SQL); 

     while (rs.next()) { 
      boolean writeFile = true; 
      byte[] bytesIn = rs.getBytes("CTR_DATA"); 
      //scan input byte array and copy every second byte to output byte array 
      byte[] bytesOut = new byte[bytesIn.length/2]; 
      for (int i = 0; i < bytesIn.length; i++) { 
       if ((i % 2) == 1) { 
        if (bytesIn[i] != 0x00) { 
         System.out.println(String.format("Darn. bytesIn value at offset %d is not 0x00. Skipping...", i)); 
         writeFile = false; 
         break; 
        } 
       } 
       else { 
        bytesOut[i/2] = bytesIn[i]; 
       } 
      } 
      if (writeFile) { 
       String outFile = 
         "C:\\__tmp\\pdfTest\\" + rs.getString("CTR_FILENAME"); 
       FileOutputStream fos = new FileOutputStream(outFile); 
       fos.write(bytesOut); 
       fos.close(); 
       System.out.println(String.format("\"%s\" created.", outFile)); 
      } 
     } 
     rs.close(); 
     con.close(); 
    } catch(Exception e) { 
     System.out.println(e.getMessage()); 
     System.exit(0); 
    } 
} 

Полагают, что если где-то по пути, какой-то процесс взял то, что он думал, был «строка» однобайтовых символов (например, Windows-1252) и преобразуется в Unicode (например, , UCS-2LE), просто вставив 0x00 после каждого символа (без каких-либо манипуляций с фактическими байтами данных), самым простым решением было бы просто вернуть эти 0x00 байтов.

Смежные вопросы