在FoxPro应用程序中粘贴后,从JTextArea复制的文本已经破坏了编码

时间:2015-04-15 13:15:06

标签: java windows swing visual-foxpro

我遇到了Java剪贴板的一个非常奇怪的问题。我有JTextArea文本包含重音(例如“Žluťoučkýkůň”)。当我选择文本并按CTRL + C并将其粘贴到记事本或Microsoft Word时,一切正常。

但是当我将它粘贴到VisualFoxPro中制作的某些第三方应用程序中时(我知道它很古老,但我们的用户需要此应用程序)所有重音字母都因编码问题而被破坏。 Java应用程序使用UTF-8,FoxPro应用程序使用Windows-1250。

当我使用剪贴板查看器(https://code.google.com/p/clipboardviewer/)在JTextArea中按CTRL + C后查看在剪贴板中创建的所有DataFlavor时,我看到以下内容:

ClipboardViewer http://data.itpro.cz/clipboard.png

System.String UnicodeText 正确显示,但文字已损坏。我假设FoxPro应用程序正在使用此DataFlavor。

ClipboardViewer http://data.itpro.cz/clipboard2.png

当我将文本粘贴到记事本中时,按CTRL + A和CTRL + C,剪贴板的内容会发生变化,如下图所示。

ClipboardViewer http://data.itpro.cz/clipboard3.png

我的问题:这是Java中的错误吗?是否可以全局控制此行为(使用某些命令行-D开关或其他方法),或者需要在每个JTextArea和JTextField中捕获CTRL + C键击并手动创建带有自定义DataFlavor的DataTransfer? (不需要为此建议代码,我能够做到这一点,但在应用程序中为每个JTextComponent注册它会很痛苦)

1 个答案:

答案 0 :(得分:1)

我找到了3种可能的解决方案:

1)修改 jre \ lib \ flavormap.properties 文件。以TEXT开头的行可以修改为:

TEXT=text/plain;charset=cp1250;eoln="\r\n";terminators=1

请求cp1250目标编码。 这非常有效,但我相信每个Java更新都会覆盖此文件,因此无法用于生产。

2)使用-Dfile.encoding = cp1250启动JVM,此选项还会修改剪贴板功能,但如果您依赖于新的InputStreamReader等构造函数而未指定,它也可能会更改应用程序的某些行为字符集。

3)要在每个JTextComponent上捕获CTRL + C:

textArea.addKeyListener(new KeyAdapter() {
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_C && (e.getModifiers() & KeyEvent.CTRL_MASK) != 0) {

            Toolkit toolkit = Toolkit.getDefaultToolkit();
            Clipboard clipboard = toolkit.getSystemClipboard();
            CliboardString text = new CliboardString(textArea.getSelectedText(),"cp1250","Windows-1250");
            clipboard.setContents(text, null);
            e.consume();
        }
    }
});

ClipboardString的实现如下:

public class CliboardString implements Transferable, ClipboardOwner {

private final DataFlavor flavor;

private final String data;
private final String javaEncoding;

public CliboardString(String data,String flavorEncoding,String javaEncoding) {
    this.data = data;
    this.javaEncoding = javaEncoding;
    flavor =  new DataFlavor("text/plain;charset="+flavorEncoding, "TEXT");
}

@Override
public DataFlavor[] getTransferDataFlavors() {
    return new DataFlavor[] {flavor};
}

@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
    return flavor!=null && flavor.equals(this.flavor);
}

@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
    if (isDataFlavorSupported(flavor)) {
        return new ByteArrayInputStream(data.getBytes(javaEncoding));
    }
    throw new UnsupportedFlavorException(flavor);
}

@Override
public void lostOwnership(Clipboard clipboard, Transferable contents) {
}

}