• Linux下Java剪贴板的访问


    1 概述

    本文主要讲述了如何利用xselLinux环境下对系统剪贴板的访问。

    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);
    

    换句话说,这样只是临时复制到剪贴板,并没有永久复制,那么,有没有其他办法可以在运行程序结束之后也能访问到剪贴板呢?

    3 xsel

    xselLinux下访问剪贴板的命令行工具,类似的还有xclip,没有安装的可以使用包管理器安装。其中写入到剪贴板命令如下:

    echo "test clipboard" | xsel -ib
    

    由此想到了可以尝试使用Runtime

    public static void main(String[] args) throws Exception {
        Runtime runtime = Runtime.getRuntime();
        // 直接执行命令
        Process process = runtime.exec("echo \"111\" | xsel -ib");
        // 等待执行结束
        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
    

    可以看到输出结果是不正常的,这样就相当于变成了执行

    echo "\"111\" | xsel -ib"
    

    也就是输出的字符串都是echo的参数。

    4 创建脚本文件

    出现上面结果的原因是Process并不能直接支持使用管道运算符,因此,采用直接创建脚本运行命令的方法。

    步骤:

    • 创建临时脚本文件:使用Files.createFile创建
    • 授权:700权限,也就是所有者读、写、执行权限,使用Files.setPosixFilePermissions
    • 写入脚本文件:向脚本文件写入echo str | xsel -ib,使用Files.writeString
    • 执行:利用Process.exec执行脚本文件
    • 删除:利用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()的换行输出,说明ProcessinputStream以及errorStream都没有内容。

    测试结果也是正常,能够剪贴出111字符串。

    5 从剪贴板读取

    从剪贴板读取的原理类似,就是xsel的参数不一样,这里不展开了,放上完整代码:

    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;
        }
    }
    
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Qt 自定义model实现文件系统的文件名排序
  • 原文地址:https://www.cnblogs.com/6b7b5fc3/p/16259712.html
Copyright © 2020-2023  润新知