Puede agregar un método adicional a StreamReader (el código fuente de, p. Ej.Mono podría ser utilizado para ese propósito):
private StringBuilder lineBuilder;
public int RegexBufferSize
{
set { lastRegexMatchedLength = value; }
get { return lastRegexMatchedLength; }
}
private int lastRegexMatchedLength = 0;
public virtual string ReadRegex(Regex regex)
{
if (base_stream == null)
throw new ObjectDisposedException("StreamReader", "Cannot read from a closed RegexStreamReader");
if (pos >= decoded_count && ReadBuffer() == 0)
return null; // EOF Reached
if (lineBuilder == null)
lineBuilder = new StringBuilder();
else
lineBuilder.Length = 0;
lineBuilder.Append(decoded_buffer, pos, decoded_count - pos);
int bytesRead = ReadBuffer();
bool dataTested = false;
while (bytesRead > 0)
{
var lineBuilderStartLen = lineBuilder.Length;
dataTested = false;
lineBuilder.Append(decoded_buffer, 0, bytesRead);
if (lineBuilder.Length >= lastRegexMatchedLength)
{
var currentBuf = lineBuilder.ToString();
var match = regex.Match(currentBuf, 0, currentBuf.Length);
if (match.Success)
{
var offset = match.Index + match.Length;
pos = 0;
decoded_count = lineBuilder.Length - offset;
ensureMinDecodedBufLen(decoded_count);
lineBuilder.CopyTo(offset, decoded_buffer, 0, decoded_count);
var matchedString = currentBuf.Substring(match.Index, match.Length);
return matchedString;
}
else
{
lastRegexMatchedLength *= (int) 1.1; // allow for more space before attempting to match
dataTested = true;
}
}
bytesRead = ReadBuffer();
}
// EOF reached
if (!dataTested)
{
var currentBuf = lineBuilder.ToString();
var match = regex.Match(currentBuf, 0, currentBuf.Length);
if (match.Success)
{
var offset = match.Index + match.Length;
pos = 0;
decoded_count = lineBuilder.Length - offset;
ensureMinDecodedBufLen(decoded_count);
lineBuilder.CopyTo(offset, decoded_buffer, 0, decoded_count);
var matchedString = currentBuf.Substring(match.Index, match.Length);
return matchedString;
}
}
pos = decoded_count;
return null;
}
En el método anterior, se usan las siguientes vars:
- decoded_buffer: la char buffer que contiene/contendrá los datos leídos
- pos : offset dentro de la matriz que contiene datos no controlados
- decoded_count: el último elemento dentro del búfer que contiene los datos de lectura
- RegexBufferSize: el tamaño mínimo de la entrada de expresiones regulares antes de una ny se produce la coincidencia.
El método ReadBuffer() necesita leer los datos de la secuencia. El método ensureMinDecodedBufLen() necesita asegurarse de que decoded_buffer sea lo suficientemente grande.
Al llamar al método, pase la Regex que debe coincidir.
¿Por qué no puedes esperar hasta recibir todos los datos? – ChaosPandion
En mi experiencia, a menudo la expresión regular obstaculiza el rendimiento, no las cadenas de conversión y GC. A menos que su coincidencia sea muy compleja, le sugiero que cree su propio escáner de flujo para las coincidencias en lugar de Regex. Pero debe compararlo con el uso de una expresión regular para asegurarse de que está en el camino correcto. –
@ChaosPandion: Si la transmisión es un archivo grande, no voy a cargar todas sus gigas en la memoria, especialmente no en utf-16 (codificación de cadena en la memoria en .net). Si el flujo proviene de Internet, quiero poder escanearlo antes de que se reciban todos los datos recibidos (IE HTML Parser, muestre las partes descargadas antes de que el resto de la página se descargue). – DxCK