Приложение Delphi Console увеличивает лимит ввода символов

Можно ли увеличить количество символов, которые консольное приложение принимает для readln.

Кажется, вы только набираете 254 символа

Воспроизведение в Delphi

Файл> Создать> Другое> Консольное приложение

измените код, как указано ниже

program Project3;

{$APPTYPE CONSOLE} 

{$R *.res}

uses
  System.SysUtils;

var MyTest : String;
begin
  try
    readln(MyTest);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Вставьте эту строку в запущенное приложение (его 300-символьная строка)

ABCDEFHIL1ABCDEFHIL2ABCDEFHIL3ABCDEFHIL4ABCDEFHIL5ABCDEFHIL6ABCDEFHIL7ABCDEFHIL8ABCDEFHIL9ABCDEFHI10ABCDEFHI11ABCDEFHI12ABCDEFHI13ABCDEFHI14ABCDEFHI15ABCDEFHI16ABCDEFHI17ABCDEFHI18ABCDEFHI19ABCDEFHI20ABCDEFHI21ABCDEFHI22ABCDEFHI23ABCDEFHI24ABCDEFHI25ABCDEFHI26ABCDEFHI27ABCDEFHI28ABCDEFHI29ABCDEFHI30

Для меня это прерывает строку с 254 символами

ABCDEFHIL1ABCDEFHIL2ABCDEFHIL3ABCDEFHIL4ABCDEFHIL5ABCDEFHIL6ABCDEFHIL7ABCDEFHIL8ABCDEFHIL9ABCDEFHI10ABCDEFHI11ABCDEFHI12ABCDEFHI13ABCDEFHI14ABCDEFHI15ABCDEFHI16ABCDEFHI17ABCDEFHI18ABCDEFHI19ABCDEFHI20ABCDEFHI21ABCDEFHI22ABCDEFHI23ABCDEFHI24ABCDEFHI25ABCD

enter image description here

Ответ 1

AFAIK, вы не можете заставить Readln() RTL Readln() принимать больше символов (хотя и внутренне, она закодирована для запуска цикла, который должен иметь возможность обрабатывать более 254 символов). По умолчанию, когда вы вставляете тестовую строку 300-char в консольное окно, она перестает принимать символы на 254 даже до нажатия Enter.

Но вы можете использовать другой подход - вызовите GetStdHandle(STD_INPUT_HANDLE) а затем вызовите ReadFile() в этой HANDLE чтобы прочитать, сколько вы хотите. Если вы используете буфер размером не менее 300 байт, он с радостью примет тестовую строку с 300 символами:

program Project3;

{$APPTYPE CONSOLE} 

{$R *.res}

uses
  System.SysUtils, Winapi.Windows;

var
  buf : array[0..299] of AnsiChar;
  MyTest: AnsiString;//string;
  hStdIn: THandle;
  dwNumRead: DWORD;
begin
  try
    //Readln(MyTest);
    hStdIn := GetStdHandle(STD_INPUT_HANDLE);
    ReadFile(hStdIn, buf, sizeof(buf), dwNumRead, nil);
    SetString(MyTest, buf, dwNumRead);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Затем вы можете позволить RTL обрабатывать эту буферизацию для вас, обернув HANDLE в THandleStream и TStreamReader (последний позволяет указать размер буфера - по умолчанию - 1024 байта), например:

program Project3;

{$APPTYPE CONSOLE} 

{$R *.res}

uses
  System.SysUtils, Winapi.Windows, System.Classes;

var
  MyTest : String;
  strm: THandleStream;
  reader: TStreamReader;
begin
  try
    //Readln(MyTest);
    strm := THandleStream.Create(GetStdHandle(STD_INPUT_HANDLE));
    try
      reader := TStreamReader.Create(strm);
      try
        MyTest := reader.ReadLine;
      finally
        reader.Free;
      end;
    finally
      strm.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Ответ 2

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

Без какого-либо параметра file Readln использует глобальный Input так, чтобы то, что вы собираетесь изменить:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

var MyTest : String;
    Buff: array[0..511] of Char;
begin
  try
    TTextRec(Input).BufSize := SizeOf(Buff);
    TTextRec(Input).BufPtr := @Buff;
    ReadLn(MyTest);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.