从Windows剪贴板直接获取二进制数据

9
我已经试了一个小时了,一直在尝试找到一种方法来获取剪贴板中的字节数组。但是,我只能找到有关如何从剪贴板获取纯文本的信息...这根本没有帮助。
我尝试过按照以下步骤进行操作:Java 获取剪贴板的字节
我也尝试过按照以下步骤进行操作:http://mrbool.com/manipulating-clipboard-content-with-java/24758
每次都会遇到 DataFlavor 不支持的问题。肯定有些简单的东西我错过了...我的意思是...它怎么可以支持纯文本、图像和 Java 对象,却没有基本的功能呢?
如果我听起来很讽刺和生气...Java 似乎对我有这种影响。:(

我尝试了Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);并且它可以工作。也许你可以尝试data.getBytes(Charset.defaultCharset());请展示你正在使用的代码。 - naveejr
当我使用以下代码时,出现“UnsupportedFlavorException: Unicode String”错误:String x = (String)Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); - BeigeAlert
如果我写System.out.println(Toolkit.getDefaultToolkit().getSystemClipboard().getAvailableDataFlavors().length);,会返回“0”。这是否意味着无法获取数据? - BeigeAlert
你正在复制什么数据?能否提供一些样本数据?你是如何确保数据在剪贴板中的? - naveejr
剪贴板中的数据是从“自然选择2”的关卡编辑器复制来的。我可以使用来自这里的“InsideClipboard”确保剪贴板中的数据:http://www.nirsoft.net/utils/inside_clipboard.html我同时打开了一个窗口中的关卡编辑器和另一个窗口中的eclipse,但仍未列出任何数据格式。 - BeigeAlert
这是 InsideClipboard 打开剪贴板中的关卡编辑器数据的样子:http://i.imgur.com/Zax0H9d.jpg - BeigeAlert
1个回答

5

Awt剪贴板和MIME类型

InsideClipboard显示,内容的MIME类型为application/spark editor

您应该能够通过使用构造函数DataFlavor(String mimeType, String humanReadableFormat)创建一个MIME类型DataFlavor,在这种情况下,类表示将是一个InputStream,您可以以经典方式提取字节...

然而,此剪贴板实现对mime类型定义非常严格,您不能在格式ID中使用空格,这太糟糕了,因为您的编辑器似乎把空格放在那里:(

可能的解决方案,如果您可以访问JavaFX

JavaFX的剪贴板管理更加宽容,并容忍剪贴板中各种“格式名称”(如InsideClipboard所称),而不仅仅是像awt中没有空格的type/subtype mime格式。

例如,使用LibreOffice Draw 4.2并复制一个矩形形状,awt只看到一个application/x-java-rawimage格式,而JavaFX看到的是与InsideClipboard相同的所有格式:

[application/x-java-rawimage],[PNG],[Star Object Descriptor(XML)],[cf3],[Windows位图],[GDIMetaFile],[cf17],[Star Embed Source(XML)],[Drawing Format]

然后,您可以从JavaFX剪贴板中获取原始数据,以java.nio.ByteBuffer的形式。

//with awt
DataFlavor[] availableDataFlavors = Toolkit.getDefaultToolkit().getSystemClipboard().getAvailableDataFlavors();
System.out.println("Awt detected flavors : "+availableDataFlavors.length);
for (DataFlavor f : availableDataFlavors) {
    System.out.println(f);
}

//with JavaFX (called from JavaFX thread, eg start method in a javaFX Application
Set<DataFormat> contentTypes = Clipboard.getSystemClipboard().getContentTypes();
System.out.println("JavaFX detected flavors : " + contentTypes.size());
for (DataFormat s : contentTypes) {
        System.out.println(s);
}

//let's attempt to extract bytes from the clipboard containing data from the game editor
// (note : some types will be automatically mapped to Java classes, and unknown types to a ByteBuffer)
// another reproducable example is type "Drawing Format" with a Rectangle shape copied from LibreOffice Draw 4.2
DataFormat df = DataFormat.lookupMimeType("application/spark editor");
if (df != null) {
    Object content = Clipboard.getSystemClipboard().getContent(df);
    if (content instanceof ByteBuffer) {
        ByteBuffer buffer = (ByteBuffer) content;
        System.err.println(new String(buffer.array(), "UTF-8"));
    } else
        System.err.println(content);
}

糟糕...我本来希望有一个纯Java的解决方案,而不需要人们安装一堆其他的库。不过没关系,还是谢谢你的帮助! - BeigeAlert
没问题。请注意,自Java 7起,Oracle的Java发行版已包含JavaFX!但是在Linux上的openjdk中没有(当然,Oracle的也可以在Linux上安装)。 - Simon Baslé

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接