Un StreamReader personalizado que desarrolle hace algún tiempo para ayudarme un poco.
public delegate void ManejadorExcepcion(object sender, string mensaje);
public delegate void ManejadorAbrirCerrarArchivo(object sender, AccionArchivo accionArchivo);
public delegate void ManejadorIniciarFinalizarLectura(object sender, EstadoLecturaArchivo estadoLecturaArchivo);
public enum AccionArchivo {
Abrir,
Cerrar
}
public enum EstadoLecturaArchivo {
Iniciado,
Finalizado
}
/// <summary>
/// StreamReader personalizado
/// </summary>
public sealed class LectorArchivo : IDisposable {
//Campos
private string _dirArchivo;
private string _nombreArchivoCorto;
private string _lineaAnterior;
private string _lineaActual;
private int _posicionActual;
private int _totalLineas;
private Dictionary<string, string> _valores;
private StreamReader _lector;
private Encoding _codificacion;
private bool _alAbrirCerrarArchivoEventoDisparado;
//Eventos
public event ManejadorAbrirCerrarArchivo AlAbrirCerrarArchivo;
public event ManejadorIniciarFinalizarLectura AlIniciarFinalizarLectura;
//Constructores
public LectorArchivo(string dirArchivo, Dictionary<string, string> valores){
InicializarComponentes(dirArchivo, valores, Encoding.Default);
}
public LectorArchivo(string dirArchivo, Dictionary<string, string> valores, Encoding codificacion) {
InicializarComponentes(dirArchivo, valores, codificacion);
}
public LectorArchivo(string dirArchivo){
InicializarComponentes(dirArchivo, new Dictionary<string, string>(), Encoding.Default);
}
public LectorArchivo(string dirArchivo, Encoding codificacion) {
InicializarComponentes(dirArchivo, new Dictionary<string, string>(), codificacion);
}
//Métodos públicos
public void Abrir() {
_lector = new StreamReader(_dirArchivo, _codificacion);
if (AlAbrirCerrarArchivo != null)
AlAbrirCerrarArchivo(this, AccionArchivo.Abrir);
}
public void Cerrar() {
_lector.Close();
if (AlAbrirCerrarArchivo != null)
AlAbrirCerrarArchivo(this, AccionArchivo.Cerrar);
}
public void Dispose() {
Dispose();
}
public string LeerLinea() {
string retVal = null;
_lineaAnterior = _lineaActual;
retVal = _lector.ReadLine();
if(AlIniciarFinalizarLectura != null && !_alAbrirCerrarArchivoEventoDisparado) {
AlIniciarFinalizarLectura(this, EstadoLecturaArchivo.Iniciado);
_alAbrirCerrarArchivoEventoDisparado = true;
}
_lineaActual = retVal;
_posicionActual++;
if (retVal.Trim().Length > 0)
retVal = EliminarCaracteres(retVal);
return retVal;
}
public string LeerLinea(Predicate<string> predicado) {
string retVal;
retVal = LeerLinea();
if (retVal != null) {
if (!predicado.Invoke(retVal)) retVal = null;
}
return retVal;
}
public List<string> LeerLineas(int cantidad) {
List<string> retVal = new List<string>();
for(int i = 1; i <= cantidad; i++) {
if(!FinDeArchivo)
retVal.Add(LeerLinea());
else
break;
}
return retVal;
}
//Propiedades
public string DirArchivo {
get { return _dirArchivo; }
}
public string NombreArchivoCorto {
get { return _nombreArchivoCorto; }
}
public string LineaAnterior {
get { return _lineaAnterior; }
}
public string LineaActual {
get { return _lineaActual; }
}
public int PosicionActual {
get { return _posicionActual; }
}
public int TotalLineas {
get {
if(_totalLineas == -1) {
_totalLineas = LectorArchivo.CuantasLineas(_dirArchivo);
}
return _totalLineas;
}
}
public Dictionary<string, string> Valores {
get { return _valores; }
}
public bool FinDeArchivo {
get {
bool retVal = !(_lector.Peek() != -1);
if (retVal) {
if (AlIniciarFinalizarLectura != null)
AlIniciarFinalizarLectura(this, EstadoLecturaArchivo.Finalizado);
}
return retVal;
}
}
//Métodos Privados
private string EliminarCaracteres(string linea) {
string retVal;
Dictionary<string, string>.Enumerator enumerador;
KeyValuePair<string, string> par;
enumerador = _valores.GetEnumerator();
par = new KeyValuePair<string, string>();
while (enumerador.MoveNext()) {
par = enumerador.Current;
linea = linea.Replace(par.Key, par.Value);
}
enumerador.Dispose();
retVal = linea;
return retVal;
}
private void InicializarComponentes(string dirArchivo, Dictionary<string, string> valores, Encoding codificacion) {
if (!File.Exists(dirArchivo)) throw new FileNotFoundException();
_dirArchivo = dirArchivo;
_nombreArchivoCorto = System.IO.Path.GetFileName(_dirArchivo);
_valores = valores;
_posicionActual = 0;
_totalLineas = -1;
_codificacion = codificacion;
_alAbrirCerrarArchivoEventoDisparado = false;
}
private void IDisposable.Dispose() {
_lector.Dispose();
_lector = null;
}
//Métodos estáticos
public static int CuantasLineas(string dirArchivo) {
int retVal = 0;
LectorArchivo x = new LectorArchivo(dirArchivo);
for (retVal = 0; !x.FinDeArchivo; retVal++, x.LeerLinea());
x.Cerrar();
x.Dispose();
return retVal;
}
public static int CuantasLineas(string dirArchivo, Predicate<string> predicado) {
int retVal = 0;
LectorArchivo x = new LectorArchivo(dirArchivo);
while (!x.FinDeArchivo) {
if (x.LeerLinea(predicado) != null) retVal++;
}
x.Cerrar();
x.Dispose();
return retVal;
}
public static string IrLinea(string dirArchivo, int numeroLinea) {
string retVal = null;
int contador = 0;
LectorArchivo x = new LectorArchivo(dirArchivo);
while (!x.FinDeArchivo) {
retVal = x.LeerLinea();
contador++;
if (contador.Equals(numeroLinea)) break;
}
x.Cerrar();
x.Dispose();
return retVal;
}
public static string[] ObtenerLineas(string dirArchivo, int desde, int hasta, bool incluirLimites) {
//Evaluar que el valor de los parametros sean razonables,
//Ejemplo:
// - dirArchivo = Debe ser un archivo que exista en disco
// - Desde = No puede ser un valor negativo
// - Hacer que el metodo funcione con Genericos siempre y cuando los valores de <T> sea un Array, ReadOnlyCollection, List<string>, etc.
// - Hacer las pruebas correspondientes para evaluar el rendimiento.
string[] retVal;
string lineaLeida;
int dimension;
int contador;
LectorArchivo lectorArchivo;
dimension = incluirLimites ? (hasta - desde) + 1 : (hasta - desde);
retVal = new string[dimension];
contador = 0;
lectorArchivo = new LectorArchivo(dirArchivo);
while (!lectorArchivo.FinDeArchivo) {
lineaLeida = lectorArchivo.LeerLinea();
if (incluirLimites) {
if (lectorArchivo.PosicionActual >= desde && lectorArchivo.PosicionActual <= hasta) {
retVal[contador] = lineaLeida;
contador++;
}
} else {
if (lectorArchivo.PosicionActual > desde && lectorArchivo.PosicionActual < hasta) {
retVal[contador] = lineaLeida;
contador++;
}
}
if (contador == retVal.Length) break;
}
lectorArchivo.Cerrar();
lectorArchivo.Dispose();
return retVal;
}
public static void GenerarNuevoArchivo(string dirArchivoOrigen, string dirArchivoNuevo, Predicate<string> predicado) {
LectorArchivo lectorArchivo;
StreamWriter escritor;
string linea;
lectorArchivo = new LectorArchivo(dirArchivoOrigen);
escritor = new StreamWriter(dirArchivoNuevo, false, Encoding.Default);
while (!lectorArchivo.FinDeArchivo) {
linea = lectorArchivo.LeerLinea();
if (predicado.Invoke(linea)) {
escritor.WriteLine(linea);
}
}
escritor.Close();
escritor.Dispose();
lectorArchivo.Cerrar();
lectorArchivo.Dispose();
}
}