By default read-line leaves the \r character at the end of a line entered on the command line on Windows

Topic for discussion of

by default read-line leaves the \r character at the end of a line entered on the command line on Windows

Related GitHub items

I think the default for read-line is fine, and it is consistent with other languages.

I think the problem is that, in the Racket executable, stdin and stdout are opened in binary instead of text mode -- on Linux, this does not matter, but on Windows this causes the port to not translate the "\r\n" sequence into "\n".

A similar problem exists when writing. For example, on Window, when running the following program and redirecting the output to a file, produces a single "\n" in the file instead of the expected "\r\n":

#lang racket
(write-string "Hello World\n")

The equivalent C++ program, when its output is redirected to a file, produces the expected "\r\n" at the end of the greeting:

#include <iostream>

int main()
{
    std::cout << "Hello World!\n";
    return 0;
}

The problem with the output line endings is less noticeable, since most windows utilities (including the famous notepad.exe) now handle files with "\n".

According to (Text and Binary Mode File I/O | Microsoft Learn), stdin, stdout and stderr are always opened in text mode by default, and the user needs to re-open them in binary mode if they want binary output (I don't think there is a Racket facility to change the text/binary mode of an open port)

Alex.

I think the problem is that, in the Racket executable, stdin and stdout are opened in binary instead of text mode -- on Linux, this does not matter, but on Windows this causes the port to not translate the "\r\n" sequence into "\n".

I had the same thought, and @mflatt replied:

(Changing current-input-port to be in text mode creates all sorts of other problems, because it depends on whether you wanted text input or binary input. We tried things like that in the early days.)

EDITED: added the missing response.

A ghost of this lives on in racket --help:

  -b, --binary
     No effect, since stdin and stdout/stderr are
     always binary

A related but more limited feature I've sometimes wanted is a function somewhat like reincode-input-port that consumes one port and produces another, but performs precisely the same transformation on all platforms that text mode does on Windows. There are various functions that transform a broader class of newline encodings to #\newline, but I don't know a way to access exactly the same transformation that's built in on Windows.

1 Like