【问题标题】:Encoding issue with apache poi converterapache poi转换器的编码问题
【发布时间】:2017-01-25 16:20:03
【问题描述】:

我有一个 ms word doc 文件,我正在使用 apache poi 将其转换为 html 文档。

这是我正在运行的代码

    InputStream input = new FileInputStream (path);
    HWPFDocument wordDocument = new HWPFDocument (input);            
    WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter (DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() );

    List<Picture> pics = wordDocument.getPicturesTable().getAllPictures();
    if (pics != null) 
    {
        for (int i = 0; i <pics.size(); i++) 
        {
            Picture pic = (Picture) pics.get (i);
            try 
            {
                pic.writeImageContent (new FileOutputStream (path + pic.hashCode() + '.' + pic.suggestFileExtension()) );
            }
            catch (FileNotFoundException e) 
            {
                e.printStackTrace();
            }
        }
    }

    wordToHtmlConverter.setPicturesManager (new PicturesManager() 
    {               
        public String savePicture (byte[] content, PictureType pictureType, String suggestedName, float widthInches, float heightInches) 
        {
            for(Picture picName:pics)
            {
                return Integer.toString(picName.hashCode()) + '.' + picName.suggestFileExtension();
            }

            return null;
        }
    });

    wordToHtmlConverter.processDocument(wordDocument);                       
    Document htmlDocument = wordToHtmlConverter.getDocument();                        
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    DOMSource domSource = new DOMSource(htmlDocument);
    StreamResult streamResult = new StreamResult (outStream);

    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer serializer = tf.newTransformer();
    serializer.setOutputProperty (OutputKeys.ENCODING, "gbk");
    serializer.setOutputProperty (OutputKeys.INDENT, "yes");
    serializer.setOutputProperty (OutputKeys.METHOD, "html");
    serializer.transform (domSource, streamResult);
    outStream.close();

    String html = new String (outStream.toByteArray());

代码运行良好,它保留了图像和样式。但是,html 中的某些字符似乎存在问题,它没有正确编码。例如,原始 .doc 文件中的某些项目符号样式无法正确输出。我尝试了多个字符集(ASCII、UTF-8、gbk ...)都没有正确生成项目符号。

我 %99% 确定项目符号由于编码而显示为乱码。有没有人遇到过这样的 apache 问题?

【问题讨论】:

    标签: encoding apache-poi converter


    【解决方案1】:

    这不是编码问题,而是字体问题。 Word 使用 ANSI 代码和特殊字体作为它的默认项目符号列表。例如,第一个项目符号点是字体“符号”的项目符号。第二个要点是字体“Courier New”的圆形,第三个要点是字体“Wingdings”的正方形。

    因此,最简单的方法是将项目符号文本的ANSI 代码替换为 unicode。这样我们就可以对 HTML 使用 UTF-8 了。

    例子:

    字WordBulletList.doc:

    Java:

    import java.io.StringWriter;
    import java.io.FileInputStream;
    import java.io.File;
    import java.io.PrintWriter;
    
    import javax.xml.transform.OutputKeys;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    
    import javax.xml.parsers.DocumentBuilderFactory;
    
    import org.apache.poi.hwpf.HWPFDocument;
    import org.apache.poi.hwpf.HWPFDocumentCore;
    import org.apache.poi.hwpf.usermodel.Paragraph;
    import org.apache.poi.hwpf.converter.WordToHtmlConverter;
    import org.apache.poi.hwpf.converter.FontReplacer;
    import org.apache.poi.hwpf.converter.FontReplacer.Triplet;
    
    import org.w3c.dom.Document;
    
    import java.awt.Desktop;
    
    public class TestWordToHtmlConverter {
    
     public static void main(String[] args) throws Exception {
    
      Document newDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
    
      WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(newDocument) {
    
       protected void processParagraph(HWPFDocumentCore hwpfDocument, 
                                       org.w3c.dom.Element parentElement, 
                                       int currentTableLevel, 
                                       Paragraph paragraph, 
                                       java.lang.String bulletText) {
        if (bulletText!="") {
         //System.out.println((int)bulletText.charAt(0));
         bulletText = bulletText.replace("\uF0B7", "\u2022");
         bulletText = bulletText.replace("\u006F", "\u00A0\u00A0\u26AA");
         bulletText = bulletText.replace("\uF0A7", "\u00A0\u00A0\u00A0\u00A0\u25AA");
        }
    
        super.processParagraph(hwpfDocument, parentElement, currentTableLevel, paragraph, bulletText);
       }
    
      };
    
      wordToHtmlConverter.processDocument(new HWPFDocument(new FileInputStream("WordBulletList.doc")));
    
      StringWriter stringWriter = new StringWriter();
      Transformer transformer = TransformerFactory.newInstance().newTransformer();
      transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
      transformer.setOutputProperty( OutputKeys.ENCODING, "utf-8" );
      transformer.setOutputProperty( OutputKeys.METHOD, "html" );
      transformer.transform(new DOMSource(wordToHtmlConverter.getDocument()), new StreamResult(stringWriter));
    
      String html = stringWriter.toString();
    
      try(PrintWriter out = new PrintWriter("WordBulletList.html")) {
        out.println(html);
      }
    
      File htmlFile = new File("WordBulletList.html");
      Desktop.getDesktop().browse(htmlFile.toURI());
    
     }
    }
    

    HTML:

    ...
    <body class="b1 b2">
    <p class="p1">
    <span>Word bullet list:</span>
    </p>
    <p class="p2">
    <span class="s1">&bull;​&nbsp;</span><span>Bullet1</span>
    </p>
    <p class="p2">
    <span class="s1">&nbsp;&nbsp;⚪​&nbsp;</span><span>Bullet2</span>
    </p>
    <p class="p2">
    <span class="s1">&nbsp;&nbsp;&nbsp;&nbsp;▪​&nbsp;</span><span>Bullet3</span>
    </p>
    <p class="p2">
    <span class="s1">&nbsp;&nbsp;⚪​&nbsp;</span><span>Bullet2</span>
    </p>
    <p class="p2">
    <span class="s1">&bull;​&nbsp;</span><span>Bullet1</span>
    </p>
    <p class="p1">
    <span>End</span>
    </p>
    </body>
    ...
    

    【讨论】:

    • 我已经尝试过这种方法,我在最终的 html 页面上得到了与以前相同的错误结果。
    • 那么您在 Word 中使用了其他项目符号点符号。请取消注释//System.out.println((int)bulletText.charAt(0)); 并查看使用了什么字符代码,将其转换为十六进制并替换那个“\u....”字符。
    【解决方案2】:

    问题已解决

    我终于找到了解决这个特殊问题的方法。答案受到@pawelini1 的启发,他提出了自己的问题Encoding issue with Apache POI

    解决方案很简单,我所做的只是在我的 html 字符串上使用 URLEncoder/Decoder

    String html = URLEncoder.encode(new String(outStream.toByteArray(), "UTF-8"), "UTF-8");
    String decoded = URLDecoder.decode(html, "UTF-8");
    

    现在我的网页可以正常显示了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-27
      • 2017-03-17
      • 2012-01-04
      • 2020-12-13
      • 1970-01-01
      相关资源
      最近更新 更多