Почему я могу прочитать более 254 символов с помощью Console.ReadLine, если в документах указано, что я не должен этого делать? - PullRequest
2 голосов
/ 07 февраля 2020

документы для Console.ReadLine говорят:

По умолчанию метод считывает ввод из 256-символьного входного буфера. Поскольку это включает символ (ы) Environment.NewLine, метод может читать строки, содержащие до 254 символов. Чтобы читать более длинные строки, вызовите метод OpenStandardInput (Int32).

Тем не менее, я могу читать больше, чем столько символов, просто отлично. Запуск простой программы, такой как:

string s = Console.ReadLine();
Console.WriteLine(s);
Console.WriteLine(s.Length);

Console.ReadKey();

с вводом, подобным:

aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjj

, возвращает тот же ввод с длиной 500.

Пример запуска здесь .

Устаревшие тогда документы или слова "по умолчанию" здесь?


Обновление: Джереми нашел ограничение в 4096 определено в исходном коде .

Я проверил, что. NET Базовое приложение будет читать только первые 4094 символа из стандартного ввода (исключая переводы строки).

В моем случае у меня фактически есть процесс. NET Core 3.1, который запускает процесс. NET Framework 4.6, перенаправляя его StandardOut и StandardIn. Я убедился, что процесс. NET Framework может успешно прочитать 1 миллиард символов через Console.ReadLine(), где процесс. NET Core 3.1 отправляет материал процесса Framework через fwProcess.StandardInput.WriteLine(Serialize(<some stuff>));

Это также работает, когда . NET Процесс платформы заменен на. NET Процесс ядра.

Таким образом, кажется, что ограничение в 256 символов не применяется при перенаправлении stdout / stdin, но если кто-то может выкопать окончательный Доказательства / документы, объясняющие это, я был бы признателен. Если все еще существует ограничение (исключая случай OutOfMemory), но оно составляет 1,1 миллиарда символов, я хотел бы знать. Я также хотел бы знать, зависит ли это от платформы (у меня Windows 10).

Если это поможет, это код, который я запускаю.

ConsoleApp1 :

ProcessStartInfo processInfo = new ProcessStartInfo {
    CreateNoWindow = true,
    FileName = "ConsoleApp2.exe",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardInput = true
};

StringBuilder s = new StringBuilder();
var proc = Process.Start(processInfo);

int n = 1_000_000_000;
for (int i = 0; i < n; i++)
    s.Append("a");

proc.StandardInput.WriteLine(s.ToString());
string s = proc.StandardOutput.ReadLine();
Console.WriteLine(s.Length == n); // logs True

Console.ReadKey();

ConsoleApp2:

string s = Console.ReadLine();
Console.WriteLine(s);

1 Ответ

2 голосов
/ 07 февраля 2020

Перефразируя от здесь :

Режим консоли cmd по умолчанию - "ENABLE_LINE_INPUT", что означает, что когда код выдает вызов :: ReadFile для stdin, :: ReadFile не делает не возвращайтесь к звонящему, пока он не встретит возврат каретки. Но вызов ReadFile имеет только ограниченный размер буфера, который был передан ему. Это означает, что cmd смотрит на размер предоставленного ему буфера и определяет на основании того, сколько символов может быть длина строки ... если бы строка была длиннее, он не смог бы сохранить все данные в буфере.

Размер буфера по умолчанию, используемый при открытии Console.In, теперь равен 4096 ( source )

Документация с открытым исходным кодом, доступна здесь , если вы хотите отправить запрос на выпуск или запрос.

При перенаправлении StandardOut / StandardIn это ограничение не применяется. Начиная с здесь :

Ограничение на количество памяти, которое вы передаете.

...