Allineamento dati con repository di origine
This commit is contained in:
293
HorseRacingPredictor/HorseRacingPredictor/Manager/FileReader.cs
Normal file
293
HorseRacingPredictor/HorseRacingPredictor/Manager/FileReader.cs
Normal file
@@ -0,0 +1,293 @@
|
||||
using CsvHelper;
|
||||
using CsvHelper.Configuration;
|
||||
using CsvHelper.TypeConversion;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HorseRacingPredictor.Manager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gestore generico per la lettura di file CSV
|
||||
/// </summary>
|
||||
public class FileReader
|
||||
{
|
||||
public class NullableDecimalConverter : DefaultTypeConverter
|
||||
{
|
||||
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||||
{
|
||||
return ConvertToDecimal(text);
|
||||
}
|
||||
}
|
||||
|
||||
public class NullableIntConverter : DefaultTypeConverter
|
||||
{
|
||||
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||||
{
|
||||
return ConvertToInt(text);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legge un file CSV e lo converte in un DataTable
|
||||
/// </summary>
|
||||
/// <param name="filePath">Percorso del file CSV</param>
|
||||
/// <returns>DataTable contenente i dati del file CSV</returns>
|
||||
public DataTable ReadCsvToDataTable(string filePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
throw new ArgumentException("Il percorso del file non può essere vuoto.", nameof(filePath));
|
||||
}
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
throw new FileNotFoundException($"File non trovato: {filePath}");
|
||||
}
|
||||
|
||||
var dataTable = new DataTable();
|
||||
|
||||
// Configurazione per CsvHelper
|
||||
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
|
||||
{
|
||||
HasHeaderRecord = true,
|
||||
MissingFieldFound = null, // Ignora campi mancanti
|
||||
TrimOptions = TrimOptions.Trim, // Rimuove spazi iniziali e finali
|
||||
PrepareHeaderForMatch = args => args.Header.Replace("#", "").Trim() // Rimuove # e spazi dai nomi delle colonne
|
||||
};
|
||||
|
||||
using (var reader = new StreamReader(filePath))
|
||||
using (var csv = new CsvReader(reader, config))
|
||||
{
|
||||
// Legge l'intestazione
|
||||
csv.Read();
|
||||
csv.ReadHeader();
|
||||
|
||||
// Crea le colonne della tabella dai nomi delle colonne del CSV
|
||||
foreach (var header in csv.HeaderRecord)
|
||||
{
|
||||
string columnName = header.Replace("#", "").Trim();
|
||||
dataTable.Columns.Add(columnName);
|
||||
}
|
||||
|
||||
// Legge i dati riga per riga
|
||||
while (csv.Read())
|
||||
{
|
||||
var row = dataTable.NewRow();
|
||||
for (int i = 0; i < csv.HeaderRecord.Length; i++)
|
||||
{
|
||||
string columnName = csv.HeaderRecord[i].Replace("#", "").Trim();
|
||||
string value = csv.GetField(i) ?? string.Empty;
|
||||
row[columnName] = value;
|
||||
}
|
||||
dataTable.Rows.Add(row);
|
||||
}
|
||||
}
|
||||
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ottiene una lista di tutti i file CSV in una cartella e nelle sue sottocartelle
|
||||
/// </summary>
|
||||
/// <param name="folderPath">Percorso della cartella da esplorare</param>
|
||||
/// <returns>Lista di percorsi dei file CSV trovati</returns>
|
||||
public List<string> GetCsvFiles(string folderPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(folderPath))
|
||||
{
|
||||
throw new ArgumentException("Il percorso della cartella non può essere vuoto.", nameof(folderPath));
|
||||
}
|
||||
|
||||
if (!Directory.Exists(folderPath))
|
||||
{
|
||||
throw new DirectoryNotFoundException($"Directory non trovata: {folderPath}");
|
||||
}
|
||||
|
||||
var csvFiles = Directory.GetFiles(folderPath, "*.csv", SearchOption.AllDirectories);
|
||||
return new List<string>(csvFiles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metodo helper per estrarre un valore stringa da una riga di DataTable
|
||||
/// </summary>
|
||||
public string GetStringValue(DataRow row, string columnName)
|
||||
{
|
||||
if (!row.Table.Columns.Contains(columnName) || row[columnName] == DBNull.Value)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
return row[columnName].ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metodo helper per estrarre un valore intero da una riga di DataTable
|
||||
/// Gestisce valori nulli o non validi restituendo 0
|
||||
/// </summary>
|
||||
public int GetIntValue(DataRow row, string columnName)
|
||||
{
|
||||
if (!row.Table.Columns.Contains(columnName) || row[columnName] == DBNull.Value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (int.TryParse(row[columnName].ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out int result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metodo helper per estrarre un valore intero nullable da una riga di DataTable
|
||||
/// Restituisce null per valori mancanti o non validi
|
||||
/// </summary>
|
||||
public int? GetNullableIntValue(DataRow row, string columnName)
|
||||
{
|
||||
if (!row.Table.Columns.Contains(columnName) || row[columnName] == DBNull.Value)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string stringValue = row[columnName].ToString();
|
||||
if (string.IsNullOrWhiteSpace(stringValue))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (int.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out int result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metodo helper per estrarre un valore decimale da una riga di DataTable con controllo di precisione
|
||||
/// Gestisce valori nulli o non validi restituendo 0
|
||||
/// </summary>
|
||||
public decimal GetDecimalValue(DataRow row, string columnName, int precision, int scale)
|
||||
{
|
||||
if (!row.Table.Columns.Contains(columnName) || row[columnName] == DBNull.Value)
|
||||
{
|
||||
return 0.0M;
|
||||
}
|
||||
|
||||
if (decimal.TryParse(row[columnName].ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out decimal result))
|
||||
{
|
||||
// Arrotonda il valore per rispettare il limite di precisione e scala
|
||||
decimal factor = (decimal)Math.Pow(10, scale);
|
||||
result = Math.Round(result, scale);
|
||||
|
||||
// Verifica se il valore è entro i limiti di precisione
|
||||
decimal maxValue = (decimal)Math.Pow(10, precision - scale) - (1 / factor);
|
||||
if (Math.Abs(result) > maxValue)
|
||||
{
|
||||
Console.WriteLine($"Valore fuori range per {columnName}: {result}, limitato a {maxValue}");
|
||||
result = result < 0 ? -maxValue : maxValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return 0.0M;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metodo helper per estrarre un valore decimale nullable da una riga di DataTable
|
||||
/// Restituisce null per valori mancanti o non validi
|
||||
/// </summary>
|
||||
public decimal? GetNullableDecimalValue(DataRow row, string columnName, int precision, int scale)
|
||||
{
|
||||
if (!row.Table.Columns.Contains(columnName) || row[columnName] == DBNull.Value)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string stringValue = row[columnName].ToString();
|
||||
if (string.IsNullOrWhiteSpace(stringValue))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (decimal.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal result))
|
||||
{
|
||||
// Arrotonda il valore per rispettare il limite di precisione e scala
|
||||
decimal factor = (decimal)Math.Pow(10, scale);
|
||||
result = Math.Round(result, scale);
|
||||
|
||||
// Verifica se il valore è entro i limiti di precisione
|
||||
decimal maxValue = (decimal)Math.Pow(10, precision - scale) - (1 / factor);
|
||||
if (Math.Abs(result) > maxValue)
|
||||
{
|
||||
Console.WriteLine($"Valore fuori range per {columnName}: {result}, limitato a {maxValue}");
|
||||
result = result < 0 ? -maxValue : maxValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converte un valore stringa in int con gestione dei valori nulli o non validi
|
||||
/// </summary>
|
||||
public static int ConvertToInt(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return 0;
|
||||
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out int result))
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converte un valore stringa in decimal con gestione dei valori nulli o non validi
|
||||
/// </summary>
|
||||
public static decimal ConvertToDecimal(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return 0m;
|
||||
|
||||
if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal result))
|
||||
return result;
|
||||
|
||||
return 0m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converte un valore stringa in int? con gestione dei valori nulli o non validi
|
||||
/// </summary>
|
||||
public static int? ConvertToNullableInt(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return null;
|
||||
|
||||
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out int result))
|
||||
return result;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converte un valore stringa in decimal? con gestione dei valori nulli o non validi
|
||||
/// </summary>
|
||||
public static decimal? ConvertToNullableDecimal(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return null;
|
||||
|
||||
if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal result))
|
||||
return result;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user