简体   繁体   中英

how to merge two complex rtf(having images or tables) in java

Below is my code snippet which works for simple rtf merge. but it is not working for complex rtf merge like rtf having some images or tables. could anyone help on this how to merge two rtf having images or tables

 File input1 = new File("C:\\input\\document1.rtf");
    File input2 = new File("C:\\input\\document2.rtf");
    File output = new File ("C:\\output\\res.rtf");

    FileInputStream fis1 = null;
    FileInputStream fis2 = null;
    FileOutputStream fw = null;
    try {
        fis1 = new FileInputStream(input1);
        fis2 = new FileInputStream(input2);
        fw = new FileOutputStream(output);
    } catch (IOException e1) {
        e1.printStackTrace();
    }


    try {
        Document doc1 = load(fis1);
        Document doc2 = load(fis2);
        //String contents1 = doc1.getText(0, doc1.getLength());
        //String contents2 = doc2.getText(0, doc2.getLength());
        mergeDocument((DefaultStyledDocument)doc2, (DefaultStyledDocument)doc1);
        RTFEditorKit rtf = new RTFEditorKit();
        rtf.write(fw, doc1, 0, doc1.getLength());

    } catch (IOException e) {
        e.printStackTrace();
    } catch (BadLocationException e) {
        e.printStackTrace();
    }
    finally{
        try {
            fis1.close();
            fis2.close();
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public static Document load(InputStream is) throws IOException {
    RTFEditorKit rtf = new RTFEditorKit();
    Document doc = rtf.createDefaultDocument();
    BufferedReader input = new BufferedReader(new InputStreamReader(is));
    try {
        rtf.read(input, doc, 0);
    } catch (BadLocationException ble) {
        throw new IOException(ble);
    }
    return doc;
}

public static void mergeDocument(DefaultStyledDocument source, DefaultStyledDocument dest) throws BadLocationException {
    ArrayList<DefaultStyledDocument.ElementSpec> specs=new ArrayList<DefaultStyledDocument.ElementSpec>();
    DefaultStyledDocument.ElementSpec spec=new DefaultStyledDocument.ElementSpec(new SimpleAttributeSet(), 
             DefaultStyledDocument.ElementSpec.EndTagType);
    specs.add(spec);
    fillSpecs(source.getDefaultRootElement(), specs, false);
    spec=new DefaultStyledDocument.ElementSpec(new SimpleAttributeSet(), DefaultStyledDocument.ElementSpec.StartTagType);
    specs.add(spec);

    DefaultStyledDocument.ElementSpec[] arr = new DefaultStyledDocument.ElementSpec[specs.size()];
    specs.toArray(arr);
    insertSpecs(dest, dest.getLength(), arr);
}

protected static void insertSpecs(DefaultStyledDocument doc, int offset, DefaultStyledDocument.ElementSpec[] specs) {
    try {
        Method m=DefaultStyledDocument.class.getDeclaredMethod("insert", new Class[] {int.class, DefaultStyledDocument.ElementSpec[].class});
        m.setAccessible(true);
        m.invoke(doc, new Object[] {offset, specs});
    } catch (Exception e) {
        e.printStackTrace();
    }
}

protected static void fillSpecs(Element elem, ArrayList<DefaultStyledDocument.ElementSpec> specs, boolean includeRoot) throws BadLocationException{
    DefaultStyledDocument.ElementSpec spec;
    if (elem.isLeaf()) {
        String str=elem.getDocument().getText(elem.getStartOffset(), elem.getEndOffset()-elem.getStartOffset());
        spec=new DefaultStyledDocument.ElementSpec(elem.getAttributes(), 
                 DefaultStyledDocument.ElementSpec.ContentType,str.toCharArray(), 0, str.length());
        specs.add(spec);
    }
    else {
        if (includeRoot) {
            spec=new DefaultStyledDocument.ElementSpec(elem.getAttributes(), DefaultStyledDocument.ElementSpec.StartTagType);
            specs.add(spec);
        }
        for (int i=0; i<elem.getElementCount(); i++) {
            fillSpecs(elem.getElement(i), specs, true);
        }

        if (includeRoot) {
            spec=new DefaultStyledDocument.ElementSpec(elem.getAttributes(), DefaultStyledDocument.ElementSpec.EndTagType);
            specs.add(spec);
        }
    }

As lowagie.itext discard RTF(Rich Text Format) related function from 2009. we have to do this start from scratch. The basic logic is

  1. remove source doc last curly brace, add a page break
  2. delete target doc header (from first left curly brace to second one)
  3. uniquely merge (union) the target doc font tables, style table, color table to the source doc (not implemented)
  4. append left target doc to source doc

http://latex2rtf.sourceforge.net/RTF-Spec-1.2.pdf

Merge RTF files

 private static byte[] mergeRTF(byte[] sourceRtf, byte[] targetRtf) {
    String sourceStr = new String(sourceRtf, StandardCharsets.UTF_8);
    String targetStr = new String(targetRtf, StandardCharsets.UTF_8);
    //source string remove last right curly brace }
    int lastRightBraceIndex = sourceStr.lastIndexOf('}');
    sourceStr = sourceStr.substring(0, lastRightBraceIndex);
    //target string remove from 1st left Curly brace to 2nd one.
    int secondLeftBraceIndex = StringUtils.ordinalIndexOf(targetStr, "{", 2);
    targetStr = targetStr.substring(secondLeftBraceIndex);
    // source append \page
    StringBuilder mergedStr = new StringBuilder(sourceStr);
    mergedStr.append(System.lineSeparator()).append("\\page").append(System.lineSeparator());
    mergedStr.append(targetStr);

    return mergedStr.toString().getBytes(StandardCharsets.UTF_8);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM