Linux下Java剪贴板的访问
1 概述
本文主要講述了如何利用xsel在Linux環(huán)境下對系統(tǒng)剪貼板的訪問。
2 起因
在搜索引擎直接搜索“Java訪問剪貼板”,大部分都是直接使用AWT API進行訪問的例子:
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); StringSelection selection = new StringSelection("test"); clipboard.setContents(selection, selection);但是,一個最大的問題是,需要該程序一直運行,才能訪問到剪貼板,因此,如果沒有其他處理邏輯,需要加上線程休眠代碼:
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); StringSelection selection = new StringSelection("test"); clipboard.setContents(selection, selection); TimeUnit.HOURS.sleep(1);換句話說,這樣只是臨時復(fù)制到剪貼板,并沒有永久復(fù)制,那么,有沒有其他辦法可以在運行程序結(jié)束之后也能訪問到剪貼板呢?
3 xsel
xsel是Linux下訪問剪貼板的命令行工具,類似的還有xclip,沒有安裝的可以使用包管理器安裝。其中寫入到剪貼板命令如下:
echo "test clipboard" | xsel -ib由此想到了可以嘗試使用Runtime:
public static void main(String[] args) throws Exception {Runtime runtime = Runtime.getRuntime();// 直接執(zhí)行命令Process process = runtime.exec("echo \"111\" | xsel -ib");// 等待執(zhí)行結(jié)束process.waitFor();StringBuilder builder = new StringBuilder();// 獲取輸出BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));for (String s; ((s = reader.readLine()) != null); ) {builder.append(s);}System.out.println(builder);builder = new StringBuilder();// 獲取錯誤輸出reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));for (String s; ((s = reader.readLine()) != null); ) {builder.append(s);}System.out.println(builder);// 獲取返回值int exitValue = process.exitValue();System.out.println("exitValue is " + exitValue);if (exitValue != 0) {System.out.println("error");}process.destroy(); }運行之后輸出如下:
"111" | xsel -ib "111" | xsel -ib exitValue is 0可以看到輸出結(jié)果是不正常的,這樣就相當(dāng)于變成了執(zhí)行
echo "\"111\" | xsel -ib"也就是輸出的字符串都是echo的參數(shù)。
4 創(chuàng)建腳本文件
出現(xiàn)上面結(jié)果的原因是Process并不能直接支持使用管道運算符,因此,采用直接創(chuàng)建腳本運行命令的方法。
步驟:
- 創(chuàng)建臨時腳本文件:使用Files.createFile創(chuàng)建
- 授權(quán):700權(quán)限,也就是所有者讀、寫、執(zhí)行權(quán)限,使用Files.setPosixFilePermissions
- 寫入腳本文件:向腳本文件寫入echo str | xsel -ib,使用Files.writeString
- 執(zhí)行:利用Process.exec執(zhí)行腳本文件
- 刪除:利用Files.delete刪除臨時文件
代碼如下:
public static void main(String[] args) throws Exception {String fileName = "1.sh";Path executeFile = Files.createFile(Path.of(fileName));Files.setPosixFilePermissions(executeFile, Set.of(PosixFilePermission.OWNER_WRITE,PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.OWNER_READ));String clipboardContent = "111";Files.writeString(executeFile, "echo " + clipboardContent + " | xsel -ib");Runtime runtime = Runtime.getRuntime();Process process = runtime.exec("./" + fileName);process.waitFor();StringBuilder builder = new StringBuilder();BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));for (String s; ((s = reader.readLine()) != null); ) {builder.append(s);}System.out.println(builder);builder = new StringBuilder();reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));for (String s; ((s = reader.readLine()) != null); ) {builder.append(s);}System.out.println(builder);int exitValue = process.exitValue();System.out.println("exitValue is " + exitValue);if (exitValue != 0) {System.out.println("error");}Files.delete(executeFile);process.destroy(); }輸出:
exitValue is 0有兩行空行是System.out.println()的換行輸出,說明Process的inputStream以及errorStream都沒有內(nèi)容。
測試結(jié)果也是正常,能夠剪貼出111字符串。
5 從剪貼板讀取
從剪貼板讀取的原理類似,就是xsel的參數(shù)不一樣,這里不展開了,放上完整代碼:
import java.io.BufferedReader; import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermission; import java.util.Set;public class Main {private static final String FILENAME = "1.sh";public static void main(String[] args) throws Exception {writeToClipboard("111111");System.out.println(readFromClipboard());writeToClipboard("22222");System.out.println(readFromClipboard());}//寫入到剪貼板private static void writeToClipboard(String content) throws Exception {Path executeFile = createFile("echo " + content + " | xsel -ib");exec(executeFile);}//從剪貼板讀取private static String readFromClipboard() throws Exception {Path executeFile = createFile("xsel -ob");return exec(executeFile);}private static Path createFile(String fileContent) throws Exception {Path executeFile = Files.createFile(Path.of(FILENAME));Files.setPosixFilePermissions(executeFile, Set.of(PosixFilePermission.OWNER_WRITE,PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.OWNER_READ));Files.writeString(executeFile, fileContent);return executeFile;}private static String exec(Path executeFile) throws Exception {Runtime runtime = Runtime.getRuntime();Process process = runtime.exec("./" + FILENAME);process.waitFor();StringBuilder builder = new StringBuilder();BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));for (String s; ((s = reader.readLine()) != null); ) {builder.append(s);}String res = "";if (builder.length() != 0) {res = builder.toString();}reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));builder = new StringBuilder();for (String s; ((s = reader.readLine()) != null); ) {builder.append(s);}if (builder.length() != 0) {System.out.println(builder);}int exitValue = process.exitValue();System.out.println("exitValue is " + exitValue);if (exitValue != 0) {System.out.println("error");}Files.delete(executeFile);process.destroy();return res;} }總結(jié)
以上是生活随笔為你收集整理的Linux下Java剪贴板的访问的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Python深度学习从零开始学》简介
- 下一篇: linux 其他常用命令