c# - separado - Leer el registro de ancho fijo desde el archivo de texto
leer y escribir archivos en c# (7)
Tengo un archivo de texto lleno de registros donde cada campo en cada registro tiene un ancho fijo. Mi primer enfoque sería analizar cada registro simplemente usando string.Substring (). ¿Hay una mejor manera?
Por ejemplo, el formato podría describirse como:
<Field1(8)><Field2(16)><Field3(12)>
Y un archivo de ejemplo con dos registros podría verse así:
SomeData0000000000123456SomeMoreData
Data2 0000000000555555MoreData
Solo quiero asegurarme de no pasar por alto una forma más elegante que Substring ().
Actualización: finalmente fui con una expresión regular como Killersponge sugirió:
private readonly Regex reLot = new Regex(REGEX_LOT, RegexOptions.Compiled);
const string REGEX_LOT = "^(?<Field1>.{6})" +
"(?<Field2>.{16})" +
"(?<Field3>.{12})";
Luego uso lo siguiente para acceder a los campos:
Match match = reLot.Match(record);
string field1 = match.Groups["Field1"].Value;
¿Por qué reinventar la rueda? Use la clase TextFieldParser de .NET de acuerdo con este instructivo para Visual Basic .
Desafortunadamente, de fábrica, CLR solo proporciona subcadenas para esto.
Alguien más en CodeProject hizo un analizador personalizado que usa atributos para definir campos , es posible que desee ver eso.
Es posible que tenga que tener cuidado, si el final de las líneas no está rellenado con espacios para llenar el campo, su subcadena no funcionará sin un poco de manipulación para calcular cuánto más de la línea hay para leer. Esto, por supuesto, solo se aplica al último campo :)
No, Subcadena está bien. Para eso es para eso.
Puede configurar un origen de datos ODBC para el archivo de formato fijo y luego acceder a él como cualquier otra tabla de base de datos. Esto tiene la ventaja adicional de que el conocimiento específico del formato de archivo no se compila en su código para ese fatídico día en que alguien decide colocar un campo extra en el medio.
Subcadena me suena bien. El único inconveniente que puedo pensar inmediatamente es que significa copiar los datos cada vez, pero no me preocuparé hasta que demuestres que se trata de un cuello de botella. Subcadena es simple :)
Podría usar una expresión regular para hacer coincidir un registro completo a la vez y capturar los campos, pero creo que eso sería excesivo.
Use FileHelpers .
Ejemplo:
[FixedLengthRecord()]
public class MyData
{
[FieldFixedLength(8)]
public string someData;
[FieldFixedLength(16)]
public int SomeNumber;
[FieldFixedLength(12)]
[FieldTrim(TrimMode.Right)]
public string someMoreData;
}
Entonces, es tan simple como esto:
var engine = new FileHelperEngine<MyData>();
// To Read Use:
var res = engine.ReadFile("FileIn.txt");
// To Write Use:
engine.WriteFile("FileOut.txt", res);