none
¿Cómo puedo transferir el contenido de un archivo de texto a una lista? (explico, lean por favor) RRS feed

  • Pregunta

  • Tengo un archivo de texto con la siguiente estructura:

    ENCABEZADO 1.........ENCABEZADO 2.......ENCABEZADO 3.......ENCABEZADO 4

    -----------------.........------------------.......------------------........------------------

    Dato 1.....................Dato 2...................Dato 3.....................Dato 4

    Dato 1.....................Dato 2...................Dato 3.....................Dato 4

    Dato 1.....................Dato 2...................Dato 3.....................Dato 4

    Dato 1.....................Dato 2...................Dato 3.....................Dato 4

    Como pueden observar las dos primeras líneas corresponden al encabezado y las siguientes a los datos.

    Puse puntos suspensivos para que se vea ordenado pero en realidad se trata de un espacio en blanco de separación entre dato y dato.

    Lo que deseo es transferir el contenido de ese archivo de texto (Datos.txt) a una lista (lisDatos) cuyos elementos sean un arreglo que contenga a los cuatro datos de cada fila (descartando las dos líneas del encabezado). O sea sólo quiero obtener los datos de manera que:

    lisDatos(1) = {"Dato 1", "Dato 2", "Dato 3", "Dato 4"} 'De la primera fila

    lisDatos(2) = {"Dato 1", "Dato 2", "Dato 3", "Dato 4"} 'De la segunda fila y así sucesivamente

    Deseo hacerlo en una línea más o menos así:

    lisDatos = File.ReadAllLines("Datos.txt", ¿QUÉ PONDRÍA AQUÍ PARA OBTENER EL RESULTADO ANTERIOR?)

    domingo, 8 de abril de 2018 17:16

Respuestas

  • Ah, para, eso es otra cosa. En la pregunta inicial habías dicho que el separador de columnas era un espacio en blanco. Pero resulta que no es el caso, no se puede usar el espacio como separador entre otras cosas porque hay columnas que contienen un espacio en blanco en medio del texto (tal como "Windows RE"), y además hay columnas vacías, y además queremos conservar los espacios cuando hay más de uno.

    Así que no se trata de un fichero con columnas divididas por un separador, sino que son columnas de longitud fija. Siendo así, el criterio para trocearlas es tomar una subcadena que tenga la longitud exacta deseada.

    Por ejemplo, la primera columna sería linea.SubString(0, 11), la segunda sería linea.SubString(12, 3), etc. (obviamente tendrás que ajustar los números según la anchura que realmente tengan).

    Pero me temo que esto sí que no se puede conseguir en una única línea. Bueno, sí, puedes escribir todos los "Substring" uno detrás de otro en la misma línea, pero no ganarías nada y quedará menos legible que si lo escribes en varias líneas.

    • Marcado como respuesta James2016-2 lunes, 9 de abril de 2018 16:35
    lunes, 9 de abril de 2018 5:54

Todas las respuestas

  • No, en una sola línea no vas a poder hacerlo, salvo que esa línea haga una llamada a una función que lo haga. Vas a necesitar estos pasos:

    - Primero usa el File.ReadAllLines para leer las líneas completas a un array de líneas (el File.ReadAllLines no sabe "hacer" nada con las líneas, no puedes pasarle instrucciones en el sitio que has puesto en negrita).

    - Después se recorre ese array con un bucle (que puede ser explícito o podrías usar un selector de LINQ) usando la función Split para trocear cada línea por los espacios en blanco.

    Si lo haces con LINQ se puede juntar todo en una línea y quedaría algo parecido a lo siguiente:

    Dim lisDatos = File.ReadAllLines("Datos.txt").Skip(2).Select(Function(s) s.Split(" "c)).ToList();

    domingo, 8 de abril de 2018 18:14
  • Sí a eso me refería más o menos, o sea a una función que lo haga. Algo así:

    Encoding.Default).Where(Function(x) x...    'pero allí no sé qué más poner

    domingo, 8 de abril de 2018 18:24
  • ¿Has probado la que te puse en la anterior respuesta? Es un Select en lugar del Where. Y el Skip que te puse es para saltarse las cabeceras.
    domingo, 8 de abril de 2018 20:26
  • No, todavía no lo probé es que estoy tratando de resolver otra parte del programa que estoy haciendo, pero creo que no me expliqué bien en la pregunta, lo que consultaba era una línea más o menos así

    Lista = File.ReadAllLines(ArchivoTemporal, Encoding.Default).Where(Function(x) x.Trim <> String.Empty).Select(Function(x) x.ToUpper.Trim.TrimEnd("."c)).ToList()

    Quería usar una línea así para obtener la lista de la pregunta. El código de encima obtiene una lista con otras condiciones pero la idea es la misma, o sea usar una función adecuada en la misma línea que devuelva la lista pero según las condiciones de la pregunta inicial.

    domingo, 8 de abril de 2018 21:34
  • Buenas, probé el código de LINQ:

    Dim lisDatos = File.ReadAllLines("Datos.txt").Skip(2).Select(Function(s) s.Split(" "c)).ToList();

    y funciona, pero hay un detalle, no me extrae columnas uniformemente.

    Para efectos de visualización entre elemento y elemento de cada fila le puse un caracter "|" como separador y la salida es esta:

    Imagenes del archivo de texto y de la salida via programa:


    Salida:

    Veo que en el archivo de texto (imagen de arriba) las columnas tienen un ancho fijo, cómo podría hacer para extraer por columna un número fijo de caracteres? por ejemplo la primera que sea de ancho 14, la segunda de ancho 4 y así...


    lunes, 9 de abril de 2018 3:38
  • Ah, para, eso es otra cosa. En la pregunta inicial habías dicho que el separador de columnas era un espacio en blanco. Pero resulta que no es el caso, no se puede usar el espacio como separador entre otras cosas porque hay columnas que contienen un espacio en blanco en medio del texto (tal como "Windows RE"), y además hay columnas vacías, y además queremos conservar los espacios cuando hay más de uno.

    Así que no se trata de un fichero con columnas divididas por un separador, sino que son columnas de longitud fija. Siendo así, el criterio para trocearlas es tomar una subcadena que tenga la longitud exacta deseada.

    Por ejemplo, la primera columna sería linea.SubString(0, 11), la segunda sería linea.SubString(12, 3), etc. (obviamente tendrás que ajustar los números según la anchura que realmente tengan).

    Pero me temo que esto sí que no se puede conseguir en una única línea. Bueno, sí, puedes escribir todos los "Substring" uno detrás de otro en la misma línea, pero no ganarías nada y quedará menos legible que si lo escribes en varias líneas.

    • Marcado como respuesta James2016-2 lunes, 9 de abril de 2018 16:35
    lunes, 9 de abril de 2018 5:54
  • Sí, sorry pensé que los otros espacios eran irrelevantes pero veo que no, trocé cada fila como me indica recorriéndolas en un For dándole un ancho fijo a cada columna y agregándolas a una lista de arrays donde cada elemento del array correponde a una columna de cada fila y ya quedó. Gracias por todo.
    lunes, 9 de abril de 2018 16:35