从java进程调用jpegoptim和pngquant,在标准文本中传递图像,并在标准文本中读取结果:断管或挂起
我有一个jpeg或png类型的变量中的imagen,我正在尝试通过Java1.6使用命令行jpegoptim或pngquant转换它 问题是我不能让它工作。我读了很多答案,但没有找到答案 这是我尝试的最后一个函数:从java进程调用jpegoptim和pngquant,在标准文本中传递图像,并在标准文本中读取结果:断管或挂起,java,bash,image-processing,Java,Bash,Image Processing,我有一个jpeg或png类型的变量中的imagen,我正在尝试通过Java1.6使用命令行jpegoptim或pngquant转换它 问题是我不能让它工作。我读了很多答案,但没有找到答案 这是我尝试的最后一个函数: public int execute(byte[] image) throws IOException { ProcessBuilder processBuilder = new ProcessBuilder(commandLine); final Process p
public int execute(byte[] image) throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
final Process process = processBuilder.start();
final ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
final ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream();
try {
// Handle stdout...
new Thread() {
public void run() {
try {
IOUtils.copy(process.getInputStream(), outputBuffer);
} catch (Exception e) {
LOG.error("Error executing " + commandLine,e);
}
}
}.start();
// Handle sderr...
new Thread() {
public void run() {
try {
IOUtils.copy(process.getErrorStream(), errorBuffer);
} catch (Exception e) {
LOG.error("Error executing " + commandLine,e);
}
}
}.start();
process.getOutputStream().write(image);
process.getOutputStream().flush();
process.waitFor();
result = outputBuffer.toByteArray();
errorMsg = errorBuffer.toString("ASCII");
} catch (InterruptedException e) {
LOG.error("Error executing " + commandLine,e);
} finally {
if( process != null ) {
close(process.getErrorStream());
close(process.getOutputStream());
close(process.getInputStream());
process.destroy();
}
}
return process.exitValue();
}
命令行用于jpg:
this.commandLine = new ArrayList<String>();
this.commandLine.add("jpegoptim");
this.commandLine.add("-m90");
this.commandLine.add("--stdout");
this.commandLine.add("--stdin");
等待永远不会回来。。。少了什么
如果我在刷新(在上面的代码中注释)之后放入“stdin.close();”,则进程结束。但是stdout没有被完全处理,并且显示了一个错误:java.io.IOException:Stream关闭两次(每个线程一次)。logfile.log与映像相同,但标准输出被截断
我通过命令行对此进行测试:
java-cp testProc.jar testProc.Test image.jpg>image\u new.jpg
logfile.log等于image.jpg
image_new.jpg更小,是image.jpg的截断版本
有什么线索吗?从最后两行开始。您不能使用
>stdin
通过stdin
。查看一些ProcessBuilder示例,了解如何使用BufferedWriter写入进程的stdin(Java进程的stdout),然后使用BufferedReader对子进程的stdout执行同样的操作。
如果在这之后仍然存在问题,那么为了进行诊断,您可以尝试用
tee-a日志文件
替换jpegoptim
和pngquant
,它将获取stdin并将其直接传输回stdout(和一个名为logfile的文件)。然后您就得到了一个包含所有管道数据的文件,或者您将得到一个空文件和管道错误,因为您的Java程序没有传入数据,您可以查看它是否正确。
如果您得到一个包含数据的文件,并且没有管道错误,这可能意味着
jpegoptim
没有返回任何数据。此时,您可以通过管道将数据从
logfile
传输到命令行上的jpegoptim
,并使用这些选项,直到它正常工作,然后在Java代码中使用这些工作选项。最后,我让它正常工作了
我纯粹靠运气找到了解决办法!。。。
我取消了那句台词:
stdin.close();
并在“process.waitFor();”行之后添加:这几行:
errorT.join();
outputT.join();
要处理图像,命令如下:
commandLine.add("jpegoptim");
commandLine.add("-m90");
commandLine.add("--stdout");
commandLine.add("--stdin");
以及:
最终代码:
public int execute(List<String> commandLine, byte[] image) throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
final Process process = processBuilder.start();
OutputStream stdin = process.getOutputStream ();
final InputStream stderr = process.getErrorStream ();
final InputStream stdout = process.getInputStream ();
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
Thread errorT = new Thread() {
public void run() {
byte[] buf = new byte[1024];
int len;
try {
while ((len = stdout.read(buf)) != -1) {
// process byte buffer
bos.write(buf, 0, len);
bos.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
errorT.start();
Thread outputT = new Thread() {
public void run() {
byte[] buf = new byte[1024];
int len;
try {
while ((len = stderr.read(buf)) != -1) {
System.err.write(buf, 0, len);
System.err.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
outputT.start();
stdin.write(image);
stdin.flush();
stdin.close();
try {
process.waitFor();
errorT.join();
outputT.join();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
stdin.close();
stderr.close();
stdout.close();
System.out.write(bos.toByteArray());
return 0;
}
public int execute(列表命令行,字节[]图像)引发IOException{
ProcessBuilder ProcessBuilder=新的ProcessBuilder(命令行);
最终流程=processBuilder.start();
OutputStream stdin=process.getOutputStream();
final InputStream stderr=process.getErrorStream();
final InputStream stdout=process.getInputStream();
final ByteArrayOutputStream bos=新建ByteArrayOutputStream();
线程错误t=新线程(){
公开募捐{
字节[]buf=新字节[1024];
内伦;
试一试{
而((len=stdout.read(buf))!=-1){
//进程字节缓冲区
bos.write(buf,0,len);
bos.flush();
}
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
};
error.start();
线程输出=新线程(){
公开募捐{
字节[]buf=新字节[1024];
内伦;
试一试{
而((len=stderr.read(buf))!=-1){
系统错误写入(buf,0,len);
System.err.flush();
}
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
};
output.start();
标准写入(图像);
stdin.flush();
stdin.close();
试一试{
process.waitFor();
error.join();
output.join();
}捕捉(中断异常e1){
//TODO自动生成的捕捉块
e1.printStackTrace();
}
stdin.close();
stderr.close();
stdout.close();
System.out.write(bos.toByteArray());
返回0;
}
谢谢你的回答。我照你的建议做了,但现在我还有其他错误。我编辑了这篇文章来展示他们
errorT.join();
outputT.join();
commandLine.add("jpegoptim");
commandLine.add("-m90");
commandLine.add("--stdout");
commandLine.add("--stdin");
commandLine.add("pngquant");
commandLine.add("--quality=70-80");
commandLine.add("-");
public int execute(List<String> commandLine, byte[] image) throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
final Process process = processBuilder.start();
OutputStream stdin = process.getOutputStream ();
final InputStream stderr = process.getErrorStream ();
final InputStream stdout = process.getInputStream ();
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
Thread errorT = new Thread() {
public void run() {
byte[] buf = new byte[1024];
int len;
try {
while ((len = stdout.read(buf)) != -1) {
// process byte buffer
bos.write(buf, 0, len);
bos.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
errorT.start();
Thread outputT = new Thread() {
public void run() {
byte[] buf = new byte[1024];
int len;
try {
while ((len = stderr.read(buf)) != -1) {
System.err.write(buf, 0, len);
System.err.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
outputT.start();
stdin.write(image);
stdin.flush();
stdin.close();
try {
process.waitFor();
errorT.join();
outputT.join();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
stdin.close();
stderr.close();
stdout.close();
System.out.write(bos.toByteArray());
return 0;
}