2010-10-22 60 views
9

Tôi đang cố tạo ứng dụng giao diện người dùng trong Java để xử lý các chuyển đổi SVG hàng loạt bằng tính năng dòng lệnh của Inkscape. Tôi đang lấy và cập nhật mã từ https://sourceforge.net/projects/conversionsvg/. Cách nhà phát triển ban đầu xử lý gọi Inkscape theo Runtime.getRuntime(). Exec (Chuỗi). Vấn đề tôi đang gặp phải là một số mâu thuẫn giữa việc sử dụng methodA và methodB. Tôi đã tạo một dự án thử nghiệm java đơn giản để chứng minh các hành động khác nhau đang được thực hiện.ProcessBuilder vs Runtime.exec()

CallerTest.java

package conversion; 

import java.io.IOException; 

public class CallerTest { 

    static String pathToInkscape = "\"C:\\Program Files\\Inkscape\\inkscape.exe\""; 

    public static void main(String[] args) { 

     ProcessBuilderCaller processBuilder = new ProcessBuilderCaller(); 
     RuntimeExecCaller runtimeExec = new RuntimeExecCaller(); 

     // methodA() uses one long command line string 
     try { 

     String oneLongString_ProcessBuilder = pathToInkscape + " -f \"C:\\test.svg\" -D -w 100 -h 100 -e \"C:\\ProcessBuilder-methodB.png\""; 
     String oneLongString_RuntimeExec = pathToInkscape + " -f \"C:\\test.svg\" -D -w 100 -h 100 -e \"C:\\RuntimeExec-methodA.png\""; 

//  processBuilder.methodA(oneLongString_ProcessBuilder); 
     runtimeExec.methodA(oneLongString_RuntimeExec); 

     } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     } 

     // methodB() uses an array containing the command and the options to pass to the command 
     try { 

     String[] commandAndOptions_ProcessBuilder = {pathToInkscape, " -f \"C:/test.svg\" -D -w 100 -h 100 -e \"C:\\ProcessBuilder-methodB.png\""}; 
     String[] commandAndOptions_RuntimeExec = {pathToInkscape, " -f \"C:/test.svg\" -D -w 100 -h 100 -e \"C:\\RuntimeExec-methodB.png\""}; 

     processBuilder.methodB(commandAndOptions_ProcessBuilder); 
//  runtimeExec.methodB(commandAndOptions_RuntimeExec); 

     } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     } 
    } 
} 

RuntimeExecCaller.java

package conversion; 

import java.io.IOException; 

public class RuntimeExecCaller { 
    Process process; 

    // use one string 
    public void methodA(String oneLongString) throws IOException { 
     process = Runtime.getRuntime().exec(oneLongString); 
    } 

    // use the array 
    public void methodB(String[] commandAndOptions) throws IOException { 
     process = Runtime.getRuntime().exec(commandAndOptions); 
    } 
} 

ProcessBuilderCaller.java

package conversion; 

import java.io.IOException; 

public class ProcessBuilderCaller { 
    Process process; 

    // use one string 
    public void methodA(String oneLongString) throws IOException { 
     process = new ProcessBuilder(oneLongString).start(); 
    } 

    // use the array 
    public void methodB(String[] commandAndOptions) throws IOException { 
     process = new ProcessBuilder(commandAndOptions).start(); 
    } 
} 

quả

Cả methodA (String) cuộc gọi làm việc, nhưng khi methodB (String []) được gọi là Inkscape đã được bắt đầu và các đối số được truyền không chính xác. Sau methodB (String []) thực hiện tôi nhận được một hộp thoại báo lỗi Inkscape cho từng nói

Không tải được các yêu cầu tập tin -f C: /test.svg -D -w 100 -h 100 -e C : \ RuntimeExec-methodB.png

Không tải được các yêu cầu tập tin -f C: /test.svg -D -w 100 -h 100 -e C: \ ProcessBuilder-methodB.png

và khi tôi nhấp vào Đóng trên hộp thoại, Inkscape bật lên với một tài liệu trống mới. Vì vậy, tôi đoán tôi có một vài câu hỏi:

Sự khác nhau giữa Runtime.getRuntime(). Exec (String) và Runtime.getRuntime(). Exec (String [])?

javadoc nói rằng Runtime.exec (String) cuộc gọi Runtime.exec (lệnh, null) (đó là Runtime.exec (cmd String, String [] envp)) mà trong lần lượt gọi Runtime.exec (cmdarray, envp) (là Runtime.exec (String [] cmdarray, String [] envp)). Vì vậy, nếu Runtime.getRuntime(). Exec (String) đang gọi Runtime.exec (String []) anyways, tại sao tôi nhận được kết quả khác nhau khi sử dụng các phương pháp khác nhau?

Có phải điều gì đó đang xảy ra ở hậu trường nơi Java thiết lập môi trường khác nhau tùy thuộc vào phương pháp nào được gọi?

Trả lời

12

Tôi nghi ngờ vấn đề của bạn bắt nguồn từ cách bạn chỉ định danh sách đối số của mình. Về cơ bản, bạn đang chuyển "-f C:/test.svg -D -w 100 -h 100 -e C:\RuntimeExec-methodB.png" dưới dạng một đối số duy nhất tới Inkscape.

Những gì bạn cần làm là vượt qua các đối số riêng, như vậy:

String[] commandAndOptions_ProcessBuilder = {pathToInkscape, "-f", "C:\\est.svg", "-D", "-w", "100", "-h", "100", "-e", "C:\\ProcessBuilder-methodB.png"}; 
String[] commandAndOptions_RuntimeExec = {pathToInkscape, "-f", "C:\\test.svg", "-D", "-w", "100", "-h", "100", "-e","C:\\RuntimeExec-methodB.png"}; 

khoảng nói, khi bạn sử dụng Runtime.exec(String), giá trị mà bạn vượt qua trong được đánh giá bởi các vỏ, mà phân tích ra danh sách đối số. Khi bạn sử dụng Runtime.exec(String[]), bạn đang cung cấp danh sách đối số, do đó, nó không cần xử lý. Lợi ích của việc này là bạn không phải thoát khỏi các giá trị đặc biệt cho shell, vì các đối số sẽ không được đánh giá bởi nó.

+0

Tôi khá chắc chắn rằng Java xử lý tách các đối số trong cả hai 'ProcessBuilder' hoặc' Runtime.exec() ', nhưng nếu không chính xác. – Jonathan

+2

@ Jonathan, xem nhanh Thời gian chạy cho thấy bạn đúng - StringTokenizer được sử dụng để chia nhỏ chuỗi trên khoảng trắng. Điều đó có nghĩa là nếu bạn có khoảng trống trong đường dẫn của tệp thi hành, bạn sẽ cần sử dụng Runtime.exec (String []). – userkci

Các vấn đề liên quan