MQLArticles/Utils/File.mqh

498 lines
30 KiB
MQL5
Raw Permalink Normal View History

2025-09-22 09:08:13 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
string get_header(string _filename)
{
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
string header = FileReadString(_fh);
FileClose(_fh);
return header;
}
//+------------------------------------------------------------------+
int numero_lineas_csv(string _filename)
{
int lineas = 0;
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
while(!FileIsEnding(_fh))
{
FileReadString(_fh);
lineas++;
}
FileClose(_fh);
return lineas;
}
//+------------------------------------------------------------------+
int numero_columnas_csv(string _filename)
{
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
string linea = FileReadString(_fh);
string columnas[];
StringSplit(linea, ',', columnas);
FileClose(_fh);
return ArraySize(columnas);
}
//+------------------------------------------------------------------+
matrix cargar_atributos_csv(string _filename, string &out_cabezera, int num_clases = 1)
{
int num_columnas = numero_columnas_csv(_filename);
int num_lineas = numero_lineas_csv(_filename);
matrix atributos(num_lineas - 1, num_columnas - num_clases);
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
if(_fh == INVALID_HANDLE)
{
Print(__FUNCTION__, "::Error: No se pudo abrir el archivo ", _filename);
return atributos;
}
// Leer cabecera (ignorar)
out_cabezera = FileReadString(_fh);
int index = 0;
while(!FileIsEnding(_fh))
{
string linea = FileReadString(_fh);
if(StringLen(linea) == 0) // Ignorar l<EFBFBD>neas vac<EFBFBD>as
continue;
string datos[];
StringSplit(linea, ',', datos);
// Validar si la l<EFBFBD>nea tiene el n<EFBFBD>mero esperado de columnas
if(ArraySize(datos) != num_columnas)
{
Print("Advertencia: L<00>nea mal formada en archivo CSV: ", linea);
continue;
}
vector atributos_linea(num_columnas - num_clases);
for(int i = 0; i < num_columnas - num_clases; i++)
atributos_linea.Set(i, StringToDouble(datos[i]));
atributos.Row(atributos_linea, index);
index++;
}
FileClose(_fh);
return atributos;
}
//+------------------------------------------------------------------+
//| Funci<EFBFBD>n para extraer una columna de un CSV |
//+------------------------------------------------------------------+
string ExtractCSVColumn(string file_name, int col_index, ushort separator = ',')
{
string result = "";
string sym = ShortToString(separator);
// Abrir el archivo CSV en modo lectura
int handle = FileOpen(file_name, FILE_READ | FILE_CSV);
if(handle == INVALID_HANDLE)
{
Print(__FUNCTION__, "::Error al abrir el archivo: ", file_name);
return "";
}
// Leer el archivo l<EFBFBD>nea por l<EFBFBD>nea hasta el final
while(!FileIsEnding(handle))
{
string line = FileReadString(handle);
// Dividir la l<EFBFBD>nea por comas en un arreglo de strings
string columns[];
int count = StringSplit(line, separator, columns);
// Verificar que la columna deseada exista en esta l<EFBFBD>nea
if(count > col_index)
{
// Si ya hay contenido en 'result', se a<EFBFBD>ade una coma como separador
if(result != "")
result += sym;
result += columns[col_index];
}
}
FileClose(handle);
return result;
}
//+------------------------------------------------------------------+
matrix cargar_clases_csv(string _filename, int num_clases = 1)
{
int num_columnas = numero_columnas_csv(_filename);
int num_lineas = numero_lineas_csv(_filename);
matrix clases(num_lineas - 1, num_clases);
int _fh = FileOpen(_filename, FILE_ANSI | FILE_COMMON | FILE_CSV | FILE_READ, "\n");
FileReadString(_fh);
int index = 0;
while(!FileIsEnding(_fh))
{
vector clases_linea(num_clases);
string linea = FileReadString(_fh);
string datos[];
StringSplit(linea, ',', datos);
for(int i = 0; i < num_clases; i++)
{
clases_linea.Set(i, StringToDouble(datos[num_columnas - num_clases + i]));
}
clases.Row(clases_linea, index);
index++;
}
FileClose(_fh);
return clases;
}
//+------------------------------------------------------------------+
struct file_data_csv
{
private:
string file_cabezera;
int file_handle;
string file_name;
bool create;
public:
void Create(string new_file_name, string cabezera, int open_flags = FILE_WRITE | FILE_CSV | FILE_COMMON)
{
this.file_name = new_file_name;
this.file_cabezera = cabezera;
this.file_handle = FileOpen(this.file_name, open_flags);
create = true;
if(this.file_handle == INVALID_HANDLE)
{
Print(__FUNCTION__"::Error al abrir el archivo: ", this.file_name, ", ultimo error: ", GetLastError());
}
FileWrite(this.file_handle, cabezera);
};
inline string GetFileName()
{
return this.file_name;
}
inline void Close()
{
FileClose(this.file_handle);
}
inline void Write(string text)
{
FileWrite(this.file_handle, text);
}
};
//+------------------------------------------------------------------+
void DeleteFileWithChecks(string fileName, int commonFlag = FILE_COMMON)
{
ResetLastError();
// Comprobar si el archivo existe en la ubicaci<EFBFBD>n especificada
if(FileIsExist(fileName, commonFlag))
{
// Intentar eliminar el archivo
if(FileDelete(fileName, commonFlag))
{
// Confirmaci<EFBFBD>n de que el archivo fue eliminado
Print("Archivo '", fileName, "' eliminado correctamente.");
}
else
{
// Informar del error al intentar eliminar el archivo
int errCode = GetLastError();
Print("Error al eliminar el archivo '", fileName, "'. C<00>digo de error: ", errCode);
}
}
else
{
// El archivo no existe, informar al usuario
Print("El archivo '", fileName, "' no existe en la ubicaci<00>n especificada.");
}
}
// Funci<EFBFBD>n para cambiar el nombre de un archivo en la carpeta de datos comunes o local
void RenameFileWithChecks(const string oldFileName, int commonFlag, const string newFileName, int modeFlags)
{
// Comprobar si el archivo original existe
if(FileIsExist(oldFileName, commonFlag))
{
// Intentar cambiar el nombre del archivo
if(FileMove(oldFileName, commonFlag, newFileName, modeFlags))
{
// Confirmaci<EFBFBD>n de que el nombre del archivo fue cambiado
Print("El archivo '", oldFileName, "' ha sido renombrado a '", newFileName, "' correctamente.");
}
else
{
// Informar del error al intentar cambiar el nombre del archivo
int errCode = GetLastError();
Print("Error al cambiar el nombre del archivo de '", oldFileName, "' a '", newFileName, "'. C<00>digo de error: ", errCode);
}
}
else
{
// El archivo no existe, informar al usuario
Print("El archivo '", oldFileName, "' no existe en la ubicaci<00>n especificada.");
}
}
struct Filas
{
string datos[];
};
struct CSV
{
Filas data[];
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CSVToArray(const string &fileName, bool common_flag, CSV &file, ushort line_separator, uint code_page = CP_ACP)
{
// Limpia el array existente
ArrayResize(file.data, 0);
int flags = common_flag ? FILE_COMMON : 0;
// Verifica que el archivo exista
if(!FileIsExist(fileName, flags))
{
printf("%s:: El archivo %s no existe", __FUNCTION__, fileName);
return false; // Sale de la funci<EFBFBD>n si el archivo no existe
}
flags = !common_flag ? (FILE_READ | FILE_CSV) : (FILE_READ | FILE_CSV | FILE_COMMON);
ResetLastError();
// Abre el archivo en modo lectura
const int fileHandle = FileOpen(fileName, flags, "\n", code_page);
if(fileHandle == INVALID_HANDLE)
{
Print(__FUNCTION__, ":: Error al abrir el archivo: ", fileName, " | ultimo error: ", GetLastError());
return false; // Sale de la funci<EFBFBD>n si no se puede abrir el archivo
}
// Lee el archivo l<EFBFBD>nea por l<EFBFBD>nea
while(!FileIsEnding(fileHandle))
{
const string line = FileReadString(fileHandle);
if(StringLen(line) > 0)
{
ArrayResize(file.data, file.data.Size() + 1);
string linea[];
StringSplit(line, line_separator, linea);
ArrayResize(file.data[file.data.Size() - 1].datos, linea.Size());
for(int i = 0; i < ArraySize(linea) ; i++)
file.data[file.data.Size() - 1].datos[i] = linea[i];
}
}
// Cierra el archivo
printf("%s:: Exito al cargar el archivo %s, numero de filas %d", __FUNCTION__, fileName, ArraySize(file.data));
FileClose(fileHandle);
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
string StringTrim(const string text)
{
int start = 0;
int end = StringLen(text) - 1;
while(start <= end && StringGetCharacter(text, start) <= ' ')
start++;
while(end >= start && StringGetCharacter(text, end) <= ' ')
end--;
if(start > end)
return "";
return StringSubstr(text, start, end - start + 1);
}
//+------------------------------------------------------------------+
string vector_to_string(const vector &v, string separator = ",")
{
string vector_str = "";
ulong length = v.Size();
for(ulong i = 0; i < length; i++)
vector_str += DoubleToString(v[i], 14) + (i == length - 1 ? "" : separator);
return vector_str;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
vector string_to_vector(const string str, ushort separator = ',')
{
string valores_linea[];
StringSplit(str, separator, valores_linea);
int num_valores = ArraySize(valores_linea);
vector v(num_valores);
for(int i = 0; i < num_valores; i++)
v[i] = StringToDouble(valores_linea[i]);
return v;
}
//---
// Convierte un CSV en una matriz, opcionalmente saltando la cabecera
bool CSVToMatrix(string fileName,
matrix& out_mtx,
bool common_flag,
bool file_have_header,
ushort line_separator,
string &out_header)
{
// Limpia el array existente
out_mtx.Resize(0, 0);
// Verifica que el archivo exista
int flags = common_flag ? FILE_COMMON : 0;
if(!FileIsExist(fileName, flags))
{
Print(__FUNCTION__, ":: El archivo ", fileName, " no existe");
return false;
}
ResetLastError();
// Abre el archivo en modo lectura CSV
flags = common_flag == false ? (FILE_READ | FILE_CSV) : (FILE_READ | FILE_CSV | FILE_COMMON);
int fileHandle = FileOpen(fileName, flags, "\n");
if(fileHandle == INVALID_HANDLE)
{
Print(__FUNCTION__, ":: Error al abrir el archivo: ", fileName, " | ultimo error: ", GetLastError());
return false;
}
// Si hay cabecera y no estamos al final, la leemos y descartamos
if(file_have_header && !FileIsEnding(fileHandle))
{
out_header =FileReadString(fileHandle);
}
int cols = 0;
// Lee el resto del archivo l<EFBFBD>nea por l<EFBFBD>nea
while(!FileIsEnding(fileHandle))
{
string line = FileReadString(fileHandle);
if(StringLen(line) == 0) // omite l<EFBFBD>neas vac<EFBFBD>as
continue;
// A<EFBFBD>ade una nueva fila a out_mtx
out_mtx.Resize(out_mtx.Rows() + 1, out_mtx.Cols());
int row = (int)out_mtx.Rows() - 1;
// Divide la l<EFBFBD>nea seg<EFBFBD>n el separador
string fields[];
StringSplit(line, line_separator, fields);
// Ajusta el n<EFBFBD>mero de columnas y asigna los valores
if(cols == 0)
{
out_mtx.Resize(out_mtx.Rows(), ArraySize(fields));
cols = ArraySize(fields);
}
vector v(ArraySize(fields));
if(v.Size() != cols)
{
printf("%s: Error critico la linea %s\n Es invalida el numero de columnas de esa fila es diferente a %I32d", __FUNCTION__, line, cols);
continue;
}
for(int i = 0; i < ArraySize(fields); i++)
v[i] = StringToDouble(fields[i]);
out_mtx.Row(v, row);
}
// Cierra el archivo y retorna <EFBFBD>xito
FileClose(fileHandle);
return true;
}
bool MatrixToCSV(string fileName,
matrix &mtx,
bool common_flag,
string header,
ushort line_separator = ',')
{
int flags = FILE_WRITE | FILE_CSV;
if(common_flag)
flags |= FILE_COMMON;
// Abrir el archivo
int file = FileOpen(fileName, flags, "\n");
if(file == INVALID_HANDLE)
{
Print(__FUNCTION__, " Error al abrir el archivo CSV: ", fileName);
return false;
}
// Escribir encabezado si se proporciona
if(StringLen(header) > 0)
FileWriteString(file, header + "\n");
// Obtener dimensiones
int rows = (int)mtx.Rows();
int cols = (int)mtx.Cols();
// Escribir los datos
for(int i = 0; i < rows; i++)
{
string line = "";
for(int j = 0; j < cols; j++)
{
if(j > 0) line += ShortToString(line_separator);
line += DoubleToString(mtx[i][j], 8);
}
FileWriteString(file, line + "\n");
}
FileClose(file);
Print(__FUNCTION__, " Exportaci<00>n completada: ", fileName);
return true;
}
//+------------------------------------------------------------------+
//| Extrae columnas especificadas de una matriz |
//+------------------------------------------------------------------+
matrix ExtraerMaxtriDeMatrix(const matrix &m, ulong start_col, ulong end_col)
{
matrix out = { };
// Verifica rangos v<EFBFBD>lidos
if(start_col < 0 || end_col >= m.Cols() || start_col > end_col)
{
Print(__FUNCTION__, " Error: <00>ndices de columna inv<00>lidos.");
return m; // retorna matriz vac<EFBFBD>a
}
// N<EFBFBD>mero de filas y columnas que tendr<EFBFBD> la nueva matriz
ulong rows = m.Rows();
printf("%s | Numero de columnas totales %I64u | Start %I64u | End %I64u", __FUNCTION__, m.Cols(), start_col, end_col);
// Copia los datos desde la matriz original a la matriz resultado
for(ulong i = start_col ; i <= end_col; i++)
{
out.Resize(rows, out.Cols() + 1);
vector c = m.Col(i);
out.Col(c, out.Cols() - 1);
}
return out;
}
//+------------------------------------------------------------------+