0

PDFファイルをXMLファイルに変換するためのプロトタイプを作成しようとしています。結果は少し奇妙で、すべての文字がシンボルになります。StringBufferバグは、がバイト配列からデータを取得する場所にあると思います。Javaの知識を持っている人が助けてくれますか?

このプロトタイプソフトウェアはiTextAPIを使用しています。PDFファイルを読むために、PDFReaderクラスを使用しました。データは最初にバイト配列に変換され、次に、を使用してStringbuffer再び文字列に変換されます。次にStreamResult、XMLで変換された結果のホルダーとして機能するものを使用しました。

その後、TransformerクラスはさまざまなソースからのXMLを処理し、変換出力をさまざまなシンクに書き込みます。次にTransformerHandler、SAXをリッスンしContentHandler、イベントを解析して結果に変換します。

メソッドstartElement()endElement()ofTransformerHandlerクラスは、xmlファイルにタグを作成しました。パーサーは、XMLドキュメントのすべてのstartElement()要素の最初とすべての要素の最後でメソッドを呼び出しました。endElement()

import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.sax.*;
import javax.xml.transform.stream.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

public class Cp2x {

        static StreamResult streamResult;
        static TransformerHandler handler;
        static AttributesImpl atts;

        public static void main(String[] args) throws IOException {

                try {
                        Document document = new Document();
                        document.open();
                        PdfReader reader = new PdfReader("C:\\helloworld.pdf");
                        PdfDictionary page = reader.getPageN(1);
                        PRIndirectReference objectReference = (PRIndirectReference) page
                                        .get(PdfName.CONTENTS);
                        PRStream stream = (PRStream) PdfReader
                                        .getPdfObject(objectReference);
                        byte[] streamBytes = PdfReader.getStreamBytes(stream);
                        PRTokeniser tokeniser = new PRTokeniser(streamBytes);

                        StringBuffer string_buffer = new StringBuffer();
                        while (tokeniser.nextToken()) {
                                if (tokeniser.getTokenType() == PRTokeniser.TK_STRING) {
                                        string_buffer.append(tokeniser.getStringValue());
                                }
                        }
                        String test = string_buffer.toString();
                        streamResult = new StreamResult("test.xml");
                        initXML();
                        process(test);
                        closeXML();
                        document.add(new Paragraph(".."));
                        document.close();
                } catch (Exception e) {
                }
        }

        public static void initXML() throws ParserConfigurationException,
                        TransformerConfigurationException, SAXException {
                SAXTransformerFactory tf = (SAXTransformerFactory) SAXTransformerFactory
                                .newInstance();

                handler = tf.newTransformerHandler();
                Transformer serializer = handler.getTransformer();
                serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
                serializer.setOutputProperty(
                                "{http://xml.apache.org/xslt}indent-amount", "4");
                serializer.setOutputProperty(OutputKeys.INDENT, "yes");
                handler.setResult(streamResult);
                handler.startDocument();
                atts = new AttributesImpl();
                handler.startElement("", "", "Document", atts);
        }

        public static void process(String s) throws SAXException {
                String[] elements = s.split("\\|");
                atts.clear();
                handler.startElement("", "", "Note", atts);
                handler.characters(elements[0].toCharArray(), 0, elements[0].length());
                handler.endElement("", "", "Note");
        }

        public static void closeXML() throws SAXException {
                handler.endElement("", "", "Document");
                handler.endDocument();
        }
}
4

1 に答える 1

1

@sudmong が言うように、エンコーディングの問題があります。ページ コンテンツ ストリームPRTokeniserから文字列を読み取るために使用しないでください。ページ コンテンツ ストリーム内の文字列のエンコーディングは完全にコンテンツ記述のそのステップでの現在のフォントのエンコーディング。参照。ISO 32000-1セクション 7.3.4.2コンテンツ ストリーム外の文字列のリテラル文字列と、コンテンツ ストリーム内の文字列の 9.6.6文字エンコーディング

@BrunoLowagie が指摘するように、ページ コンテンツが直接のページ コンテンツ ストリーム内だけでなく、そこから参照される XObjects 内にあることも完全に無視します。ISO 32000-1セクション 8.10フォーム XObjects。彼はまた、コンテンツ ストリーム内の文字列は読み上げ順である必要はないことも指摘しています。同上セクション 9.4テキストオブジェクト

また、ページ ディクショナリの Contents エントリの値がストリームまたはストリームの配列のいずれかになる可能性があることも無視します。

値は、単一のストリームまたはストリームの配列のいずれかです。値が配列の場合、その効果は、配列内のすべてのストリームが順番に連結されて単一のストリームを形成したかのようになります。準拠しているライターは、コンテンツ ストリームを中断しても、画像オブジェクトやその他のリソースを発生時に作成できます。ストリーム間の分割は、語彙トークン間の境界でのみ発生する可能性がありますが (7.2、「語彙規則」を参照)、ページの論理コンテンツまたは組織とは関係ありません。PDF ファイルを使用または生成するアプリケーションは、Contents 配列の既存の構造を保持する必要はありません。適合するライターは、要素を含まない Contents 配列を作成してはなりません。

セクション 7.7.3.3 ISO 32000-1ページ オブジェクト

本当に自分でパーサーをプログラミングしたいのであれば、まずISO 32000-1を勉強したほうがよいでしょう。

それ以外の場合は、...text.pdf.parserPDF コンテンツを解析するための非常に優れたツールである iText のパッケージを見てください。気が向いたら、改善してみるといいかもしれません。

于 2013-02-12T15:31:09.587 に答える