7

我想启动一个浏览器并使用 Java 的 Runtime exec 加载一个网页。确切的调用如下所示:

String[] explorer = {"C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE", 
    "-noframemerging", 
    "C:\\ ... path containing unicode chars ... \\Main.html"};
Runtime.getRuntime().exec(explorer);

在我的例子中,路径包含"\u65E5\u672C\u8A9E"字符日本语。

显然这是一个 java 错误: http ://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4947220

我的问题是:是否有一个可行的解决方法可以仅使用 Java 完成?似乎可以为此编写一个 JNI 库,但如果可能的话,我想避免这种情况。我尝试将路径 URI 编码为 ascii 并将命令写入批处理文件,但没有成功。

4

6 回答 6

2

在提到的Java 错误页面上,您将找到一种解决方法,据报道该解决方法可以使用 ProcessBuilder 并将参数包装在环境变量中。这是来自 Parag Thakur 的源代码:

String[] cmd = new String[]{"yourcmd.exe", "Japanese CLI argument: \ufeff\u30cb\u30e5\u30fc\u30b9"};        
Map<String, String> newEnv = new HashMap<String, String>();
newEnv.putAll(System.getenv());
String[] i18n = new String[cmd.length + 2];
i18n[0] = "cmd";
i18n[1] = "/C";
i18n[2] = cmd[0];
for (int counter = 1; counter < cmd.length; counter++)
{
    String envName = "JENV_" + counter;
    i18n[counter + 2] = "%" + envName + "%";
    newEnv.put(envName, cmd[counter]);
}
cmd = i18n;

ProcessBuilder pb = new ProcessBuilder(cmd);
Map<String, String> env = pb.environment();
env.putAll(newEnv);
final Process p = pb.start();
于 2010-08-11T15:49:56.080 回答
2

创建一个 .bat/.sh 文件。将您的命令写入该文件并执行它。确保在 windows (chcp 65001) 的情况下已将代码页更改为 unicode。例如在 windows 中执行以下命令:

String[] command ={"C:\\aconex\\学校\\mysql\\bin\\mysql", "-esource", "大村箕島a\\data.sql"};

创建一个名为 temp.bat 的临时文件并使用 Runtime.getRuntime().exec temp.bat执行

chcp 65001
C:\aconex\学校\mysql\bin\mysql -esource 大村箕島a\data.sql
于 2015-03-23T05:44:11.787 回答
0

这是我考虑过的两个解决方案,每个解决方案或多或少都是解决方法:

  1. 创建一个临时 html 重定向文件,它将浏览器重定向到正确的页面。请注意,IE 将期望本地文件未编码的 unicode,而其他浏览器可能只接受 uri 编码的文件路径

  2. 使用 windows 文件的短文件名。它不会包含 unicode 字符。

于 2009-12-16T19:25:25.003 回答
0

多年来,我们一直在使用 JNI 从 Java 启动进程。Runtime.exec 或 ProcessBuilder 都不起作用,而且考虑到它已经存在了多长时间,他们似乎不太可能解决这个问题。

但是,您应该能够通过使用输入流、套接字或环境变量来传递参数来解决此问题。如果您无法直接控制可执行文件,则必须制作一个包装器。

于 2011-06-15T03:49:38.087 回答
0

你可以使用JNA。使用 3.3.0 或更高版本调用CreateProcess

WinBase.PROCESS_INFORMATION.ByReference processInfo = 
    new WinBase.PROCESS_INFORMATION.ByReference();
WinBase.STARTUPINFO startupInfo = new WinBase.STARTUPINFO();

String command = "C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE " +
    "-noframemerging \"C:\\\u65E5\u672C\u8A9E\\Main.html\"";

if (!Kernel32.INSTANCE.CreateProcess(
    null,           // Application name, not needed if supplied in command line
    command,        // Command line
    null,           // Process security attributes
    null,           // Thread security attributes
    true,           // Inherit handles
    0,              // Creation flags
    null,           // Environment
    null,           // Directory
    startupInfo,
    processInfo))
{
    throw new IllegalStateException("Error creating process. Last error: " +
        Kernel32.INSTANCE.GetLastError());
}

// The CreateProcess documentation indicates that it is very important to 
// close the returned handles
Kernel32.INSTANCE.CloseHandle(processInfo.hThread);
Kernel32.INSTANCE.CloseHandle(processInfo.hProcess);

long pid = processInfo.dwProcessId.longValue();

重定向子进程的输出有点困难,但并非不可能。

于 2011-09-20T06:26:07.037 回答
-1

我认为您可以使用Apache Commons Exec库或ProcessBuilder来试一试;)

于 2009-12-16T19:34:36.280 回答