Как изменить сценарий Powershell, чтобы он записывал файлы в кодировке ANSI - Windows-1252? - PullRequest
2 голосов
/ 20 марта 2019

У меня есть сценарий банковского приложения, который генерирует «отфильтрованный» выходной файл, удаляя записи об ошибках из файла ежедневного входного банка (см. Как создать сценарий Windows Server для удаления записей об ошибках И предыдущую запись вкаждый из файла с результатами, записанными в НОВЫЙ файл ).«Отфильтрованный» выходной файл будет отправлен государству для обновления их системы.В качестве примечания: исходные входные файлы, которые мы получаем из банка, отображаются в моем редакторе файлов (UltraEdit) как Unix 1252 (ANSI Latin 1), и каждая запись заканчивается только переводом строки.

Я отправилпара тестовых выходных файлов, сгенерированных как из «чистых» (без ошибок), так и из «грязных» (содержавших 4 ошибки) входных файлов в State для проверки их завершения, чтобы убедиться, что все было хорошо до реализации, но это немного беспокоило, потому чтовыходные файлы были сгенерированы в кодировке UTF-16 с окончаниями строк CRLF, где входной и текущий нефильтрованный выходные данные кодируются в Windows-1252.Все остальные выходные файлы в этой системе закодированы в Windows-1252.

Конечно же ... Я получил сообщение, что кодировка системы штата неправильная.Их комментарии были следующими: «Файл был закодирован в формате UCS-2 Little Endian, и его необходимо было преобразовать в ANSI для запуска в нашей системе.Это было неожиданно.

После этого файл без подробных транзакций будет работать через нашу программу отклонения EFT.

Кажется, что все было обработано нормально, но нам пришлось сделать какое-то преобразование.Может ли оно быть отправлено в ANSI или должно быть выполнено в UCS 2 Little Endian? »

Я безуспешно пытался добавить –Кодировку« Windows-1252 »и –Кодировку windows-1252 в свой оператор out-file, с помощьюоба возвращают сообщение: Out-File: Невозможно проверить аргумент в параметре 'Кодировка'.Аргумент «Windows-1252» не принадлежит набору «unknown, string, unicode, bigendianunicode, utf8, utf7, utf32, ascii, default, oem», указанному атрибутом ValidateSet.Укажите аргумент в наборе, а затем повторите команду.В C: \ EZTRIEVE \ PwrShell \ TEST2_FilterR02.ps1: 47 char: 57 + ... OutputStrings |Out-File $ OutputFileFiltered -Кодирование "Windows-1252" + ~~~~~~~~~~~~~~ + CategoryInfo: InvalidData: (:) [Out-File], ParameterBindingVal idationException + FullyQualifiedErrorId: ParameterArgumentValidationError, Microsoft.Power Shell.Commands.OutFileCommand

Я искал какую-то помощь в этом в течение нескольких дней, но на самом деле ничего не ясно, и подавляющее большинство из того, что я нашел, касалось преобразования из Windows-1252 в другое.кодирование.Вчера я нашел комментарий где-то о stackoverflow, что «ANSI» совпадает с Windows-1252, но до сих пор я не нашел ничего, что показывало бы, как правильно добавить опцию кодирования Windows-1252 к моему выражению out-file,Powershell примет это.Мне действительно нужно закончить этот проект, чтобы я мог заняться следующими, которые были добавлены в мою очередь.Возможно, мне не хватает какого-то подпараметра, который нужно добавить к –Encoding?

Это тестируется в среде Dollar Universe (планировщик заданий) на новом сервере резервного копирования, работающем под управлением Windows Server 2016 Standard с Powershell 5.1.Наша производственная система работает под управлением Dollar Universe на Windows Server 2012 R2, также с Powershell 5.1 (да, мы ищем достаточное окно для обновления: -)

С моей последней попытки мой сценарий Powershell:

 [cmdletbinding()]
 Param
 (
     [string] $InputFilePath
 )   

 # Read the text file
 $InputFile = Get-Content $InputFilePath

# Initialize output record counter
$Inrecs = 0
$Outrecs = 0

# Get the time
$Time = Get-Date -Format "MM_dd_yy"

# Set up the output file name
$OutputFileFiltered = "C:\EZTRIEVE\CFIS\DATA\TEST_CFI_EFT_RETURN_FILTERED"

# Initialize the variable used to hold the output
$OutputStrings = @()

# Loop through each line in the file
# Check the line ahead for "R02" and add it to the output
# or skip it appropriately
for ($i = 0; $i -lt $InputFile.Length - 1; $i++)
{
    if ($InputFile[$i + 1] -notmatch "R02")
    {
        # The next record does not contain "R02", increment count and add it to the output
        $Outrecs++
        $OutputStrings += $InputFile[$i]
    }
    else
    {
        # The next record does contain "R02", skip it
        $i++
    }
}

# Add the trailer record to the output
$OutputString += $InputFile[$InputFile.Length - 1]

# Write the output to a file
# $OutputStrings | Out-File $OutputFileFiltered
$OutputStrings | Out-File $OutputFileFiltered -Encoding windows-1252

# Display record processing stats:

$Filtered = $Outrecs-$i

