尝试执行代码块(尤其是Java中的ProcessBuilder类)时遇到一个奇怪的问题
起作用的代码:
package modules.user.verify;
import java.io.*;
import java.util.*;
import java.net.*;
public class VerifyUser {
public static void main(String[] args) {
boolean listening = true;
try {
ServerSocket server = new ServerSocket(20002);
while(listening) {
Socket client = server.accept();
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String input, store = "", request = "";
// For all input received, write it to the request buffer.
while((input = in.readLine()) != null) {
request += input;
} // end while loop
BufferedReader reader = new BufferedReader(new FileReader("store/address-book/address-book.xml"));
while((input = reader.readLine()) != null) {
store += input;
} // end while loop
String acl2 = "(include-book \"modules/user/verify/verify-user\")" +
"(in-package \"ACL2\")" +
"(set-state-ok t)" +
"(set-guard-checking :none)" +
"(testUser \"" + request + "\" \"" + store + "\" state)";
System.out.println("Executing ACL2 runtime...");
ProcessBuilder processBuilder = new ProcessBuilder("acl2");
File log = new File("logs/user/verify/acl2_log.txt");
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
Process process = processBuilder.start();
PrintWriter procIn = new PrintWriter(process.getOutputStream());
// Write the ACL2 to the process, exit ACL2 and close the socket
procIn.println(acl2);
procIn.println("(good-bye)");
procIn.flush();
procIn.close();
out.close();
in.close();
client.close();
} // end while loop
server.close();
System.exit(0);
} catch(Exception e) {
e.printStackTrace();
} // end try/catch
} // end function main
} // end class VerifyUser
无效的代码:
package modules.user.register;
import java.io.*;
import java.util.*;
import java.net.*;
public class RegisterUser {
public static void main(String[] args) {
boolean listening = true;
try {
// Acquire the listening port for connection to client.
ServerSocket server = new ServerSocket(20001);
while(listening) {
// Wait until the client connects
Socket client = server.accept();
// Handles for input and output streams relating to the socket connection
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
// Buffers
String input, store="", request="";
// Read the input from the connection
while((input = in.readLine()) != null) {
request += input;
} // end while
// Read the contents of the address-book currently stored
BufferedReader reader = new BufferedReader(new FileReader("store/address-book/address-book.xml"));
while((input = reader.readLine()) != null) {
store += input;
} // end while
// The ACL2 code to execute.
String acl2 = "(include-book \"register-user\")" +
"(in-package \"ACL2\")" +
"(registerUser \"" + request + "\" \"" + store + "\" state)";
// Initialize ACL2 and dump its output to the log
System.out.println("Executing ACL2 runtime for RegisterUser...");
ProcessBuilder processBuilder = new ProcessBuilder("acl2");
File log = new File("logs/user/register/acl2_log.txt");
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
Process process = processBuilder.start();
PrintWriter procIn = new PrintWriter(process.getOutputStream());
// Write the ACL2 to the process, close ACL2
//procIn.println(acl2);
//procIn.println("(good-bye)");
//procIn.flush();
//procIn.close();
// Old store is old address-book file and new store is newly generated
File oldStore = new File("store/address-book/address-book.xml");
File newStore = new File("store/address-book/temp_address-book.xml");
// Response header information
String response = "<?xml version='1.0'?>" +
"<!DOCTYPE response SYSTEM 'dtd/reponse.dtd'>" +
"<response>";
// Determine if there was a change.
// If entry was added, the length > that old length.
if(oldStore.length() < newStore.length()) {
// Replace old file with new file
oldStore.delete();
newStore.renameTo(oldStore);
// Extract data from request XML
String name = request.substring(request.indexOf("<name>")+6, request.indexOf("</name>")-7);
String domain = request.substring(request.indexOf("<domain>")+8, request.indexOf("</domain>")-9);
// Create the store directory for the user's emails
File storeDirectory = new File("store/email/" + domain + "/" + name + "/");
storeDirectory.mkdirs();
response += "<message>ACCEPT</message>";
} else {
// Remove new file as it is pointless
newStore.delete();
response += "<message>REJECT</message>";
} // end if-else
response += "</response>";
// Writeback the response to the client
out.print(response);
out.flush();
// Close all streams
out.close();
in.close();
client.close();
} // end while
} catch(Exception e) {
e.printStackTrace();
} // end try/catch
} // end function main
} // end class RegisterUser
如您所见,我没有在程序中传递任何参数。当我在Windows DOS shell上回显%PATH%时,它表明C:\ ACL2在我的ENV变量中(这是文件夹acl2.exe所在的位置)。我尝试将acl2更改为C:\ ACL2 \ acl2.exe仅具有相同的结果。
令我感到困惑的是为什么第一个完美地工作而第二个(具有几乎完全相同的代码-完全相同的ProcessBuilder代码)却无法正常工作的原因。
看来这段代码是我的问题所在:
System.out.println("Executing ACL2 runtime...");
ProcessBuilder processBuilder = new ProcessBuilder("acl2");
File log = new File("logs/user/register/acl2_log.txt");
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
Process process = processBuilder.start();
PrintWriter procIn = new PrintWriter(process.getOutputStream());
错误:
Executing ACL2 runtime for RegisterUser...
java.io.IOException: Cannot run program "acl2": The system cannot find the path specified
at java.lang.ProcessBuilder.start(Unknown Source)
at modules.user.register.RegisterUser.main(RegisterUser.java:74)
Caused by: java.io.IOException: The system cannot find the path specified
at java.lang.ProcessImpl.openForAtomicAppend(Native Method)
at java.lang.ProcessImpl.newFileOutputStream(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
... 2 more
应该发生的是,启动的进程是ACL2环境,将代码发送给它,然后执行该代码,然后杀死该进程(通过ACL2中的(再见)命令)。之后,代码应在使用Java一点点之后退出,这与发生错误的ACL2进程无关。
VerifyUser程序调用ACL2,将响应写入“ server-response.xml”文件,然后正常退出而不会发生任何事件。
RegisterUser程序应调用ACL2,编写一个响应并优雅地退出,一小段Java代码为用户创建一个目录,并删除一个存储文件,并重命名新生成的目录以供用户注册。
最佳答案
由于抛出异常
at java.lang.ProcessImpl.openForAtomicAppend(Native Method)
并且您使用两种不同的路径:
File log = new File("logs/user/verify/acl2_log.txt");
File log = new File("logs/user/register/acl2_log.txt");
可能找到了
acl
命令,但是无法执行重定向。在这种情况下,错误消息不是很有帮助,但是-如果您在两行之间阅读-也不是错误。