Member 4576405
Привет,
Недавно я сделал программу для импорта CSV-файла, она содержит проверки ошибок, нормализации и другие материалы. Вы можете адаптировать этот код для своих целей, импортированные столбцы CSV описаны в классе Order -> method: InitializeFieldDesc().
using System;
using System.IO;
using System.Collections.Generic;
public class ImportCSV
{
List<Order> orders; // Valid order list
List<Order> invalidOrders; // Invalid order list
Logger logger; // Logger for info and errors
/// <summary>
/// Initialize object and load file data
/// </summary>
public ImportCSV(string filePath)
{
logger = new Logger();
orders = new List<Order>();
invalidOrders = new List<Order>();
LoadOrders(filePath);
}
#region Load orders
/// <summary>
/// Load orders from file
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
private void LoadOrders(string filePath)
{
// Check if file exists
if (File.Exists(filePath))
{
GetOrdersFromFile(filePath);
}
else
{
// File not exits
throw new FileNotFoundException("File not found");
}
}
/// <summary>
/// Get orders from file and insert in List
/// </summary>
/// <param name="filePath"></param>
private void GetOrdersFromFile(string filePath)
{
// set active order in logger
logger.setActiveOrder(-1);
logger.AddInfo("Opening file: " + filePath);
try
{
string[] lines = File.ReadAllLines(filePath);
// insert one order per line
for (int i = 0; i < lines.Length; i++)
{
// logger active order id
logger.setActiveOrder(i);
// Initialize order class with field desc
Order tempOrder = new Order(ref logger);
logger.AddInfo("Mapping a string into order's object. Line nº: " + i.ToString());
// Mapping a string into order's object
tempOrder.LoadOrder(i, lines[i]);
if (!tempOrder.hasErrors)
{
// Add valid order
orders.Add(tempOrder);
}
else
{
// Add invalid order
invalidOrders.Add(tempOrder);
logger.AddInfo("Invalid data detection in line nº: " + i.ToString());
}
}
}
catch (Exception exc)
{
// set active order in logger
logger.setActiveOrder(-1);
logger.AddException(exc);
}
// set active order in logger
logger.setActiveOrder(-1);
logger.AddInfo(string.Format("Ends of orders load process. Valid orders: {0}. Invalid orders: {1}.",
orders.Count.ToString(), invalidOrders.Count.ToString()));
}
#endregion
#region Public properties get valid & invalid orders
/// <summary>
/// Get valid orders
/// </summary>
public List<Order> getValidOrders
{
get { return orders; }
}
/// <summary>
/// Get invalids orders (data corrupted or string malformed)
/// </summary>
public List<Order> getInvalidOrders
{
get { return invalidOrders; }
}
#endregion
#region Manage Order
/// <summary>
/// Field metadata
/// </summary>
public class OrderField
{
public string fieldName; // name of the field
public DataCheck.ChecksTypes checkType; // cheks type that will pass
public System.Type dataType; // Data type
public bool mandatory; // Required data
public object value = null; // Object value
}
/// <summary>
/// Manage order
/// </summary>
public class Order
{
private Logger logger; // Logger var
List<OrderField> fieldDesc; // List of order's fields
private DataCheck check; // Checking class
/// <summary>
/// Initialize an order with fieldDesc class injection
/// </summary>
/// <param name="_logger"></param>
/// <param name="_fieldDesc"></param>
public Order(ref Logger _logger)
{
logger = _logger;
check = new DataCheck(ref logger);
// Load fields
InitializefieldDesc();
}
// todo: automatize this description load
/// <summary>
/// Initialize fields description manually
/// </summary>
private void InitializefieldDesc()
{
fieldDesc = new List<OrderField>();
fieldDesc.Add(new OrderField()
{
fieldName = "OrderId",
checkType = DataCheck.ChecksTypes.PositiveInteger,
dataType = typeof(Int32),
mandatory = true
});
fieldDesc.Add(new OrderField()
{
fieldName = "DealId",
checkType = DataCheck.ChecksTypes.PositiveInteger,
dataType = typeof(Int32),
mandatory = true
});
fieldDesc.Add(new OrderField()
{
fieldName = "Email",
checkType = DataCheck.ChecksTypes.Email,
dataType = typeof(Int32),
mandatory = true
});
fieldDesc.Add(new OrderField()
{
fieldName = "Street",
checkType = DataCheck.ChecksTypes.Street,
dataType = typeof(Int32),
mandatory = true
});
fieldDesc.Add(new OrderField()
{
fieldName = "City",
checkType = DataCheck.ChecksTypes.String,
dataType = typeof(Int32),
mandatory = true
});
fieldDesc.Add(new OrderField()
{
fieldName = "State",
checkType = DataCheck.ChecksTypes.State,
dataType = typeof(Int32),
mandatory = true
});
fieldDesc.Add(new OrderField()
{
fieldName = "ZipCode",
checkType = DataCheck.ChecksTypes.NO_CHECK,
dataType = typeof(Int32),
mandatory = true
});
fieldDesc.Add(new OrderField()
{
fieldName = "CreditCard",
checkType = DataCheck.ChecksTypes.NO_CHECK,
dataType = typeof(Int32),
mandatory = true
});
}
/// <summary>
/// Map order from string, performs check and normalizations
/// </summary>
/// <param name="idOrder"></param>
/// <param name="orderLine"></param>
public void LoadOrder(int idOrder, string orderLine)
{
string[] orderParts = orderLine.Split(',');
if (orderParts.Length != fieldDesc.Count)
{
logger.AddInvalidDataError("Order line malformed, item counts: " + orderParts.Length);
}
else
{
// Check all data, to know all the errors at the end of the mapping process
for (int i = 0; i < fieldDesc.Count; i++)
{
check.FieldDataCheck(fieldDesc[i], orderParts[i]);
}
}
}
#region Public properties: field mapping by name
// Map fields by name
public int OrderId { get { return (int)fieldDesc[0].value; } }
public int DealId { get { return (int)fieldDesc[1].value; } }
public string Email { get { return (string)fieldDesc[2].value; } }
public string Street { get { return (string)fieldDesc[3].value; } }
public string City { get { return (string)fieldDesc[4].value; } }
public string State { get { return (string)fieldDesc[5].value; } }
public string ZipCode { get { return (string)fieldDesc[6].value; } }
public string CreditCard { get { return (string)fieldDesc[7].value; } }
#endregion
/// <summary>
/// Return if there is invalid data in
/// </summary>
public bool hasErrors
{
get { return logger.thereisInvalidData; }
}
}
#endregion
#region Utilities
/// <summary>
/// Logger class for log & exceptions
/// </summary>
public class Logger
{
internal enum LogType
{
INVALID_DATA,
EXCEPTION,
INFO
} // Log's record type
// Log item struct: type and message
internal struct LogItem
{
public LogType logType;
public string message;
}
// Log dictionary to facilite access by orderId
private Dictionary<int, List<LogItem>> Log;
// active orderID
private int activeOrderId;
/// <summary>
/// Initialize logger
/// </summary>
public Logger()
{
Log = new Dictionary<int, List<LogItem>>();
}
/// <summary>
/// Get order log by id (create if not exist)
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
internal