You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Set-Content/Add-Content/Get-Content use an 8-bit character encoding by default, but the help topics state ASCII; problematic Core default file encoding #3248
That is, ASCII encoding turns a non-ASCII character into literal? (0x3f)
The fact that Set-Content without an -Encoding argument resulted in ö on reading implies that ASCII encoding wasn't used, and the specific byte value of 0xf6 further implies that that a single-byte, extended-ASCII encoding was used:
For Windows PowerShell, it is the respective system's legacy codepage ("ANSI"), such as Windows-1252 on US-English systems, or Windows-1251 on Russian systems. In other words: the specific encoding is, to put it in Unix terms, locale-dependent.
changed the title [-]Set-Content/Add-Content/Get-Content use Default ("ANSI") character encoding by default, but the help topics state ASCII[/-][+]Set-Content/Add-Content/Get-Content use an 8-bit character encoding by default, but the help topics state ASCII[/+]on Mar 3, 2017
Lets see PowerShell FullCRL. Default use function GetACP (Retrieves the current Windows ANSI code page identifier for the operating system.) See .Net Framework Reference
OEM is in only PowerShell and use function GetOEMCP (Returns the current original equipment manufacturer (OEM) code page identifier for the operating system.) See PowerShell code
I don't know why the both encodings was added in Powershell. Maybe PowerShell PG comment this.
Default is still not released in CoreCLR - so it is external issue. Maybe PowerShell PG find out this internally with .Net team. And should we use waiting-netstandart20 label? OEM is not in CoreCLR at all - so it seems is internal issue. Is it make sense to fix it?
Here Default is not PowerShell default, it is OS default. Every system can has own default. Original .Net code use GetACP() to get OS default code page. Modern Unix use en_US.UTF-8 as default.
As you can see then we can properly read and write files on Windows Russian with 1251 (default system) code page by: Get-Content -Encoding Default and Set-Content -Encoding Default
As far as Unix locale names mapping Unix uses standard names Table of locales (This is not a complete sample). Therefore, the fix in CoreCLR will not be too difficult.
We should wait for MSFT expert conclusion and then it will be clear that we need to fix in the code and documentation.
Ilya (@iSazonov): Good idea. I've cleaned up my comments here, and I've revised the original post to point to the relevant other issues / comments / RFC.
changed the title [-]Set-Content/Add-Content/Get-Content use an 8-bit character encoding by default, but the help topics state ASCII[/-][+]Set-Content/Add-Content/Get-Content use an 8-bit character encoding by default, but the help topics state ASCII; problematic Core default file encoding[/+]on Mar 6, 2017
Ilya (@iSazonov): I hear you, but do users who rely on this kind of software need this legacy support in PowerShell Core? Aren't users who rely on legacy Windows applications likely to stay in the realm of Windows PowerShell?
I see the following fundamental options (from a purely conceptual standpoint - ease of implementation is not being considered here).
I think it's important to get clarity with respect to what should be implemented - as opposed to what can be.
Based on the appropriate way forward, we can assess what aspects should be implemented by the underlying .NET Core rather than in PowerShell Core.
(a) Core-NoWinLegacy:
Forgo all Windows legacy support in PowerShell Core - only implement it in Windows PowerShell.
(b) Core-WinLegacy-onWindows:
Provide Windows legacy support in PowerShell Core too, but only on Windows.
(c) Core-WinLegacy-Everywhere:
Provide Windows legacy support in PowerShell Core on all platforms, including Unix.
(c) may be what James Truher (@JamesWTruher) had in mind in his RFC, though the RFC mistakenly assumes only having to deal with 1, fixed single-byte legacy behavior: ASCII - whereas the truth is that a whole raft of culture-specific "ANSI" codepages must be emulated.
—
As for how these options relate to things needed from .NET Core:
(a) clearly needs no additional effort.
(b) also needs no additional effort - the aforementioned NuGet package can bring in all Windows legacy code pages, and [cultureinfo]::CurrentCulture.TextInfo.ANSICodePage and [cultureinfo]::CurrentCulture.TextInfo.OEMCodePageon Windows already tell us what code pages to use as the legacy defaults.
(c) Will be implemented in .NET CoreCLR v2: The current pre-v2 version already reports values for [cultureinfo]::CurrentCulture.TextInfo.ANSICodePage and [cultureinfo]::CurrentCulture.TextInfo.OEMCodePage on Unix too, performing the aforementioned mapping of Unix locale identifiers to legacy Windows code pages.
There are still edge cases - see below.
That said, if the consensus is to implement (c), these edge cases (see bottom) should be considered an acceptable price to pay for Windows legacy support on Unix.
Note that currently, Unix legacy support is not even part of the debate - while UTF-8-based locales are near-ubiquitous nowadays, Unix platforms still support legacy locales based on single-byte charmaps comparable to Windows legacy code pages.
To be legacy-friendly on Unix platforms, these charmaps would have to be respected too.
.NET Core, with the limited set of code pages it comes with, is not capable of this legacy Unix support, and, as of this writing, the preview version of v2 doesn't change that.
Edge cases when mapping Unix locales to Windows legacy code pages:
As mentioned before, some culture uses more than one script (alphabet); gotta love Wikipedia:
Serbian is practically the only European standard language with complete synchronic digraphia,[15] using both Cyrillic and Latin alphabets;
Thus, when mapping a Serbian Unix locale to a legacy Windows code page, one or the other alphabet must be chosen, because no single legacy code page can represent both alphabets.
This choice isn't unambiguous.
Here is the list of Serbian (sr_*) locales available on two sample Unix platforms:
macOS 10.12:
sr_YU
sr_YU.ISO8859-2
sr_YU.ISO8859-5
sr_YU.UTF-8
Ubuntu 16.04:
sr_ME UTF-8
sr_RS UTF-8
sr_RS@latin UTF-8
macOS is stuck in the past (YU representing the long-defunct former Yugoslavia); the .ISO8859-2 and .ISO8859-5 unambiguously imply the Latin and Cyrillic alphabet respectively, but what sr_YU.UTF-8 should map to - given that UTF-8 is capable of encoding both alphabets - is open to interpretation. If there's always a preferred alphabet for such cultures, perhaps that's a non-issue - I don't know the answer to that.
Ubuntu faces the same issues, with only sr_RS@latin UTF-8implying the alphabet via the embedded @latin script/variant identifier.
In practice, as of .NET Core v2.0.0-beta-001836-00, all of the above cases default to the Latin alpabet.
First just want to say, thanks for the extended explanations, everyone. This has been thoroughly useful. And thanks, Ilya (@iSazonov), for looping in the dotnet/standard folks.
Now, next steps:
I want to tease the encoding issue into as many smaller chunks as possible. This thread was originally about the OEM/Default codepage issue. If we can fix that in Windows with a platform-specific guard today, and fix it later on Linux with .NET Standard and System.Text.Encoding.CodePages, we should do that and close out this issue.
As I said in the other thread, I'm not concerned about the legacy Linux encoding scenario. It's uncommon, and we don't have baggage there.
The other questions should all be addressed in RFC0020 Default File Encoding PowerShell-RFC#71 and fixed in the RFC so that everyone can have a central view of how we're addressing encodings and so the @PowerShell/powershell-committee can sign off on that view.
Joey Aiello (@joeyaiello): Thanks, that indeed sounds reasonable (and I hope it's OK that, as an outsider, I'm being vocal here - I love PowerShell and I think getting the encoding right is crucial to PowerShell's cross-platform success).
Per the plan I posted above, let's close this particular as resolved, and drive the RFC to completion via the normal process. If other issues arise after that, we should open new issues.
Activity
iSazonov commentedon Mar 3, 2017
The default is changed for PowerShell Core to ISO-8859-1
For OEM too ISO-8859-1
File provider
GetContentReader
GetContentWriter
[-]Set-Content/Add-Content/Get-Content use Default ("ANSI") character encoding by default, but the help topics state ASCII[/-][+]Set-Content/Add-Content/Get-Content use an 8-bit character encoding by default, but the help topics state ASCII[/+]iSazonov commentedon Mar 4, 2017
This is real regression (breaking change) and we should fix it.
iSazonov commentedon Mar 4, 2017
The
Defaultis changed for PowerShell Core to ISO-8859-1For
OEMISO-8859-1 too.Lets see PowerShell FullCRL.
Defaultuse function GetACP (Retrieves the current Windows ANSI code page identifier for the operating system.) See .Net Framework ReferenceOEMis in only PowerShell and use function GetOEMCP (Returns the current original equipment manufacturer (OEM) code page identifier for the operating system.) See PowerShell codeI don't know why the both encodings was added in Powershell. Maybe PowerShell PG comment this.
Defaultis still not released in CoreCLR - so it is external issue. Maybe PowerShell PG find out this internally with .Net team. And should we usewaiting-netstandart20label?OEMis not in CoreCLR at all - so it seems is internal issue. Is it make sense to fix it?iSazonov commentedon Mar 4, 2017
Michael Klement (@mklement0) See .Net Framework Reference
We can not use Windows-1252 as default.
iSazonov commentedon Mar 5, 2017
Here
Defaultis not PowerShell default, it is OS default. Every system can has own default. Original .Net code useGetACP()to get OS default code page. Modern Unix useen_US.UTF-8as default.SteveL-MSFT commentedon Mar 5, 2017
cc James Truher (@JamesWTruher) Bruce Payette (@BrucePay)
iSazonov commentedon Mar 5, 2017
Michael Klement (@mklement0) Current
Windows Powershellbehavior is based on .Net Framework and it is dynamic:Current
PowerShell Corebehavior is hard-coded to ISO-8859-1. If we change it on Windows-1252 we still not get Windows PowerShell behavior:Preferred solution is to fix this in CoreCLR.
As you can see then we can properly read and write files on Windows Russian with 1251 (default system) code page by:
Get-Content -Encoding DefaultandSet-Content -Encoding DefaultAs far as Unix locale names mapping Unix uses standard names Table of locales (This is not a complete sample). Therefore, the fix in CoreCLR will not be too difficult.
We should wait for MSFT expert conclusion and then it will be clear that we need to fix in the code and documentation.
iSazonov commentedon Mar 6, 2017
Michael Klement (@mklement0) We have a RFC draft for this. Welcome to discuss PowerShell/PowerShell-RFC#71
mklement0 commentedon Mar 6, 2017
Ilya (@iSazonov): Good idea. I've cleaned up my comments here, and I've revised the original post to point to the relevant other issues / comments / RFC.
[-]Set-Content/Add-Content/Get-Content use an 8-bit character encoding by default, but the help topics state ASCII[/-][+]Set-Content/Add-Content/Get-Content use an 8-bit character encoding by default, but the help topics state ASCII; problematic Core default file encoding[/+]iSazonov commentedon Mar 6, 2017
Michael Klement (@mklement0)
See full PowerShell repo list https://github.com/PowerShell/
SteveL-MSFT commentedon Mar 6, 2017
Michael Klement (@mklement0) more specifically https://github.com/powershell/powershell-docs
9 remaining items
iSazonov commentedon Mar 24, 2017
There is a huge amount of software that only works with legacy code pages. Although the number has decreased since 2003 year.
mklement0 commentedon Mar 26, 2017
Ilya (@iSazonov): I hear you, but do users who rely on this kind of software need this legacy support in PowerShell Core? Aren't users who rely on legacy Windows applications likely to stay in the realm of Windows PowerShell?
I see the following fundamental options (from a purely conceptual standpoint - ease of implementation is not being considered here).
I think it's important to get clarity with respect to what should be implemented - as opposed to what can be.
Based on the appropriate way forward, we can assess what aspects should be implemented by the underlying .NET Core rather than in PowerShell Core.
(a) Core-NoWinLegacy:
Forgo all Windows legacy support in PowerShell Core - only implement it in Windows PowerShell.
(b) Core-WinLegacy-onWindows:
Provide Windows legacy support in PowerShell Core too, but only on Windows.
(c) Core-WinLegacy-Everywhere:
Provide Windows legacy support in PowerShell Core on all platforms, including Unix.
(c) may be what James Truher (@JamesWTruher) had in mind in his RFC, though the RFC mistakenly assumes only having to deal with 1, fixed single-byte legacy behavior: ASCII - whereas the truth is that a whole raft of culture-specific "ANSI" codepages must be emulated.
—
As for how these options relate to things needed from .NET Core:
(a) clearly needs no additional effort.
(b) also needs no additional effort - the aforementioned NuGet package can bring in all Windows legacy code pages, and
[cultureinfo]::CurrentCulture.TextInfo.ANSICodePageand[cultureinfo]::CurrentCulture.TextInfo.OEMCodePageon Windows already tell us what code pages to use as the legacy defaults.(c) Will be implemented in .NET CoreCLR v2: The current pre-v2 version already reports values for
[cultureinfo]::CurrentCulture.TextInfo.ANSICodePageand[cultureinfo]::CurrentCulture.TextInfo.OEMCodePageon Unix too, performing the aforementioned mapping of Unix locale identifiers to legacy Windows code pages.There are still edge cases - see below.
That said, if the consensus is to implement (c), these edge cases (see bottom) should be considered an acceptable price to pay for Windows legacy support on Unix.
Note that currently, Unix legacy support is not even part of the debate - while UTF-8-based locales are near-ubiquitous nowadays, Unix platforms still support legacy locales based on single-byte charmaps comparable to Windows legacy code pages.
To be legacy-friendly on Unix platforms, these charmaps would have to be respected too.
.NET Core, with the limited set of code pages it comes with, is not capable of this legacy Unix support, and, as of this writing, the preview version of v2 doesn't change that.
Edge cases when mapping Unix locales to Windows legacy code pages:
As mentioned before, some culture uses more than one script (alphabet); gotta love Wikipedia:
Thus, when mapping a Serbian Unix locale to a legacy Windows code page, one or the other alphabet must be chosen, because no single legacy code page can represent both alphabets.
This choice isn't unambiguous.
Here is the list of Serbian (
sr_*) locales available on two sample Unix platforms:macOS is stuck in the past (
YUrepresenting the long-defunct former Yugoslavia); the.ISO8859-2and.ISO8859-5unambiguously imply the Latin and Cyrillic alphabet respectively, but whatsr_YU.UTF-8should map to - given that UTF-8 is capable of encoding both alphabets - is open to interpretation.If there's always a preferred alphabet for such cultures, perhaps that's a non-issue - I don't know the answer to that.
Ubuntu faces the same issues, with only
sr_RS@latin UTF-8implying the alphabet via the embedded@latinscript/variant identifier.In practice, as of .NET Core v2.0.0-beta-001836-00, all of the above cases default to the Latin alpabet.
iSazonov commentedon Mar 28, 2017
Joey Aiello (@joeyaiello) Steve Lee (@SteveL-MSFT) Michael Klement (@mklement0) I opened issue-question in .Net Core repo and get great comments about defaults dotnet/standard#260 (comment)
joeyaiello commentedon Mar 30, 2017
First just want to say, thanks for the extended explanations, everyone. This has been thoroughly useful. And thanks, Ilya (@iSazonov), for looping in the dotnet/standard folks.
Now, next steps:
OEM/Defaultcodepage issue. If we can fix that in Windows with a platform-specific guard today, and fix it later on Linux with .NET Standard andSystem.Text.Encoding.CodePages, we should do that and close out this issue.Sound reasonable?
iSazonov commentedon Mar 31, 2017
I pushed PR with fix for Default/OEM.
mklement0 commentedon Apr 1, 2017
Joey Aiello (@joeyaiello): Thanks, that indeed sounds reasonable (and I hope it's OK that, as an outsider, I'm being vocal here - I love PowerShell and I think getting the encoding right is crucial to PowerShell's cross-platform success).
joeyaiello commentedon Apr 5, 2017
Ilya (@iSazonov) Sweet!
Michael Klement (@mklement0) I don't consider you an outsider, you're here constructively voicing opinions. Keep it coming 👍
And for what it's worth, I absolutely agree. We need to nail encodings.
Fix Default/OEM encoding behavior PowerShell Core (#3467)
iSazonov commentedon Apr 6, 2017
#3467 merged and we would close the Issue or leave it open in waiting our Encoding RFC.
joeyaiello commentedon Apr 14, 2017
Per the plan I posted above, let's close this particular as resolved, and drive the RFC to completion via the normal process. If other issues arise after that, we should open new issues.
Fix Default/OEM encoding behavior PowerShell Core (PowerShell#3467)