今天接到一个任务,要用第三方提供的一个jar包来进行文件的加解密,需要使用“java -jar”命令运行jar包来对文件进行加解密操作,顺便记录一下两种实现方式
首先了解一下Process类,顾名思义,这个类叫进程类,封装了一个进程(即一个执行程序)。
官方解释:
Process类提供了执行进程输入、执行输出到进程、等待进程完成、检查进程退出状态以及销毁(杀死)进程的方法。
提供了6个抽象方法
public abstract OutputStream getOutputStream(); 返回连接到子进程正常输入的输出流
public abstract InputStream getInputStream(); 返回连接到子进程正常输出的输入流
public abstract InputStream getErrorStream(); 返回连接到子进程错误输出的输入流
public abstract int waitFor() throws InterruptedException; 使当前线程在必要时等待,直到此Process对象表示的Process终止
public abstract int exitValue(); 此Process对象表示的子流程的退出值。 按照惯例,值0表示正常终止。抛出IllegalThreadStateException的话表示此Process对象表示的子Process尚未终止
public abstract void destroy(); 杀死子进程。 此Process对象表示的子流程是否被强制终止取决于实现
1.8版本后新增以下三个公共方法
public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException{ long startTime = System.nanoTime(); long rem = unit.toNanos(timeout); do { try { exitValue(); return true; } catch(IllegalThreadStateException ex) { if (rem > 0) Thread.sleep( Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100)); } rem = unit.toNanos(timeout) - (System.nanoTime() - startTime); } while (rem > 0); return false; } public Process destroyForcibly() { destroy(); return this; } public boolean isAlive() { try { exitValue(); return false; } catch(IllegalThreadStateException e) { return true; } } }
回到原来的话题,执行“java -jar"命令运行jar包进行加解密。我先是用Runtime.exec() 方法创建一个本机进程,并返回 Process 子类的一个实例的方式来实现,来看下代码:
String command = "java -jar D:/work/si-tech/project/cbn/lib/acctmgr-application/jfycrpto.jar DEC 8613052000078705_001_003_20200115_689814_I.TXT"; try{ Process p = Runtime.getRuntime().exec(command); InputStream is = p.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String outInfo; while ((outInfo = reader.readLine()) != null) { System.out.println(outInfo); } p.waitFor(); // 等待process子进程终止 return p.exitValue() == 0; }catch (Exception e){ log.error("{}{}失败",fileName, encrypt ? "加密" : "解密"); return false; }
后来了解到,从 1.5 开始, ProcessBuilder.start()是创建Process的首选方式,于是最终改成如下方式:
/* 命令用List存储 */ String[] commandSplit = command.split(" "); List<String> lcommand = new ArrayList<>(Arrays.asList(commandSplit)); ProcessBuilder processBuilder = new ProcessBuilder(lcommand); processBuilder.redirectErrorStream(true); // 此对象的start()方法随后启动的子进程生成的任何错误输出都将与标准输出合并,以便可以使用Process.getInputStream()方法读取两者 try{ Process process = processBuilder.start(); InputStream is = process.getInputStream(); BufferedReader bs = new BufferedReader(new InputStreamReader(is)); process.waitFor(); // 等待process子进程终止 String line = null; while ((line = bs.readLine()) != null) { System.out.println(line); } return process.exitValue() == 0; }catch (Exception e){ log.error("{}{}失败",fileName, encrypt ? "加密" : "解密"); return false; }