Getting binary data directly off the windows clipboard
Asked Answered
R

1

9

I've been beating my head against the desk for about an hour now just trying to find some way of getting say... an array of bytes off the clipboard. Instead, all I can seem to find is information on how to get plain text from the clipboard... that's not helpful at all.

I've tried following this: Java getting bytes of clipboard

I've also tried following this: http://mrbool.com/manipulating-clipboard-content-with-java/24758

Every time I run into the silly DataFlavor being "unsupported". Surely there's just something simple that I'm missing here... I mean... how can it support plain text, images, and java objects, but NOT have the basic functionality that just has to be under the hood of all this?

Sorry if I sound sarcastic and pissed off here... Java seems to have that effect on me. :(

Refill answered 19/7, 2014 at 21:7 Comment(6)
I tried Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); and it is working. Maybe you can try data.getBytes(Charset.defaultCharset()); Show the code you are using.Pitzer
I get "UnsupportedFlavorException: Unicode String" when I use this code: String x = (String)Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);Refill
If I write System.out.println(Toolkit.getDefaultToolkit().getSystemClipboard().getAvailableDataFlavors().length); I get "0" returned. Does that mean there is no way to get the data???Refill
What is the data you are copying? can you provide some sample data? How did you make sure the data is in the clipboard?Pitzer
The data in the clipboard is copied from the level editor of "Natural Selection 2". I can ensure the data is in the clipboard using "InsideClipboard" from here: nirsoft.net/utils/inside_clipboard.html I literally had the level editor open in one window and eclipse in the other, and it still had no data flavors listed.Refill
Here's what InsideClipboard looks like with the level editor data in the clipboard: i.imgur.com/Zax0H9d.jpgRefill
L
5

Awt Clipboard and MIME types

InsideClipboard shows that the content's MIME type is application/spark editor

You should be able to create a MIME type DataFlavor by using the constructor DataFlavor(String mimeType, String humanReadableFormat) in which case the class representation will be an InputStream from which you can extract bytes in a classic manner...

However, this clipboard implementation is very strict on the mime type definition and you cannot use spaces in the format id, which is too bad because your editor seems to put a space there :(

Possible solution, if you have access to JavaFX

JavaFX's clipboard management is more lenient and tolerates various "Format Names" (as InsideClipboard calls them) in the clipboard, not just no-space type/subtype mime formats like in awt.

For example, using LibreOffice Draw 4.2 and copying a Rectangle shape, awt only sees a application/x-java-rawimage format whereas JavaFX sees all the same formats as InsideClipboard :

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

You can then get the raw data from the JavaFX clipboard in a 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);
}
Loree answered 1/8, 2014 at 14:27 Comment(2)
Darn... I was hoping for a plain Java solution that didn't require people to install a bunch of other libraries. Oh well, thanks for your help though!Refill
No problem. Note that oracle's Java distribution includes JavaFX as of Java 7! Not in openjdk on Linux though (but oracle's is also installable on Linux of course)Foal

© 2022 - 2024 — McMap. All rights reserved.