forked from nique_372/MQLArticles
451 lines
No EOL
26 KiB
MQL5
451 lines
No EOL
26 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| File.mqh |
| |
//| Copyright 2025, Niquel Mendoza. |
| |
//| https://www.mql5.com |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright 2025, Niquel Mendoza."
| |
#property link "https://www.mql5.com/es/users/nique_372/news"
| |
#property strict
| |
| |
#ifndef MQLARTICLES_UTILS_FILE_MQH
| |
#define MQLARTICLES_UTILS_FILE_MQH
| |
| |
//+------------------------------------------------------------------+
| |
//| Csv |
| |
//+------------------------------------------------------------------+
| |
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);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Data del 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ínea por línea hasta el final
| |
while(!FileIsEnding(handle))
| |
{
| |
string line = FileReadString(handle);
| |
| |
// Dividir la lí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ínea
| |
if(count > col_index)
| |
{
| |
// Si ya hay contenido en 'result', se añade una coma como separador
| |
if(result != "")
| |
result += sym;
| |
result += columns[col_index];
| |
}
| |
}
| |
| |
FileClose(handle);
| |
return result;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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ón especificada
| |
if(FileIsExist(fileName, commonFlag))
| |
{
| |
// Intentar eliminar el archivo
| |
if(FileDelete(fileName, commonFlag))
| |
{
| |
// Confirmació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ódigo de error: ", errCode);
| |
}
| |
}
| |
else
| |
{
| |
// El archivo no existe, informar al usuario
| |
Print("El archivo '", fileName, "' no existe en la ubicación especificada.");
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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ó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ódigo de error: ", errCode);
| |
}
| |
}
| |
else
| |
{
| |
// El archivo no existe, informar al usuario
| |
Print("El archivo '", oldFileName, "' no existe en la ubicació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ó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ón si no se puede abrir el archivo
| |
}
| |
| |
// Lee el archivo línea por lí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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
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ínea por línea
| |
while(!FileIsEnding(fileHandle))
| |
{
| |
string line = FileReadString(fileHandle);
| |
if(StringLen(line) == 0) // omite líneas vacías
| |
continue;
| |
| |
// Añ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ínea según el separador
| |
string fields[];
| |
StringSplit(line, line_separator, fields);
| |
| |
| |
// Ajusta el nú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 é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ón completada: ", fileName);
| |
return true;
| |
}
| |
| |
| |
//+------------------------------------------------------------------+
| |
matrix ExtraerMaxtriDeMatrix(const matrix &m, ulong start_col, ulong end_col)
| |
{
| |
matrix out = { };
| |
| |
// Verifica rangos válidos
| |
if(start_col < 0 || end_col >= m.Cols() || start_col > end_col)
| |
{
| |
Print(__FUNCTION__, " Error: índices de columna inválidos.");
| |
return m; // retorna matriz vacía
| |
}
| |
| |
// Número de filas y columnas que tendrá 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;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
void FolderRemoveBarraInvertida(string& folder_name)
| |
{
| |
const int lenght = StringLen(folder_name);
| |
if(folder_name[lenght - 1] == '\\')
| |
folder_name = StringSubstr(folder_name, 0, (lenght - 1));
| |
}
| |
//+------------------------------------------------------------------+
| |
#endif // MQLARTICLES_UTILS_FILE_MQH |