PowerShell Core не распознает юникод

Ваш код не создает обратное, потому что противоположное означает, что у вас есть пробелы, но с правой стороны. Правая сторона вашего вывода просто пуста, заставляя вас думать, что у вас есть обратное. Вам нужно включить пробелы, чтобы сформировать нужную форму.

Попробуйте следующее:

public class Test{
    public static void main (String [] args){
        for(int line = 1; line <= 5; line++){
            //i decreases with every loop since number of spaces
            //is decreasing
            for(int i =-1*line +5; i>=1; i--){
                System.out.print(" ");
            }
            //j increases with every loop since number of numbers
            //is decreasing
            for(int j = 1; j <= line; j++){
                System.out.print(line);
            }
            //End of loop, start a new line
            System.out.println();
        }
    }
}

Вы правильно подошли к проблеме, начав с количества строк. Затем вы должны установить связь между количеством строк (первый для цикла) и внутренними циклами. Когда вы хотите это сделать, помните эту формулу:

Скорость изменения * line + X = количество элементов в строке

Вы вычисляете скорость изменения, видя, как изменяется количество элементов после каждой строки. Например, на первой строке у вас есть 4 пробела, во второй строке - 3 пробела. Вы делаете 3 - 4 = -1, другими словами, с каждой строкой, на которую вы переходите, количество пробелов уменьшается на 1. Теперь выберите строку, скажем, вторую строку. Используя формулу, вы получите

-1 (скорость изменения) * 2 (строка) + X = 3 (сколько пробелов у вас на выбранной линии).

Вы получаете X = 5, и там у вас есть формула, которую вы можете использовать в своем коде, как вы можете видеть в строке 4 в цикле for.

for (int i = -1 * line +5; i> = 1; i -)

Вы делаете то же самое для количества чисел в каждой строке, но поскольку скорость изменения равна 1, то есть с каждой строкой количество чисел увеличивается на 1, X будет равно 0, так как число элементов равно числу строк.

