S7Explorer/Parsers/DbfParser.cs

139 lines
5.0 KiB
C#

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<Dictionary<string, string>> ReadDbfFile(string filePath, IEnumerable<string> fieldNames)
{
var result = new List<Dictionary<string, string>>();
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<string, string>();
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;
}
}
}