Java 尽管设置了代码页和输出编码,但使用 Powershell 3 返回问号的代码执行命令。

Java code executing command with Powershell 3 returning question marks despite setting codepage and outputEncoding.

这是关于一个问题,我已经做了相当多的研究,但找不到适合我的答案。因此发布一个新问题。

总结 使用 java 代码和 powershell 3 执行 powershell 命令不会返回 UTF-8 characters。当我使用 java 代码和 powershell 版本 2.

执行相同的命令时,同样的事情起作用

场景: 我有一个 java 代码,它正在启动一个新进程并执行 powershell 脚本。 最后,是完整的 java 文件和我设置代码页和 outputEncoding 的 powershell 脚本,以便我可以获得 UTF-8 格式的输出。 下面是未给出预期结果的 java 代码片段:

//String command = "powershell.exe -ExecutionPolicy RemoteSigned \"C:\temp\ListDirectory.ps1\"";
String command = "powershell.exe -Version 2.0 -ExecutionPolicy RemoteSigned \"C:\temp\ListDirectory.ps1\"";
Process powerShellProcess = Runtime.getRuntime().exec(command);
powerShellProcess.getOutputStream().close();
String line;

System.out.println("Standard Output:");
//PrintStream out = new PrintStream(System.out, true, "UTF-8");
//CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();

BufferedReader stdout = new BufferedReader(new InputStreamReader(powerShellProcess.getInputStream(), "UTF-8"));
while ((line = stdout.readLine()) != null) {
   System.out.println(line);
}
stdout.close();

现在的问题是,当我 运行 使用 powershell version 2.0 明确地给出预期的输出(即显示 UTF-8 字符,这里是雪人字符)时,这段代码工作正常:

C:\temp\Snowman☃folder\snowman☃file

但是当我取消注释第一行(使用最新版本的 powershell)和 运行 java 代码时,它 returns 我 ? 雪人角色。这是输出:

C:\temp\Snowman?folder\snowman?file

我尝试了多种选择,例如

请提出我遗漏了什么或我应该探索的东西。 提前致谢。

这是完整的 Java 代码

public class PowershellUtil {

public static void main(String[] args) throws IOException {

    invokePowershell();
    //printString();
}

static void printString() throws IOException {
    String snowman = "Ê ☃ é";
    PrintStream out = new PrintStream(System.out, true, "UTF-8");
    out.println(snowman);
}

static void invokePowershell() throws IOException {

    // String command = "powershell.exe your command";
    // Getting the version
    // String command = "powershell.exe  $PSVersionTable";
    //String command = "powershell.exe -Version 2.0 Get-ChildItem -LiteralPath 'C:\temp\Snowman☃folder' -Recurse -Filter 'snowman☃file' | ForEach-Object {$_.FullName}";
    //String command = "powershell.exe -ExecutionPolicy RemoteSigned \"C:\temp\ListDirectory.ps1\"";
    String command = "powershell.exe -Version 2.0 -ExecutionPolicy RemoteSigned \"C:\temp\ListDirectory.ps1\"";

    // Executing the command
    /*String[] envp = { "file.encoding=UTF8" };
    Process powerShellProcess = Runtime.getRuntime().exec(command, envp);*/
    Process powerShellProcess = Runtime.getRuntime().exec(command);

    // Getting the results
    powerShellProcess.getOutputStream().close();
    String line;
    System.out.println("Standard Output:");
    //PrintStream out = new PrintStream(System.out, true, "UTF-8");
    //CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();

    BufferedReader stdout = new BufferedReader(
            new InputStreamReader(powerShellProcess.getInputStream(), "UTF-8"));
    while ((line = stdout.readLine()) != null) {
        System.out.println(line);
    }
    stdout.close();
    /*InputStreamReader isr = new InputStreamReader(powerShellProcess.getInputStream());
    int data = isr.read();
    while (data != -1) {
        char theChar = (char) data;
        System.out.println("read character: " + String.valueOf(theChar));
        data = isr.read();
    }
    isr.close();*/

    System.out.println("Standard Error:");
    BufferedReader stderr = new BufferedReader(
            new InputStreamReader(powerShellProcess.getErrorStream()));
    while ((line = stderr.readLine()) != null) {
        System.out.println(line);
    }
    stderr.close();
    System.out.println("Done");
}

}

这里是powershell脚本

Set-Variable UTF8_CODEPAGE 65001
Set-Variable UTF8_ENCODING "System.Text.UTF8Encoding"
chcp $UTF8_CODEPAGE > $null
$OutputEncoding = New-Object -typename $UTF8_ENCODING
# $OutputEncoding = [System.Text.Encoding]::UTF8
# Get-ChildItem -LiteralPath 'C:\temp\Snowman☃folder' -Recurse -Filter 'snowman☃file' | ForEach-Object FullName | Out-File 'C:\temp\result.txt'
Get-ChildItem -LiteralPath 'C:\temp\Snowman☃folder' -Recurse -Filter 'snowman☃file' | ForEach-Object {$_.FullName}
# Get-Content -Path "C:\temp\result.txt" -Encoding UTF8

在打印输出之前设置 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8