Problems with UTF8 text in XE7 ReadLn command

1.1k views Asked by At

I'm facing a silly but annoying situation, when trying to display UTF 8 text in a Delphi XE7 console application. It seems the ReadLn command only reads the correct UTF 8 characters after a second try. For example:

    program ConsTest;

    {$APPTYPE CONSOLE}

    {$R *.res}

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

    var
      CurrentCodePage: Integer;
      Command: String;
      Running: Boolean;
      MyText: String;

    begin
      CurrentCodePage := GetConsoleOutputCP;
      SetConsoleOutputCP(CP_UTF8);
      SetTextCodePage(Output, CP_UTF8);

      MyText := 'Olá mundo.';
      WriteLn(MyText);

      Running := True;
      while Running do
      begin
        ReadLn(Command);
        WriteLn(Command);
        if (Command = '/q') then
          Running := false;
      end;

      SetConsoleOutputCP(CurrentCodePage);
      SetTextCodePage(Output, CurrentCodePage);
    end.

In the example above, just after I run the application, if I enter the following text:

'Olá mundo.'

The WriteLn will show:

'Ol mundo.'

Subsequently to the first pass, all UTF-8 characters read by the ReadLn command are being displayed ok. Is there any problem with this code? I tried to search for more details in the web, but I didn't find any information related to this. The call "WriteLn(MyText);" at the beginning of the code, shows the text 'Olá mundo.' correctly.

1

There are 1 answers

13
André Murta On

Ok, after pay a bit more attention to the first comment from Arioch, I tried the code below that works perfectly on any console.


    program ConsTest;

    {$APPTYPE CONSOLE}

    {$R *.res}

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

    var
      Command: String;
      Running: Boolean;
      MyText: String;

    begin
      MyText := 'Olá mundo.';
      WriteLn(MyText);

      Reset(Input); //*** That's the catch. ***

      Running := True;
      while Running do
      begin
        ReadLn(Input, Command);
        if (MyText = Command) then
          WriteLn('Yes')
        else
          WriteLn('No');

        WriteLn(Command);
        if (Command = '/q') then
          Running := false;
      end;
    end.

*OBS: The code above does not work for certain alphabets, I need a better understanding about Unicode and the console mode in Delphi. Due to certain coincidences, it solved my problem but cannot be considered actually an answer. Anyway, the call to the function "Reset(Input)" seems to be necessary in order to make sure the first call to ReadLn will work properly.