Java - 剪贴板修改:适用于 Eclipse,但不适用于 JAR

Java - Clipboard modification : Works in Eclipse, but not as JAR

我创建了一个基于两个来源(在下面的代码中说明)的软件,它检测 HTML 复制到剪贴板并将本地图像更改为 base 64 图像。

当我 运行 在 Eclipse 中但不使用 JAR 时,此代码可以完美运行。

最初,我并没有使用getHtmlDataFlavor的方法,但是当我尝试将软件作为JAR 时,我添加了它。然后,我必须确保在 HtmlSelection.getTransferData 中有 if (flavor.getRepresentationClass() == java.io.Reader.class) 否则它会崩溃。但是使用 JAR,我只能得到纯文本版本!不过,在 Eclipse 中 运行 时它仍然有效。

有人有想法吗?

我 运行 宁 Windows 10。 在命令行中执行使用:java -jar ClipboardImageToBase64-1.0.0-jar-with-dependencies.jar

GitHub 项目: https://github.com/djon2003/ClipboardImageToBase64

/**
 * Library from HTML parsing : https://jsoup.org
 * 
 * Code based on : 
 * - 
 * - http://elliotth.blogspot.ca/2005/01/copying-html-to-clipboard-from-java.html
 */

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class ClipBoardListener extends Thread implements ClipboardOwner {
    Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();

    private static DataFlavor HTML_FLAVOR = new DataFlavor("text/html;class=java.io.Reader", "HTML");
    private int nbImagesConverted = 0;
    private Transferable currentTransferable;

    @Override
    public void run() {
        Transferable trans = sysClip.getContents(this);
        TakeOwnership(trans);
    }

    @Override
    public void lostOwnership(Clipboard c, Transferable t) {

        System.out.println("Copy to clipboard detected");
        try {
            ClipBoardListener.sleep(250); // waiting e.g for loading huge
                                            // elements like word's etc.
        } catch (Exception e) {
            System.out.println("Exception: " + e);
        }
        Transferable contents = sysClip.getContents(this);
        try {
            process_clipboard(contents, c);
        } catch (Exception ex) {
            Logger.getLogger(ClipBoardListener.class.getName()).log(Level.SEVERE, null, ex);
        }
        TakeOwnership(currentTransferable);

    }

    void TakeOwnership(Transferable t) {
        sysClip.setContents(t, this);
    }

    private void getHtmlDataFlavor(Transferable t) {
        DataFlavor df = null;

        for (DataFlavor tDf : t.getTransferDataFlavors()) {
            if (tDf.getMimeType().contains("text/html")) {
                if (tDf.getRepresentationClass() == java.io.Reader.class) {
                    df = tDf;
                    break;
                }
            }
        }

        HTML_FLAVOR = df;
    }

    public void process_clipboard(Transferable t, Clipboard c) {

        String tempText = "";
        Transferable trans = t;
        currentTransferable = t;

        getHtmlDataFlavor(t);
        if (HTML_FLAVOR == null) {
            System.out.println("No HTML flavor detected");
            return; 
        }

        nbImagesConverted = 0;
        try {
            if (trans != null ? trans.isDataFlavorSupported(HTML_FLAVOR) : false) {
                if (trans.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                    tempText = (String) trans.getTransferData(DataFlavor.stringFlavor);
                }
                java.io.Reader r = (java.io.Reader) trans.getTransferData(HTML_FLAVOR);

                StringBuilder content = getReaderContent(r);
                String newHtml = changeImages(content);

                currentTransferable = new HtmlSelection(newHtml, tempText);
                System.out.println("Converted " + nbImagesConverted + " images");
            } else {
                System.out.println("Not converted:" + trans.isDataFlavorSupported(HTML_FLAVOR));
                System.out.println(trans.getTransferData(HTML_FLAVOR));
                /*
                for (DataFlavor tt : trans.getTransferDataFlavors()) {
                    if (tt.getMimeType().contains("text/html")) {
                        System.out.println("-------");
                        System.out.println(tt.toString());
                    }
                }
                */
            }

        } catch (Exception e) {
            currentTransferable = t;
            System.out.println("Conversion error");
            e.printStackTrace();
        }
    }

    private String changeImages(StringBuilder content) throws RuntimeException, IOException {
        Document doc = Jsoup.parse(content.toString());
        Elements imgs = doc.select("img");
        for (Element img : imgs) {
            String filePath = img.attr("src");
            filePath = filePath.replace("file:///", "");
            filePath = filePath.replace("file://", "");

            File file = new File(filePath);
            if (file.exists()) {
                String encoded = Base64.encodeBase64String(FileUtils.readFileToByteArray(file));
                String extension = file.getName();
                extension = extension.substring(extension.lastIndexOf(".") + 1);
                String dataURL = "data:image/" + extension + ";base64," + encoded;

                img.attr("src", dataURL); // or whatever
                nbImagesConverted++;
            }
        }

        String html = doc.outerHtml();
        html = html.replaceAll("(?s)<!--.*?-->", ""); //Remove html comments
        return html; // returns the modified HTML
    }


    private StringBuilder getReaderContent(java.io.Reader r) throws IOException {
        char[] arr = new char[8 * 1024];
        StringBuilder buffer = new StringBuilder();
        int numCharsRead;
        while ((numCharsRead = r.read(arr, 0, arr.length)) != -1) {
            buffer.append(arr, 0, numCharsRead);
        }
        r.close();
        return buffer;
    }

    private static class HtmlSelection implements Transferable {

        private String html;
        private String plainText;



        public HtmlSelection(String html, String plainText) {

            this.html = html;
            this.plainText = plainText;

        }



        public DataFlavor[] getTransferDataFlavors() {

            DataFlavor[] dfs = {HTML_FLAVOR, DataFlavor.stringFlavor};
            return dfs;

        }



        public boolean isDataFlavorSupported(DataFlavor flavor) {

            return flavor.getMimeType().contains("text/html") || flavor.getMimeType().contains("text/plain");

        }



        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {

            if (flavor.getMimeType().contains("text/html")) {
                if (flavor.getRepresentationClass() == java.io.Reader.class) {
                    return new StringReader(html);  
                } else {
                    return html;
                }
             } else {
               return plainText;
            }

            //throw new UnsupportedFlavorException(flavor);
        }

    } 

}

我终于解决了所有问题。我为感兴趣的人创建了一个 GitHub 项目。

https://github.com/djon2003/ClipboardImageToBase64