我遇到了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注册它会很痛苦)
答案 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) {
}
}