更新时间:2022-11-08 15:55:41
还是,我想知道我的原始语法出了什么问题.
Still, I would like to know what is wrong with my original syntax.
Your original syntax (fundamentally correctly) uses argument mode, in which arguments are, loosely speaking, evaluated as follows:
$
,(
或 @
开头的参数被视为字符串,即使未加引号;值得注意的是,在这些特殊字符中, [
不是 .$
, (
, or @
is treated as a string, even if not quoted; notably, [
is not among these special characters.因此, [System.Text.Encoding] :: UTF8
被解释为字符串文字 ,而不是被解释为返回 System.Text.Encoding
实例,找不到第三个参数为 string 的 System.IO.StreamWriter
构造函数.
Therefore, [System.Text.Encoding]::UTF8
is interpreted as a string literal rather than as an expression that returns an System.Text.Encoding
instance, and no System.IO.StreamWriter
constructor whose 3rd argument is a string can be found.
如 PetSerAl 的评论中所述,正确的解决方案是封闭 [System.text.Encoding] :: UTF8
放在(...)
中,以便在 expression 模式中强制其求值,从而产生理想的结果.
The correct solution, as mentioned in a comment by PetSerAl, is to enclose [System.Text.Encoding]::UTF8
in (...)
so as to force its evaluation in expression mode, where it yields the desired result.
请注意,以上内容还暗示 a.txt
周围的"..."
(双引号)不是必需的(但无害),因此我们得到:
Note that the above also implies that the "..."
(double quotes) around a.txt
aren't necessary (but do no harm), so we get:
注意:为简洁起见,在以下示例命令的完整类型中,我省略了初始的 System
组件.例如, IO.StreamWriter
是指 System.IO.StreamWriter
.在大多数情况下,在PowerShell中指定 System.
部分是可选.
Note: For brevity, I've omitted the initial System.
components from the full types in the following sample commands; e.g., IO.StreamWriter
refers to System.IO.StreamWriter
. Specifying the System.
part is optional in PowerShell in most contexts.
$f = New-Object IO.StreamWriter a.txt, $false, ([Text.Encoding]::UTF8)
请注意,是各个构造函数参数之间的
,导致它们以 array 的形式传递-即,单个参数-到 新对象
,它(在位置上)绑定到数组类型的 -ArgumentList
( -Args
)参数.
顺便说一句:将个别参数按位置传递给 separate 参数更为常见,并且需要空格来分隔它们;例如 Select-String foo t.txt
被解析为选择字符串-模式foo-路径t.txt
.
Note that it is the ,
between the individual constructor arguments that causes them to be passed as an array - i.e., a single argument - to New-Object
, where it is (positionally) bound to the array-typed -ArgumentList
(-Args
) parameter.
As an aside: passing individual arguments positionally to separate parameters is more common, and requires spaces to separate them; e.g., Select-String foo t.txt
is parsed asSelect-String -Pattern foo -Path t.txt
.
您自己的答案(已删除)使用了 伪方法语法,该语法***避免,并且仅发生工作:
Your own answer (since deleted) uses pseudo method syntax that is best avoided and only happens to work:
# AVOID: pseudo method syntax.
$f = New-Object IO.StreamWriter("a.txt", $false, [Text.Encoding]::UTF8)
即使此看起来像一个方法调用(构造函数调用),它也不是,并且实际上按以下方式进行了解析:
Even though this looks like a method call (constructor call), it isn't, and is actually parsed as follows:
$f = New-Object IO.StreamWriter -ArgumentList ("a.txt", $false, [Text.Encoding]::UTF8)
也就是说,您已经将原始参数数组包含在(...)
中,这导致其元素以 expression 模式进行解析,其中包括解决您问题的 [Text.Encoding] :: UTF8
.
That is, you've enclosed the original argument array in (...)
, which causes its elements to be parsed in expression mode, including [Text.Encoding]::UTF8
, which happened to solve your problem.
请注意-与参数模式不同,必须将字符串 a.txt
括在"..."
(或'...')在表达式模式下.
Note that - unlike in argument mode - string a.txt
does have to be enclosed in "..."
(or '...'
) in expression mode.
请注意, PSv5 + 确实确实通过静态 new()提供了一种基于方法的构建对象的方式
.方法在类型信息对象上公开 ,在这种情况下,所有参数都以 expression 模式进行解析:>
Note that PSv5+ does offer a method-based way to construct objects, via the static new()
method exposed on type-information objects, in which case all arguments are parsed in expression mode:
# PowerShell version 5 and above; you can use the ::new() method on types.
$f = [IO.StreamWriter]::new("a.txt", $false, [Text.Encoding]::UTF8)
关于何时需要 [System.Text.Encoding] :: UTF8
的注释:
A note on when [System.Text.Encoding]::UTF8
is needed:
与Window PowerShell不同,.NET 默认为 UTF-8(PowerShell [Core](v6 +)现在也是如此).
Unlike Window PowerShell, .NET defaults to UTF-8 (which PowerShell [Core] (v6+) now does too).
读取数据时,因此通常不需要显式请求UTF-8编码 .
When you read data, you therefore normally don't need to request UTF-8 encoding explicitly.
写入数据时,传递 [System.Text.Encoding] :: UTF8
会导致UTF-8文件 BOM ,而依赖于默认 UTF-8编码会创建一个没有 BOM的文件(这对于跨平台互操作性更好);要显式请求无BOM编码,请使用 [System.Text.Utf8Encoding] :: new()
.
When you write data, passing [System.Text.Encoding]::UTF8
results in a UTF-8 file with a BOM, whereas relying on the default UTF-8 encoding creates a file without a BOM (which is better for cross-platform interoperabiliy); to request a BOM-less encoding explicitly, use [System.Text.Utf8Encoding]::new()
.