139 lines
5.0 KiB
C#
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;
|
|
}
|
|
}
|
|
} |