我遇到了一个与Java剪贴板非常奇怪的问题。 我有JTextArea与文本包含口音(例如“Žluťoučkýkůň”)。 当我select文本并按CTRL + C并将其粘贴到记事本或Microsoft Word一切正常。
但是当我把它粘贴到VisualFoxPro(我知道这是古老的,但我们的用户需要这个应用程序)制作的一些第三方应用程序时,由于编码问题,所有的重音字母都被破坏了。 Java应用程序使用UTF-8,FoxPro应用程序使用Windows-1250。
当我使用剪贴板查看器( https://code.google.com/p/clipboardviewer/ )查看在JTextArea中按CTRL + C后,在剪贴板中创build的所有DataFlavors,我看到以下内容:
ClipboardViewer http://img.zgserver.com/java/clipboard.png
System.String和UnicodeText显示正确,但文本已损坏。 我假设FoxPro应用程序正在使用此DataFlavor。
ClipboardViewer http://img.zgserver.com/java/clipboard2.png
当我将文本粘贴到记事本中时,按下CTRL + A和CTRL + C,剪贴板的内容将发生变化,如下图所示。
剪贴板查看器http://img.zgserver.com/java/clipboard3.png
我的问题是:它在Java中的错误? 是否有可能全局控制这种行为(用一些命令行-D开关或其他方法),或者需要在每个JTextArea和JTextField中捕获CTRL + C按键,并手动创build带有自定义DataFlavor的DataTransfer? (不需要为此提供代码,我可以这样做,但是在应用程序中为每个JTextComponent注册它将是痛苦的)
我找到了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这样的构造函数而不指定Charset,它也可能改变你的应用程序的某些行为。
3)是要抓住每个JTextComponent CTRL + C与这个:
textArea.addKeylistner(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) { } }