for (int j = 1; j & lt; = line; j ++) {

1
задан Ansgar Wiechers 16 January 2019 в 11:45
поделиться

2 ответа

Windows использует специфичную для Windows кодировку символов cp1252. Чтобы использовать символы Юникода, необходимо выполнить эту команду до того, как вы впервые захотите что-то сделать с этим файлом:

chcp 65001 | Out-Null  # set codepage to UTF-8
$Message = [System.IO.File]::ReadAllText("$PSScriptRoot\русский.txt")

или

chcp 65001 | Out-Null  # set codepage to UTF-8
$Message = Get-Content "$PSScriptRoot\русский.txt"

Надеюсь, что это поможет

0
ответ дан Theo 16 January 2019 в 11:45
поделиться

Файлы не содержат символов, они содержат байты. Чтобы получить символы из байтов, вам нужно применить некоторую кодировку. Если вы применяете разные кодировки к одним и тем же байтам, вы можете получить разные символы в результатах.

Взяв в качестве примера вашу строку байтов:

PS> $ByteArray = [Byte[]]('24-4D-65-73-73-61-67-65-20-3D-20-5B-49-4F-2E-46-69-6C-65-5D-3A-3A-52-65-61-64-41-6C-6C-54-65-78-74-28-22-24-50-53-53-63-72-69-70-74-52-6F-6F-74-5C-F0-F3-F1-F1-EA-E8-E9-2E-74-78-74-22-2C-20-5B-53-79-73-74-65-6D-2E-54-65-78-74-2E-45-6E-63-6F-64-69-6E-67-5D-3A-3A-44-65-66-61-75-6C-74-29-0D-0A-24-4D-65-73-73-61-67-65' -split '-' | % { [Byte]::Parse(

Файлы не содержат символов, они содержат байты. Чтобы получить символы из байтов, вам нужно применить некоторую кодировку. Если вы применяете разные кодировки к одним и тем же байтам, вы можете получить разные символы в результатах.

Взяв в качестве примера вашу строку байтов:

[110]

Важно использовать правильную кодировку при чтении файлов. И еще одна важная вещь: ваш файл скрипта использует кодовую страницу 1251, а не UTF-8. Также обратите внимание, что последовательность байтов F0-F3-F1-F1-EA-E8-E9 (которая представляет мир русский в кодовой странице 1251) является недопустимой последовательностью байтов в соответствии с UTF-8, поэтому вместо этого вы получаете семь заменяющих символов (U+FFFD).

Поскольку PowerShell Core по умолчанию использует UTF-8, а в вашем файле сценария нет спецификации для указания иного (хотя нет спецификации, которая позволяет PowerShell распознавать кодовую страницу 1251), PowerShell Core читает ваш файл с использованием кодировки UTF-8, таким образом, он пытается получить доступ к �������.txt (которого у вас нет) вместо русский.txt.

Вы можете легко наблюдать это сами, если измените сценарий на запись файла вместо чтения.

PS> $ByteArray2 = [Byte[]](91, 73, 79, 46, 70, 105, 108, 101, 93, 58, 58, 87, 114, 105, 116, 101, 65, 108, 108, 84, 101, 120, 116, 40, 34, 36, 80, 83, 83, 99, 114, 105, 112, 116, 82, 111, 111, 116, 92, 240, 243, 241, 241, 234, 232, 233, 46, 116, 120, 116, 34, 44, 32, 91, 68, 97, 116, 101, 84, 105, 109, 101, 93, 58, 58, 85, 116, 99, 78, 111, 119, 41)
PS> # Representing `[IO.File]::WriteAllText("$PSScriptRoot\русский.txt", [DateTime]::UtcNow)` in codepage 1251
PS> [IO.File]::WriteAllBytes("$(Convert-Path .)\write.ps1", $ByteArray2)
PS> .\write.ps1

Теперь вы можете прочитать файл обратно с вашим оригинальным скриптом:

PS> [IO.File]::WriteAllBytes("$(Convert-Path .)\asd.ps1", $ByteArray)
PS> .\asd.ps1
01/18/2019 17:13:15

Вызов обоих скриптов с помощью PowerShell Core:

PS> pwsh -Command ".\write.ps1; .\asd.ps1"
01/18/2019 17:21:02

Как видите, ваш скрипт успешно выполнен в PowerShell Core. Если вы просматриваете текущий каталог, то можете увидеть, что в нем есть и русский.txt, и �������.txt, и их содержимое совпадает с тем, что было напечатано на консоли.

На самом деле проблема не в том, чтобы делать чтение / запись файлов (кроме самого файла скрипта). Это можно продемонстрировать с помощью простого скрипта, который просто печатает коды символов строкового литерала:

PS> $ByteArray3 = [Byte[]](40, 39, 240, 243, 241, 241, 234, 232, 233, 39, 46, 71, 101, 116, 69, 110, 117, 109, 101, 114, 97, 116, 111, 114, 40, 41, 32, 124, 32, 37, 32, 84, 111, 73, 110, 116, 51, 50, 32, 36, 110, 117, 108, 108, 32, 124, 32, 37, 32, 84, 111, 83, 116, 114, 105, 110, 103, 32, 88, 52, 41, 32, 45, 106, 111, 105, 110, 32, 39, 45, 39)
PS> # Representing `('русский'.GetEnumerator() | % ToInt32 $null | % ToString X4) -join '-'` in codepage 1251
PS> [IO.File]::WriteAllBytes("$(Convert-Path .)\test.ps1", $ByteArray3)

Вызов его в Windows PowerShell даст один результат:

PS> .\test.ps1
0440-0443-0441-0441-043A-0438-0439

В то время как PowerShell Core даст другой:

PS> pwsh -Command ".\test.ps1"
FFFD-FFFD-FFFD-FFFD-FFFD-FFFD-FFFD

Одним из способов решения этой проблемы является использование UTF-8 с спецификацией, которая гарантирует, что и Windows PowerShell, и PowerShell Core будут использовать одну и ту же кодировку при чтении файлов сценариев.

Ответ написан с допущением, что [Text.Encoding]::Default.CodePage вернет 1251, как это выглядит для ОП.

, 'HexNumber') }) PS> [Text.Encoding]::UTF8.GetString($ByteArray) $Message = [IO.File]::ReadAllText("$PSScriptRoot\�������.txt", [System.Text.Encoding]::Default) $Message PS> [Text.Encoding]::GetEncoding(1251).GetString($ByteArray) $Message = [IO.File]::ReadAllText("$PSScriptRoot\русский.txt", [System.Text.Encoding]::Default) $Message PS> [Text.Encoding]::GetEncoding(1252).GetString($ByteArray) $Message = [IO.File]::ReadAllText("$PSScriptRoot\ðóññêèé.txt", [System.Text.Encoding]::Default) $Message

Важно использовать правильную кодировку при чтении файлов. И еще одна важная вещь: ваш файл скрипта использует кодовую страницу 1251, а не UTF-8. Также обратите внимание, что последовательность байтов F0-F3-F1-F1-EA-E8-E9 (которая представляет мир русский в кодовой странице 1251) является недопустимой последовательностью байтов в соответствии с UTF-8, поэтому вместо этого вы получаете семь заменяющих символов (U+FFFD).

Поскольку PowerShell Core по умолчанию использует UTF-8, а в вашем файле сценария нет спецификации для указания иного (хотя нет спецификации, которая позволяет PowerShell распознавать кодовую страницу 1251), PowerShell Core читает ваш файл с использованием кодировки UTF-8, таким образом, он пытается получить доступ к �������.txt (которого у вас нет) вместо русский.txt.

Вы можете легко наблюдать это сами, если измените сценарий на запись файла вместо чтения.

PS> $ByteArray2 = [Byte[]](91, 73, 79, 46, 70, 105, 108, 101, 93, 58, 58, 87, 114, 105, 116, 101, 65, 108, 108, 84, 101, 120, 116, 40, 34, 36, 80, 83, 83, 99, 114, 105, 112, 116, 82, 111, 111, 116, 92, 240, 243, 241, 241, 234, 232, 233, 46, 116, 120, 116, 34, 44, 32, 91, 68, 97, 116, 101, 84, 105, 109, 101, 93, 58, 58, 85, 116, 99, 78, 111, 119, 41)
PS> # Representing `[IO.File]::WriteAllText("$PSScriptRoot\русский.txt", [DateTime]::UtcNow)` in codepage 1251
PS> [IO.File]::WriteAllBytes("$(Convert-Path .)\write.ps1", $ByteArray2)
PS> .\write.ps1

Теперь вы можете прочитать файл обратно с вашим оригинальным скриптом:

PS> [IO.File]::WriteAllBytes("$(Convert-Path .)\asd.ps1", $ByteArray)
PS> .\asd.ps1
01/18/2019 17:13:15

Вызов обоих скриптов с помощью PowerShell Core:

PS> pwsh -Command ".\write.ps1; .\asd.ps1"
01/18/2019 17:21:02

Как видите, ваш скрипт успешно выполнен в PowerShell Core. Если вы просматриваете текущий каталог, то можете увидеть, что в нем есть и русский.txt, и �������.txt, и их содержимое совпадает с тем, что было напечатано на консоли.

На самом деле проблема не в том, чтобы делать чтение / запись файлов (кроме самого файла скрипта). Это можно продемонстрировать с помощью простого скрипта, который просто печатает коды символов строкового литерала:

PS> $ByteArray3 = [Byte[]](40, 39, 240, 243, 241, 241, 234, 232, 233, 39, 46, 71, 101, 116, 69, 110, 117, 109, 101, 114, 97, 116, 111, 114, 40, 41, 32, 124, 32, 37, 32, 84, 111, 73, 110, 116, 51, 50, 32, 36, 110, 117, 108, 108, 32, 124, 32, 37, 32, 84, 111, 83, 116, 114, 105, 110, 103, 32, 88, 52, 41, 32, 45, 106, 111, 105, 110, 32, 39, 45, 39)
PS> # Representing `('русский'.GetEnumerator() | % ToInt32 $null | % ToString X4) -join '-'` in codepage 1251
PS> [IO.File]::WriteAllBytes("$(Convert-Path .)\test.ps1", $ByteArray3)

Вызов его в Windows PowerShell даст один результат:

PS> .\test.ps1
0440-0443-0441-0441-043A-0438-0439

В то время как PowerShell Core даст другой:

PS> pwsh -Command ".\test.ps1"
FFFD-FFFD-FFFD-FFFD-FFFD-FFFD-FFFD

Одним из способов решения этой проблемы является использование UTF-8 с спецификацией, которая гарантирует, что и Windows PowerShell, и PowerShell Core будут использовать одну и ту же кодировку при чтении файлов сценариев.

Ответ написан с допущением, что [Text.Encoding]::Default.CodePage вернет 1251, как это выглядит для ОП.

0
ответ дан PetSerAl 16 January 2019 в 11:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: