C# 如何限制 .NET 中 StreamReader.ReadLine() 读取的字符数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/400407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to limit the number of characters read by StreamReader.ReadLine() in .NET?
提问by Roman Shumikhin
I am writing a web server application in C# and using StreamReader class to read from an underlying NetworkStream:
我正在用 C# 编写一个 Web 服务器应用程序,并使用 StreamReader 类从底层 NetworkStream 读取:
NetworkStream ns = new NetworkStream(clientSocket);
StreamReader sr = new StreamReader(ns);
String request = sr.ReadLine();
This code is prone to DoS attacks because if the attacker never disconnects we will never finish reading the line. Is there any way to limit the number of characters read by StreamReader.ReadLine() in .NET?
这段代码很容易受到 DoS 攻击,因为如果攻击者永远不会断开连接,我们将永远不会读完该行。有没有办法限制 .NET 中 StreamReader.ReadLine() 读取的字符数?
采纳答案by Marc Gravell
You would have to use the Read(char[], int, int)
overload (which does limit the length) and do your own end-of-line detection; shouldn't be too tricky.
您将不得不使用Read(char[], int, int)
重载(它确实限制了长度)并进行自己的行尾检测;不应该太棘手。
For a slightly lazy version (that uses the single-characted reading version):
对于稍微懒惰的版本(使用单字符阅读版本):
static IEnumerable<string> ReadLines(string path, int maxLineLength)
{
StringBuilder currentLine = new StringBuilder(maxLineLength);
using (var reader = File.OpenText(path))
{
int i;
while((i = reader.Read()) > 0) {
char c = (char) i;
if(c == '\r' || c == '\n') {
yield return currentLine.ToString();
currentLine.Length = 0;
continue;
}
currentLine.Append((char)c);
if (currentLine.Length > maxLineLength)
{
throw new InvalidOperationException("Max length exceeded");
}
}
if (currentLine.Length > 0)
{
yield return currentLine.ToString();
}
}
}
回答by Austin Salonen
You can always use ".Read(...)" and MSDN recommends doing so for a situation like yours.
您始终可以使用“.Read(...)”,MSDN 建议在您遇到的情况下这样做。
http://msdn.microsoft.com/en-us/library/system.io.streamreader.readline.aspx
http://msdn.microsoft.com/en-us/library/system.io.streamreader.readline.aspx
回答by Gant
You might need one of StreamReader.Read
overload:
您可能需要StreamReader.Read
重载之一:
Taken from http://msdn.microsoft.com/en-us/library/9kstw824.aspx
取自http://msdn.microsoft.com/en-us/library/9kstw824.aspx
using (StreamReader sr = new StreamReader(path))
{
//This is an arbitrary size for this example.
char[] c = null;
while (sr.Peek() >= 0)
{
c = new char[5];
sr.Read(c, 0, c.Length);
//The output will look odd, because
//only five characters are read at a time.
Console.WriteLine(c);
}
}
Focus on the sr.Read(c, 0, c.Length)
line. This reads only 5 character from stream and put in into c
array. You may want to change 5 to value you want.
专注于sr.Read(c, 0, c.Length)
线。这仅从流中读取 5 个字符并放入c
数组中。您可能希望将 5 更改为您想要的值。
回答by Roman Shumikhin
Here is my own solution based on the solution by Marc Gravell:
这是我自己的基于 Marc Gravell 解决方案的解决方案:
using System;
using System.IO;
using System.Text;
namespace MyProject
{
class StreamReaderExt : StreamReader
{
public StreamReaderExt(Stream s, Encoding e) : base(s, e)
{
}
/// <summary>
/// Reads a line of characters terminated by CR+LF from the current stream and returns the data as a string
/// </summary>
/// <param name="maxLineLength">Maximum allowed line length</param>
/// <exception cref="System.IO.IOException" />
/// <exception cref="System.InvalidOperationException">When string read by this method exceeds the maximum allowed line length</exception>
/// <returns></returns>
public string ReadLineCRLF(int maxLineLength)
{
StringBuilder currentLine = new StringBuilder(maxLineLength);
int i;
bool foundCR = false;
bool readData = false;
while ((i = Read()) > 0)
{
readData = true;
char c = (char)i;
if (foundCR)
{
if (c == '\r')
{
// If CR was found before , and the next character is also CR,
// adding previously skipped CR to the result string
currentLine.Append('\r');
continue;
}
else if (c == '\n')
{
// LF found, finished reading the string
return currentLine.ToString();
}
else
{
// If CR was found before , but the next character is not LF,
// adding previously skipped CR to the result string
currentLine.Append('\r');
foundCR = false;
}
}
else // CR not found
{
if (c == '\r')
{
foundCR = true;
continue;
}
}
currentLine.Append((char)c);
if (currentLine.Length > maxLineLength)
{
throw new InvalidOperationException("Max line length exceeded");
}
}
if (foundCR)
{
// If CR was found before, and the end of the stream has been reached, appending the skipped CR character
currentLine.Append('\r');
}
if (readData)
{
return currentLine.ToString();
}
// End of the stream reached
return null;
}
}
}
This piece of code is provided "AS IS" with NO WARRANTY.
这段代码按“原样”提供,不提供任何保证。