2013-04-12 34 views
6

sto cercando di modificare un PDF usando questo metodo (primo blocco di codice - utilizzando PDFStreamParser e iterazione attraverso PDFOperator, quindi l'aggiornamento COSString quando necessario):Java PDFBox - Lettura e modifica di un pdf con caratteri speciali (segni diacritici)

Ho un problema con alcuni caratteri UTF-8 (segni diacritici): quando stampo il testo che voglio aggiornare mostra come "Societ?? Ii Na? Ionale" (dove '?' È un codice come 0002 o 0004).

Le cose divertenti sono:

  1. quando scrivo il file pdf aggiornato, i personaggi sono spettacolo correttamente (anche se mi could't individuati e sostituirli)
  2. se provo a spogliare il testo usando getText di PDFTextStripper (...), il testo viene estratto perfettamente.
  3. ho provato 2 versioni pdfbox: 1.5.0 (che si comporta come descritto sopra) e 1.8.1 (dove il file PDF finale, scritto, non visualizza caratteri speciali correttamente e le stringhe "null" appaiono nel documento)

Cosa posso fare (configurare) per le classi utilizzate per aggiornare il pdf (o almeno provare ...) in modo che tutti i caratteri UTF-8 siano visualizzati correttamente?

EDIT:

Screenshot: enter image description here

EDIT 2:

ho cercato attraverso il codice sorgente PDFBox in PDFTextStripper e la sua superclasse, e ho scoperto come il testo è stato estratto:

All'inizio del metodo processStream abbiamo

graphicsState = new PDGraphicsState(aPage.findCropBox()); 

quando strippaggio il testo in processEncodedText, un'istanza di classe PDFont è usato così:

final PDFont font = graphicsState.getTextState().getFont(); 

e il testo viene estratto da un byte [] con:

String c = font.encode(string, i, codeLength); 

Il nuovo problema è che quando istanzio una classe PDFont con le stesse 2 righe di codice, ottengo una classe di font "null", e quindi non posso usare il metodo .encode (...). Il codice sorgente per le classi sono qui: http://grepcode.com/file/repo1.maven.org/maven2/org.apache.pdfbox/pdfbox/1.5.0/org/apache/pdfbox/util/PDFStreamEngine.java e http://grepcode.com/file/repo1.maven.org/maven2/org.apache.pdfbox/pdfbox/1.5.0/org/apache/pdfbox/util/PDFTextStripper.java

Sto scavando ormai da più ...

+0

prendiamo ciascuno alla volta. Quindi quando stampi il tuo testo che contiene alcuni segni diacritici viene visualizzato con ??? o qualche cifra invece? Potete fornire un esempio delle vostre dichiarazioni di stampa e anche un po 'di output? – Eugene

+0

Il codice di sostituzione della stringa che hai trovato [qui su coderanch] (http: //www.coderanch.com/t/556009/open-source/PdfBox-Replace-String-double-pdf) difficilmente funziona: 1. La codifica delle stringhe nel contenuto delle pagine PDF è completamente al carattere in questione; il tuo codice presuppone una codifica standard. 2. Le lettere di una singola parola (o segnaposto nel caso in questione) possono essere distribuite su più stringhe nel flusso di contenuti; il tuo codice non troverà segnaposti separati. 3. I caratteri possono essere incorporati nel PDF solo parzialmente; se la tua stringa di sostituzione utilizza caratteri non altrimenti utilizzati, non verranno visualizzati. ... – mkl

+0

@Eugene: il testo viene visualizzato correttamente, ad eccezione dei segni diacritici visualizzati come quadrati a 4 cifre (due in alto - per esempio 00, due in basso, ex 02). Non riesco a tagliare/incollare l'output nel browser (perché verranno visualizzati come spazi bianchi), ma aggiungerò uno screenshot con l'output nella console di Eclipse. –

risposta

1

Infine, sembra che il processo di estrazione dei caratteri nel file pdf sia piuttosto complesso. Non ero in grado di utilizzare i caratteri in modo esplicito, quindi ho cercato all'interno del codice di PDFStreamEngine e delle classi che estende OperatorProcessor e ho scoperto come gli oggetti PDFont sono stati creati in una mappa (ho praticamente copiato i pezzi di codice necessari per estrarre i segni diacritici) . Quindi, dopo che ho usato i caratteri rilevati durante l'interazione con parser.getTokens() per chiamare il metodo encode (...) su ogni carattere nella "stringa".

+0

In che modo è possibile ottenere il carattere e codificare la stringa? Ho a che fare con Chinese String e ho incontrato lo stesso problema. – hwding

17

non si può semplicemente sostituire il testo nelle stringhe. Non lo dico alla leggera. Ho lavorato su Acrobat molti anni fa e ho fatto lo strumento di ricerca del testo nella versione iniziale, quindi ho una conoscenza abbastanza approfondita dei problemi della codifica del testo. Il problema principale è che ogni stringa in PDF è codificata in qualche modo. Questo perché PDF è stato creato prima che Unicode fosse generalmente disponibile e avesse una cronologia in PostScript. PosctScript è piaciuto avere metodi di codifica molto flessibili per i caratteri e la ricodifica incoraggiata.

Quindi facciamo un passo indietro e comprendiamo l'intera immagine.

Un carattere in una stringa in PDF che deve essere visualizzato con un operatore di testo è, per impostazione predefinita, codificato come una serie di caratteri a 8 bit. Per determinare quale glifo viene disegnato per ogni byte, il byte viene spinto attraverso un vettore di codifica per quel tipo di carattere. Il vettore di codifica associa il byte a un nome di glifo, che viene quindi ricercato nel carattere e disegnato sulla pagina. Essere consapevoli del fatto che questa descrizione è una mezza verità (più tardi).

La maggior parte delle app che generano PDF sono gentili e utilizzano solo una codifica standard come StandardEncoding o WinAnsiEncoding, la maggior parte delle quali è abbastanza ragionevole. Altri useranno codifiche standard insieme a un delta di codifica , che sono le differenze da una codifica standard a ciò che è codificato.

Alcune app cercano di essere molto più parsimoniose nel PDF che generano, quindi guardano i glifi che usano e decidono di incorporare un sottoinsieme del font. Se usano solo lettere e cifre romane maiuscole e minuscole, ricostruiscono il font senza quegli elementi e possono scegliere di indicizzarli nuovamente e fornire un vettore di codifica tale che il byte 0x00 vada al glifo 'a' e 0x01 vada a il glifo "b" e così via.

Ora torniamo alla mezza verità. Esiste una classe di caratteri codificati dall'ID carattere (o CID) e i caratteri TrueType e OpenType rientrano in quella categoria. In questo caso, si ottiene l'accesso a Unicode, ma di nuovo c'è un passo di codifica in cui la stringa, che ora è UTF16BE, viene mappata al CID che viene utilizzato per ottenere il glifo dal font. E per nessuna ragione particolarmente buona, Adobe usa una funzione PostScript per eseguire la mappatura. E ancora, si tratta di una verità dei 3/4 perché ci sono diverse codifiche anche per la gestione più datata di caratteri cinesi, giapponesi e coreani.

Quindi, prima di mettere allegramente un carattere in una stringa per un font PDF, è necessario fare alcune domande:

  1. È il mio glifo nel carattere?
  2. Il mio glifo è nella codifica?
  3. Qual è la codifica del mio glifo?

E uno di questi può essere diverso da quello che ti aspetti. Quindi, per esempio, se vuoi inserire Ä (una diresis), devi vedere se il font ha il glifo per esso (che potrebbe non esserci perché il font è un sottoinsieme). Quindi il font potrebbe avere una codifica divertente che potrebbe non includere il glifo. Infine, il valore o i valori effettivi dei byte da utilizzare per Ä potrebbero non essere standard.

Così quando vedo qualcuno che cerca semplicemente di sostituire un pezzo di testo nel contenuto PDF, tutto quello che vedo è un mondo di dolore. Per la maggior parte dei sane PDF, questo funzionerà dire, il 90% delle volte, ma per qualcosa di esotico - buona fortuna. Le stranezze nel rendering del testo PDF sono abbastanza dolorose che a volte è più semplice pensarlo come un formato di sola scrittura.

+0

Grazie per la risposta. Ho anche aggiornato la mia domanda con alcune conclusioni relative alle righe di codice in pdfbox, relative alla classe che estrae il testo correttamente dai miei file pdf. –

+0

@plinth questa risposta molto probabilmente non otterrà troppi upvotes ma per me merita un lotto d'oro. – Eugene

Problemi correlati