Java 和 .NET/PowerShell 产生不同的 UTF-8 字节
Java and .NET/PowerShell producing different UTF-8 bytes
我头发都白了。
我需要将 PowerShell 中的字符串转换为 UTF-8。我的参考代码在 Java 中(并且可以在更大的应用程序中正常工作),所以我需要重现它的作用。
在Java中,我做:
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
public static void main(String[] args) throws Exception {
System.out.println(bytesToHex("aöß".getBytes("UTF8")));
}
输出61C3B6C39F
.
在 PowerShell 中,我这样做
Write-Output $(([System.Text.UTF8Encoding]::New($false, $true).getBytes("aöß") | ForEach-Object ToString X2) -join '')
输出61C383C2B6C383C5B8
它们为什么不同?如何使 PowerShell 编码与 Java 匹配?
如有任何见解,我将不胜感激!
最佳
eDude
编辑:好的,现在我更困惑了。当 运行 在 PowerShell 5.1 控制台中执行上述命令时,它按预期工作。当把它放入脚本文件并执行时,它没有。
编辑 2:更多信息,如果脚本文件以 UTF-8 编码保存,则会出现错误。如果它以另一种编码(例如 Notepad++ 的 ANSI)保存,它就可以工作。为什么脚本文件的编码会改变脚本本身的行为?我怎样才能避免这种情况并确保获得一致的结果?
尝试在 Notepad++ 中将您的脚本文件转换为 UTF-8-BOM
编码并 运行 它。 PowerShell 5 的默认编码是 Western European (Windows)
(windows-1252
),因此当您的脚本文件中没有 BOM 时,它会将其读取为 UTF-16,因此是双倍长度的字符串。
PowerShell 7 中的默认编码是 UTF-8
,所以这应该不是问题。
您可以像这样检查不同 powershell 版本的默认编码:
PS> [System.Text.Encoding]::Default
您还可以指定所需的字符以避免在没有 BOM 的文件中出现此问题:
$str = [char]0x0061 + [char]0x00F6 + [char]0x00DF
Write-Output $(([System.Text.Encoding]::UTF8.GetBytes($str) | ForEach-Object ToString X2) -join '')
我头发都白了。 我需要将 PowerShell 中的字符串转换为 UTF-8。我的参考代码在 Java 中(并且可以在更大的应用程序中正常工作),所以我需要重现它的作用。
在Java中,我做:
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
public static void main(String[] args) throws Exception {
System.out.println(bytesToHex("aöß".getBytes("UTF8")));
}
输出61C3B6C39F
.
在 PowerShell 中,我这样做
Write-Output $(([System.Text.UTF8Encoding]::New($false, $true).getBytes("aöß") | ForEach-Object ToString X2) -join '')
输出61C383C2B6C383C5B8
它们为什么不同?如何使 PowerShell 编码与 Java 匹配?
如有任何见解,我将不胜感激!
最佳 eDude
编辑:好的,现在我更困惑了。当 运行 在 PowerShell 5.1 控制台中执行上述命令时,它按预期工作。当把它放入脚本文件并执行时,它没有。
编辑 2:更多信息,如果脚本文件以 UTF-8 编码保存,则会出现错误。如果它以另一种编码(例如 Notepad++ 的 ANSI)保存,它就可以工作。为什么脚本文件的编码会改变脚本本身的行为?我怎样才能避免这种情况并确保获得一致的结果?
尝试在 Notepad++ 中将您的脚本文件转换为 UTF-8-BOM
编码并 运行 它。 PowerShell 5 的默认编码是 Western European (Windows)
(windows-1252
),因此当您的脚本文件中没有 BOM 时,它会将其读取为 UTF-16,因此是双倍长度的字符串。
PowerShell 7 中的默认编码是 UTF-8
,所以这应该不是问题。
您可以像这样检查不同 powershell 版本的默认编码:
PS> [System.Text.Encoding]::Default
您还可以指定所需的字符以避免在没有 BOM 的文件中出现此问题:
$str = [char]0x0061 + [char]0x00F6 + [char]0x00DF
Write-Output $(([System.Text.Encoding]::UTF8.GetBytes($str) | ForEach-Object ToString X2) -join '')