Home Delphi Console Application increase input character limit
Reply: 2

Delphi Console Application increase input character limit

Dangas56
1#
Dangas56 Published in 2018-02-13 23:43:13Z

Is it possible to increase the amount of characters that the console app accepts for readln.
It seems to only allow you to type 254 characters

To Reproduce in Delphi

File > New > Other > Console Application

change the code to be as per below

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.

Paste this string in the running app ( its a 300 character string )

ABCDEFHIL1ABCDEFHIL2ABCDEFHIL3ABCDEFHIL4ABCDEFHIL5ABCDEFHIL6ABCDEFHIL7ABCDEFHIL8ABCDEFHIL9ABCDEFHI10ABCDEFHI11ABCDEFHI12ABCDEFHI13ABCDEFHI14ABCDEFHI15ABCDEFHI16ABCDEFHI17ABCDEFHI18ABCDEFHI19ABCDEFHI20ABCDEFHI21ABCDEFHI22ABCDEFHI23ABCDEFHI24ABCDEFHI25ABCDEFHI26ABCDEFHI27ABCDEFHI28ABCDEFHI29ABCDEFHI30

For me it chops the string off at 254 characters

ABCDEFHIL1ABCDEFHIL2ABCDEFHIL3ABCDEFHIL4ABCDEFHIL5ABCDEFHIL6ABCDEFHIL7ABCDEFHIL8ABCDEFHIL9ABCDEFHI10ABCDEFHI11ABCDEFHI12ABCDEFHI13ABCDEFHI14ABCDEFHI15ABCDEFHI16ABCDEFHI17ABCDEFHI18ABCDEFHI19ABCDEFHI20ABCDEFHI21ABCDEFHI22ABCDEFHI23ABCDEFHI24ABCDEFHI25ABCD

Remy Lebeau
2#
Remy Lebeau Reply to 2018-02-14 01:23:06Z

AFAIK, you can't make the RTL's Readln() function accept more characters (though internally, it is coded to run a loop that should be able to handle more than 254 characters). It seems by default, when you paste your 300-char test string into the console window, it stops taking characters at 254 even before you press Enter.

But, you can use a different approach - call GetStdHandle(STD_INPUT_HANDLE) and then call ReadFile() on that HANDLE to read however much you want. If you use a buffer that is at least 300 bytes, it will happily accept your 300-char test string:

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.

You can then let the RTL handle that buffering for you, by wrapping the HANDLE in a THandleStream and TStreamReader (the latter lets you specify a buffer size - it defaults to 1024 bytes), eg:

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.
Sertac Akyuz
3#
Sertac Akyuz Reply to 2018-02-15 20:17:36Z

The RTL is flexible enough to override file device driver defaults. It even allows you to write your own driver, but for your needs all you need to do is to provide a buffer sufficient enough to hold your input.

Without any file parameter Readln uses the global Input so that's what you're going to modify:

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.
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.327964 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO