The docs for Console.ReadLine
say:
By default, the method reads input from a 256-character input buffer. Because this includes the Environment.NewLine character(s), the method can read lines that contain up to 254 characters. To read longer lines, call the OpenStandardInput(Int32) method.
However, I can read more than that many characters just fine. Running a simple program like:
string s = Console.ReadLine();
Console.WriteLine(s);
Console.WriteLine(s.Length);
Console.ReadKey();
with an input like:
aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjj
yields the same input back with length 500.
Runnable example here.
Are the docs outdated then, or are the words "by default" key here?
An update: Jeremy found a limit of 4096 defined in the source code.
I have verified that a .NET Core app will only read the first 4094 characters from stdin (excluding newlines).
In my case, I actually have a .NET Core 3.1 process that starts a .NET Framework 4.6 process, redirecting its StandardOut and StandardIn. I have verified that the .NET Framework process can successfully read 1 billion characters via Console.ReadLine()
where the .NET Core 3.1 process sends the Framework process stuff via fwProcess.StandardInput.WriteLine(Serialize(<some stuff>));
This also works when the .NET Framework process is replaced with a .NET Core process.
So it seems like the 256-character limit doesn't apply when redirecting stdout/stdin, but if someone can dig up the definitive proof/docs explaining this, I would appreciate it. If there is still a limit (excluding the OutOfMemory case), but it's 1.1 billion characters, I would like to know. I'd also like to know if this is platform dependent (I'm on Windows 10).
If it helps, this is the code that I'm running.
ConsoleApp1:
ProcessStartInfo processInfo = new ProcessStartInfo {
CreateNoWindow = true,
FileName = "ConsoleApp2.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true
};
StringBuilder s = new StringBuilder();
var proc = Process.Start(processInfo);
int n = 1_000_000_000;
for (int i = 0; i < n; i++)
s.Append("a");
proc.StandardInput.WriteLine(s.ToString());
string s = proc.StandardOutput.ReadLine();
Console.WriteLine(s.Length == n); // logs True
Console.ReadKey();
ConsoleApp2:
string s = Console.ReadLine();
Console.WriteLine(s);
Paraphrasing from here:
The default cmd console mode is "ENABLE_LINE_INPUT", which means that when code issues a ::ReadFile call against stdin, ::ReadFile doesn't return to the caller until it encounters a carriage return. But the call to ReadFile only has a limited size buffer that was passed to it. Which means that cmd looks at the buffer size provided to it, and determines based on that how many characters long the line can be... if the line were longer, it wouldn't be able to store all the data into the buffer.
The default buffer size used when opening Console.In
is now 4096 (source)
The documentation is open source, and available here if you would like to submit an issue or pull request.
When redirecting StandardOut/StandardIn, this limit does not apply. From here:
The limit is how much memory you pass in.