Write-Host $i  Input records processed

Write-Host $Filtered  Error records filtered out

Write-Host $Outrecs  Output records written

1 Ответ

3 голосов
/ 20 марта 2019

Примечание:

  • Позже вы пояснили, что вам нужны переводы строк LF (в стиле Unix) - см. Нижний раздел.

  • В следующем разделе рассматривается вопрос, который был задан изначально, и представлены решения, которые приводят к появлению файлов с символами новой строки CRLF (в стиле Windows) (при запуске в Windows).


Если язык вашей системы Язык для программ, не поддерживающих Юникод настройка (или системный языковой стандарт ) имеет Windows-1252 в качестве активной кодовой страницы ANSI (например, в системах на американском и английском языках или в странах Западной Европы), использовать -Encoding Default, поскольку Default относится к эта кодовая страница в Windows PowerShell (но , а не в PowerShell Core , которая по умолчанию использует UTF-8 без спецификации и не поддерживает идентификатор кодировки Default).

Проверьте с помощью: [cultureinfo]::CurrentCulture.TextInfo.ANSICodePage -eq 1252

... | Out-File -Encoding Default $file

Примечание:

  • Если , вы уверены, что ваши данные на самом деле состоят исключительно из символов диапазона ASCII (символов с кодовыми точками в 7-битном диапазоне, за исключением символов с акцентом, таких как ü) -Encoding Default будет работать, даже если в вашей системной локали используется кодовая страница ANSI , отличная от , чем Windows-1252, учитывая, что все (однобайтовые) кодовые страницы ANSI совместно используют все символы ASCII в их 7-битном поддиапазоне; затем вы также можете использовать -Encoding ASCII, но учтите, что если в конце концов присутствуют не-ASCII символы, они будут транслитерированы в литерал ? символов, что приведет к потере информации.

  • Командлет Set-Content на самом деле по умолчанию - кодировка Default в Windows PowerShell (но не PowerShell Core , где по умолчанию используется UTF-8 без спецификации). ).

  • Несмотря на то, что строковое поведение Set-Content отличается от Out-File - , посмотрите этот ответ - на самом деле это лучший выбор, если объекты для записи в файл уже строк.


В противном случае , у вас есть два варианта:

  • Используйте функции ввода-вывода файлов .NET Framework напрямую , где вы можете использовать любую кодировку, поддерживаемую .NET; e.g.:

    $lines = ...  # array of strings (to become lines in a file)
    # CAVEAT: Be sure to specify an *absolute file path* in $file,
    #         because .NET typically has a different working dir.
    [IO.File]::WriteAllLines($file, $lines, [Text.Encoding]::GetEncoding(1252))
    
  • Используйте PowerShell Core , что позволяет передавать любую поддерживаемую кодировку .NET в параметр
    -Encoding:

    ... | Out-File -Encoding ([Text.Encoding]::GetEncoding(1252)) $file
    

Обратите внимание, что в PSv5.1 + вы можете изменить кодировку, используемую операторами > и >> , как подробно описано в этого ответа .
Однако в Windows PowerShell вы снова ограничены кодировками, поддерживаемыми параметром Out-File -Encoding.


Создание текстовых файлов с символами новой строки LF (в стиле Unix) в Windows:

PowerShell (неизменно) и .NET (по умолчанию) используют подходящую для платформы последовательность новой строки - как это отражено в [Environment]::NewLine - при записи строк в виде строк в файл. Другими словами: в Windows вы получите файлы с символами новой строки CRLF, а на Unix-подобных платформах (PowerShell Core) - с символами новой строки LF.

Обратите внимание, что приведенные ниже решения предполагают, что данные для записи в ваш файл представляют собой массив строк , представляющих строки для записи, например, возвращаемые Get-Content (где результирующие элементы массива строки входного файла без завершающей последовательности новой строки).

Чтобы явно создать файл с символами новой строки LF в Windows ( PSv5 + ):

$lines = ...  # array of strings (to become lines in a file)

($lines -join "`n") + "`n" | Set-Content -NoNewline $file

"`n" производит символ НЧ.

Примечание:

  • В Windows PowerShell неявно используется кодировка активной кодовой страницы ANSI.

  • В PowerShell Core это неявно создает файл UTF-8 без спецификации. Если вы хотите использовать вместо этого активную кодовую страницу ANSI, используйте:

    -Encoding ([Text.Encoding]::GetEncoding([cultureinfo]::CurrentCulture.TextInfo.ANSICodePage))
    

В PSv4- (PowerShell версии 4 или ниже) вам придется использовать .NET Framework напрямую:

$lines = ...  # array of strings (to become lines in a file)


# CAVEAT: Be sure to specify an *absolute file path* in $file,
#         because .NET typically has a different working dir.
[IO.File]::WriteAllText($file, ($lines -join "`n") + "`n")

Примечание:

  • В Windows PowerShell и PowerShell Core создается файл UTF-8 без спецификации.

  • Если вы хотите использовать вместо этого активную кодовую страницу ANSI, передайте [Text.Encoding]::GetEncoding([cultureinfo]::CurrentCulture.TextInfo.ANSICodePage) в качестве дополнительного аргумента для WriteAllText().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...