Simplify getting Encoding in TranscriptionOption.FlushContentToDisk
(#13910)
This commit is contained in:
parent
41ab20cce3
commit
971c428769
|
@ -1391,96 +1391,11 @@ namespace System.Management.Automation
|
|||
return hresult >= 0;
|
||||
}
|
||||
|
||||
// Attempt to determine the existing encoding
|
||||
internal static Encoding GetEncoding(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return ClrFacade.GetDefaultEncoding();
|
||||
}
|
||||
|
||||
byte[] initialBytes = new byte[100];
|
||||
int bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
using (FileStream stream = System.IO.File.OpenRead(path))
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
bytesRead = reader.Read(initialBytes, 0, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return ClrFacade.GetDefaultEncoding();
|
||||
}
|
||||
|
||||
// Test for four-byte preambles
|
||||
string preamble = null;
|
||||
Encoding foundEncoding = ClrFacade.GetDefaultEncoding();
|
||||
|
||||
if (bytesRead > 3)
|
||||
{
|
||||
preamble = string.Join("-", initialBytes[0], initialBytes[1], initialBytes[2], initialBytes[3]);
|
||||
|
||||
if (encodingMap.TryGetValue(preamble, out foundEncoding))
|
||||
{
|
||||
return foundEncoding;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for three-byte preambles
|
||||
if (bytesRead > 2)
|
||||
{
|
||||
preamble = string.Join("-", initialBytes[0], initialBytes[1], initialBytes[2]);
|
||||
if (encodingMap.TryGetValue(preamble, out foundEncoding))
|
||||
{
|
||||
return foundEncoding;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for two-byte preambles
|
||||
if (bytesRead > 1)
|
||||
{
|
||||
preamble = string.Join("-", initialBytes[0], initialBytes[1]);
|
||||
if (encodingMap.TryGetValue(preamble, out foundEncoding))
|
||||
{
|
||||
return foundEncoding;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for binary
|
||||
string initialBytesAsAscii = System.Text.Encoding.ASCII.GetString(initialBytes, 0, bytesRead);
|
||||
if (initialBytesAsAscii.IndexOfAny(nonPrintableCharacters) >= 0)
|
||||
{
|
||||
return Encoding.Unicode;
|
||||
}
|
||||
|
||||
return utf8NoBom;
|
||||
}
|
||||
|
||||
// BigEndianUTF32 encoding is possible, but requires creation
|
||||
internal static readonly Encoding BigEndianUTF32Encoding = new UTF32Encoding(bigEndian: true, byteOrderMark: true);
|
||||
// [System.Text.Encoding]::GetEncodings() | Where-Object { $_.GetEncoding().GetPreamble() } |
|
||||
// Add-Member ScriptProperty Preamble { $this.GetEncoding().GetPreamble() -join "-" } -PassThru |
|
||||
// Format-Table -Auto
|
||||
internal static readonly Dictionary<string, Encoding> encodingMap =
|
||||
new Dictionary<string, Encoding>()
|
||||
{
|
||||
{ "255-254", Encoding.Unicode },
|
||||
{ "254-255", Encoding.BigEndianUnicode },
|
||||
{ "255-254-0-0", Encoding.UTF32 },
|
||||
{ "0-0-254-255", BigEndianUTF32Encoding },
|
||||
{ "239-187-191", Encoding.UTF8 },
|
||||
};
|
||||
|
||||
internal static readonly char[] nonPrintableCharacters = {
|
||||
(char) 0, (char) 1, (char) 2, (char) 3, (char) 4, (char) 5, (char) 6, (char) 7, (char) 8,
|
||||
(char) 11, (char) 12, (char) 14, (char) 15, (char) 16, (char) 17, (char) 18, (char) 19, (char) 20,
|
||||
(char) 21, (char) 22, (char) 23, (char) 24, (char) 25, (char) 26, (char) 28, (char) 29, (char) 30,
|
||||
(char) 31, (char) 127, (char) 129, (char) 141, (char) 143, (char) 144, (char) 157 };
|
||||
|
||||
internal static readonly UTF8Encoding utf8NoBom =
|
||||
new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
|
||||
|
|
|
@ -1071,22 +1071,7 @@ namespace System.Management.Automation.Host
|
|||
/// <summary>
|
||||
/// The path that this transcript is being logged to.
|
||||
/// </summary>
|
||||
internal string Path
|
||||
{
|
||||
get
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_path = value;
|
||||
// Get the encoding from the file, or default (UTF8-NoBom)
|
||||
Encoding = Utils.GetEncoding(value);
|
||||
}
|
||||
}
|
||||
|
||||
private string _path;
|
||||
internal string Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Any output to log for this transcript.
|
||||
|
@ -1104,12 +1089,6 @@ namespace System.Management.Automation.Host
|
|||
/// </summary>
|
||||
internal bool IncludeInvocationHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The encoding of this transcript, so that appending to it
|
||||
/// can be done correctly.
|
||||
/// </summary>
|
||||
internal Encoding Encoding { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logs buffered content to disk. We use this instead of File.AppendAllLines
|
||||
/// so that we don't need to pay seek penalties all the time, and so that we
|
||||
|
@ -1117,6 +1096,13 @@ namespace System.Management.Automation.Host
|
|||
/// </summary>
|
||||
internal void FlushContentToDisk()
|
||||
{
|
||||
static Encoding GetPathEncoding(string path)
|
||||
{
|
||||
using StreamReader reader = new StreamReader(path, Utils.utf8NoBom, detectEncodingFromByteOrderMarks: true);
|
||||
_ = reader.Read();
|
||||
return reader.CurrentEncoding;
|
||||
}
|
||||
|
||||
lock (OutputBeingLogged)
|
||||
{
|
||||
if (!_disposed)
|
||||
|
@ -1125,11 +1111,13 @@ namespace System.Management.Automation.Host
|
|||
{
|
||||
try
|
||||
{
|
||||
var currentEncoding = GetPathEncoding(this.Path);
|
||||
|
||||
// Try to first open the file with permissions that will allow us to read from it
|
||||
// later.
|
||||
_contentWriter = new StreamWriter(
|
||||
new FileStream(this.Path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read),
|
||||
this.Encoding);
|
||||
currentEncoding);
|
||||
_contentWriter.BaseStream.Seek(0, SeekOrigin.End);
|
||||
}
|
||||
catch (IOException)
|
||||
|
@ -1138,7 +1126,7 @@ namespace System.Management.Automation.Host
|
|||
// file permissions.
|
||||
_contentWriter = new StreamWriter(
|
||||
new FileStream(this.Path, FileMode.Append, FileAccess.Write, FileShare.Read),
|
||||
this.Encoding);
|
||||
Utils.utf8NoBom);
|
||||
}
|
||||
|
||||
_contentWriter.AutoFlush = true;
|
||||
|
|
Loading…
Reference in a new issue