using System; using System.Collections.Generic; using System.IO; using System.Text; using NDbfReader; namespace S7Explorer.Parsers { public class DbfParser { // Lee campos específicos de un archivo DBF public static List> ReadDbfFile(string filePath, IEnumerable fieldNames) { var result = new List>(); if (!File.Exists(filePath)) throw new FileNotFoundException($"No se encontró el archivo DBF: {filePath}"); try { // Abrir tabla DBF con codificación específica (importante para caracteres especiales en STEP7) using var stream = File.OpenRead(filePath); using var table = Table.Open(stream); // Crear lector usando la API correcta var reader = table.OpenReader(); while (reader.Read()) { var record = new Dictionary(); foreach (var fieldName in fieldNames) { // Obtener valor y convertir a string si no es null var value = reader.GetValue(fieldName); // Manejar los diferentes tipos de datos if (value is byte[] byteValue) { // Para campos de tipo binario como MC5CODE record[fieldName] = Encoding.GetEncoding(1252).GetString(byteValue); } else if (value is DateTime dateValue) { // Mantener formato consistente para fechas record[fieldName] = dateValue.ToString("yyyy-MM-dd HH:mm:ss"); } else { // Para todos los demás tipos record[fieldName] = value?.ToString() ?? string.Empty; } } result.Add(record); } } catch (Exception ex) { throw new Exception($"Error al leer el archivo DBF {filePath}: {ex.Message}", ex); } return result; } // Convierte un string que representa un número a un entero opcional public static int? StringToInt(string value) { if (string.IsNullOrWhiteSpace(value)) return null; // Eliminar espacios y caracteres no numéricos iniciales string trimmedValue = value.Trim(); int startIndex = 0; while (startIndex < trimmedValue.Length && !char.IsDigit(trimmedValue[startIndex])) startIndex++; if (startIndex >= trimmedValue.Length) return null; // Extraer solo los dígitos string numericPart = new string(trimmedValue.Substring(startIndex) .TakeWhile(char.IsDigit) .ToArray()); if (int.TryParse(numericPart, out int result)) return result; return null; } // Convierte códigos Windows-1252 a UTF-8 para manejar caracteres especiales en STEP7 public static string ConvertCP1252ToUtf8(string input) { if (string.IsNullOrEmpty(input)) return string.Empty; try { // Primero decodificar como Windows-1252 y luego encodear como UTF-8 byte[] bytes = Encoding.GetEncoding(1252).GetBytes(input); return Encoding.UTF8.GetString(bytes); } catch { // En caso de error, devolver el string original return input; } } // Busca un archivo DBF en varias ubicaciones posibles basadas en el patrón de archivos STEP7 public static string FindDbfFile(string basePath, string relativePath) { string path = Path.Combine(basePath, relativePath); if (File.Exists(path)) return path; // Comprobar si se puede encontrar en un directorio padre string parentPath = Directory.GetParent(basePath)?.FullName; if (!string.IsNullOrEmpty(parentPath)) { path = Path.Combine(parentPath, relativePath); if (File.Exists(path)) return path; } // Intentar buscar por nombre de archivo en subdirectorios string fileName = Path.GetFileName(relativePath); foreach (var subdir in Directory.GetDirectories(basePath, "*", SearchOption.AllDirectories)) { path = Path.Combine(subdir, fileName); if (File.Exists(path)) return path; } return null; } } }