Delphi控制台应用程序增加输入字符限制

时间:2018-02-13 23:43:13

标签: delphi console-application

是否可以增加控制台应用程序为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

2 个答案:

答案 0 :(得分:18)

AFAIK,你不能让RTL的Readln()函数接受更多字符(虽然在内部,它被编码为运行一个应该能够处理超过254个字符的循环)。默认情况下,当您将300-char测试字符串粘贴到控制台窗口时,即使在按 Enter 之前,它也会停止在254处获取字符。

但是,您可以使用其他方法 - 拨打GetStdHandle(STD_INPUT_HANDLE),然后在ReadFile()上调用HANDLE,以便阅读您想要的内容。如果您使用至少300字节的缓冲区,它将很乐意接受您的300-char测试字符串:

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包裹在THandleStreamTStreamReader中来处理缓冲(后者允许您指定缓冲区大小 - 默认为1024 bytes),例如:

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.

答案 1 :(得分:9)

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.