- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图理解我所看到的一些行为。
我有这个 C++ 程序:
// Outputter.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
int main()
{
// UTF-8 bytes for "日本語"
std::cout << (char)0xE6 << (char)0x97 << (char)0xA5 << (char)0xE6 << (char)0x9C << (char)0xAC << (char)0xE8 << (char)0xAA << (char)0x9E;
return 0;
}
如果我在 Powershell 中运行以下命令:
[System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8
.\print_it.exe # This is the above program ^
日本語 # This is the output as displayed in Powershell
然后在 Powershell 中打印并正确显示 日本语
。
但是,如果我将 setlocale(LC_ALL, "English_United States.1252");
添加到代码中,如下所示:
int main()
{
setlocale(LC_ALL, "English_United States.1252");
// UTF-8 bytes for "日本語"
std::cout << (char)0xE6 << (char)0x97 << (char)0xA5 << (char)0xE6 << (char)0x9C << (char)0xAC << (char)0xE8 << (char)0xAA << (char)0x9E;
return 0;
}
程序现在将垃圾打印到 Powershell(æ—¥æœèªž
准确地说,这是代码页 1252 对这些字节的误解)。
但是如果我将输出通过管道传输到文件,然后对文件进行cat,它看起来不错:
.\print_it.exe > out.txt
cat out.txt
日本語 # It displays fine, like this, if I redirect to a file and cat the file.
此外,无论我设置区域设置
为何,Git bash 都会正确显示输出。
有人可以帮助我理解为什么 setlocale 会影响 Powershell 中输出的显示方式,即使相同的字节被写入 stdout 也是如此? Powershell 似乎能够以某种方式访问程序的区域设置并使用它来解释输出?
Powershell 版本为 5.1.17763.592。
最佳答案
这都是关于编码的。您使用 >
获得正确字符的原因重定向是由于 >
重定向使用 UTF-16LE默认情况下。因此您设置的编码 1252 会自动转换为 UTF-16。
根据您的 PowerShell 版本,您可以或不能更改重定向的编码。
如果您使用Out-File
与 -Encoding
切换您可以更改目标文件的编码(同样取决于您的 PowerShell 版本)。
我建议阅读 mklement0 关于此主题的优秀文章 here .
取自 cppreference
std::setlocale C++ Localizations library Defined in header
<clocale>
char* setlocale( int category, const char* locale);
The setlocale function installs the specified system locale or its portion as the new C locale. The modifications remain in effect and influences the execution of all locale-sensitive C library functions until the next call to setlocale. If locale is a null pointer, setlocale queries the current C locale without modifying it.
您发送到std::cout
的字节是相同的,但是 std::cout
是一个区域设置敏感的函数,因此它优先于您的 PowerShell UTF-8 设置。如果您省略 setlocale()
功能std::cout
遵循 shell 编码。
如果您有 Powershell 5.1 及更高版本 >
是 Out-File
的别名。您可以通过 $PSDefaultParameterValues
设置编码:
像这样:
$PSDefaultParameterValues['Out-File:Encoding'] = 'UTF8'
然后你会得到一个 UTF-8 文件(带有 BOM,这可能很烦人!)而不是默认的 UTF-16LE。
PowerShell 使用 OEM 代码页,因此默认情况下您将获得在 Windows 上设置的内容。我建议阅读 encoding on windows 上的一篇优秀文章。关键是,如果没有对 powershell 进行 UTF8 设置,您将处于现有的代码页上。
output.exe
正在将语言环境设置为 English_United States.1252
在 c++ 程序中和 output_original.exe
没有对其进行任何更改:
以下是没有UTF8 PowerShell 设置的输出:
c:\t>.\output.exe
æ-¥æo¬èªz --> nonsese within the win1252 code page
c:\t>.\output.exe | hexdump
0000000 97e6 e6a5 ac9c aae8 009e --> both hex outputs are the same!
0000009
c:\t>.\output_original.exe
日本語 --> nonsense but different one! (depens on your locale setup - my was English)
c:\t>.\output_original.exe | hexdump
0000000 97e6 e6a5 ac9c aae8 009e --> both hex outputs are the same!
0000009
那么这里会发生什么?您的程序根据程序本身或 Windows 中设置的区域设置(在我的虚拟机上为 OEM 代码 1252)给出输出。请注意,在两个版本中,十六进制转储是相同的,但输出(带编码)不同。
如果您使用 [System.Text.Encoding]::UTF8
将 PowerShell 设置为 UTF8 :
PS C:\t> [System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8
PS C:\t> .\output.exe
日本語 --> the english locales 1252 set within program notice that the output is similar to the above one (but the hexdump is different)
PS C:\t> .\output.exe | hexdump
0000000 bbef 3fbf 3f3f 0a0d -> again hex dump is same for both so they are producing the same output!
0000008
PS C:\t> .\output_original.exe
日本語 --> correct output due to the fact you have forced the PowerShell encoding to UTF8, thus removing the output dependence on the OEM code (windows)
PS C:\t> .\output_original.exe | hexdump
0000000 bbef 3fbf 3f3f 0a0d -> again hex dump is same for both so they are producing the same output!
0000008
这里发生了什么?如果您在 C++ 应用程序中强制使用语言环境, std:cout
将使用该语言环境 (1252) 进行格式化,然后将这些字符转换为 UTF8 格式(这就是第一个和第二个示例略有不同的原因)。当您不在 C++ 应用程序中强制使用区域设置时,将采用 PowerShell 编码(现在为 UTF8),您将获得正确的输出。
我发现有趣的一件事是,如果你将 Windows 系统区域设置更改为中文兼容的区域设置(中国、澳门、柴湾、香港等),那么在不强制使用 UTF8 时,你会得到一些中文字符,但会得到不同的字符。这意味着这些字节只是 Unicode,因此只有在那里它才起作用。如果您在 PowerShell 中强制使用 UTF8,即使使用中文 Windows 系统区域设置,它也可以正常工作。
我希望这能更大程度地回答您的问题。
咆哮:我花了很长时间才调查,因为 VS 2019 社区版已经过期(WFT MS?),而且我无法注册它,因为注册窗口完全是空白的。谢谢女士,但不用了。
关于c++ - 为什么 LC_ALL setlocale 设置会影响 Powershell 中的 cout 输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58883361/
我正在寻找实现 PowerShell 提供程序 在 电源外壳。 我一直在想,如果我只是定义类型,然后将它们导入我的 session (导入模块),我应该能够让它们可用。 例如,这个 不工作但它沿着我想
我创建的脚本使用了组件,这些组件仅在32位版本的Powershell中可用。 默认情况下,Windows使用Powershell x64执行脚本,这会导致一些错误。 是一种在脚本开头设置值以强制Win
是否可以从 Powershell 中检测它是否是嵌套 shell? 如果我打开 Powershell 或 cmd.exe 窗口,然后输入 powershell 在那里,是否有一个神奇的 $host.s
随着 PowerShell Core 的发布,应用程序在使用托管自动化库 (system.management.automation) 时如何选择调用哪个版本的 Powershell(Powershe
最近,我加入了我企业的 Windows 团队,凭借我的开发人员背景(一般是 Java、.NET 和 Web),我很快就对 PowerShell 产生了兴趣。我可以看到它比普通的旧批处理文件、VB 更有
假设我有一个 powershell 脚本,它在我当前路径的相对路径中包含一个 Powershell 哈希。让我们称之为“name.ps1”,它包含: $names = @{ "bob" = "b
我想为我正在构建的自定义 Powershell Commandlet 使用 SqlServerCmdletSnapin。如果我将以下代码添加到 PSM1 的开头: if ( (Get-PSSnapin
如何调用从 PowerShell 脚本中获取命名参数的 PowerShell 脚本? foo.ps1: param( [Parameter(Mandatory=$true)][String]$a=''
我即将为 Windows 管理员编写一个 PowerShell 脚本,以帮助他们完成与部署 Web 应用程序相关的某些任务。 有什么理由让我应该赞成或排除开发 PowerShell 模块 (.psm1
我的 powershell 模块有一个函数,我希望它返回一个非零退出代码。但是,作为一个模块函数,当我运行 Import-Module 时,它会加载到 powershell 控制台的上下文中。所以,当
我在这个问题上花了最后 4 个小时,非常感谢您提供的任何意见。 我需要使用不同的凭据调用 powershell 脚本并将参数传递给该脚本。 安装 WISEScript 中包装的程序后,此脚本开始收集机
我有一个场景,我需要将 powershell 命令的命令和输出转发到另一个进程以进行日志记录和处理。 我希望这个控制台尽可能接近 powershell,因此不希望将它简单地托管在另一个控制台程序中。
我正在尝试让一个主 PowerShell 脚本运行所有其他脚本,同时等待 30-60 秒以确保完成任务。我尝试过的所有其他操作都不会停止/等待第一个脚本及其进程完成,然后才能同时完成所有其他脚本,并且
我正在编写一个脚本来使用多个 plink (PuTTY) session 作为 Windows 版本的 clustersh。然而,我陷入困境,因为我想从 powershell 打开多个 Powersh
我读了这个答案:How to Open Powershell from Powershell start powershell 这将打开基础的大分辨率 PS 实例。如何打开 PS(x86)? 最佳答案
我很想知道我们是否可以在 Powershell 中做到这一点。 使用 Out-File 命令,我们可以通过管道将其输出写入文件。这样我就可以将我所有的历史命令发送到一个文本文件中。 问题是我可以在每次
我在 about_Pipelines 阅读了有关 PowerShell 中的管道工作原理的信息,并了解到管道一次传送一个对象。 所以,这个 Get-Service | Format-Table -Pr
我正在尝试像这样从 powershell 启动一个进程:- $proc = (start-process $myExe -argumentList '/myArg True' -windowStyle
## To run the script # .\get_status.ps1 -Hostname -Service_Action -Service_Name #$Hostname = "hos
让我们使用 powershell 命令 Write-Host "red text"-Fore red这会在红色前景中显示“红色文本”。 但是,您希望文本以稍微亮一点的方式显示字体颜色,浅红色。 有没有
我是一名优秀的程序员,十分优秀!