FileReadArray issue

 

Hi friends,
I'm trying to write some info from an array into a .bin file using FileWriteArray function and then read from that file and copy the file contents into another array using FileReadArray. As I checked the MQL4 documentation, I found out that it is not necessary to define the array size when using FileReadArray and therefore I can use dynamic array when I want to use FileReadArray. The problem is that when I don't define the arraysize of the array and use a dynamic array, the code won't work properly but as soon as I define the array size for the array, it works properly.

Here it is my code:

//+------------------------------------------------------------------+
//|                                                Test 1 script.mq4 |
//|                                                        Parham.PM |
//|                                          Parham.trader@yahoo.com |
//+------------------------------------------------------------------+
#property copyright "Parham.PM"
#property link      "Parham.trader@yahoo.com"
#property version   "1.00"
#property strict
#property show_inputs

input string InpFileName="data.bin";
input string InpDirectoryName="SomeFolder";
string path=InpDirectoryName+"//"+InpFileName;
int arr[][3][5],arr_to_read[][3][5];
int row_base,sheet_base;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---

   ArrayResize(arr,10);
   //ArrayResize(arr_to_read,10);

   for(int sheet=0;sheet<ArrayRange(arr,2);sheet++)
     {
      sheet_base=(sheet+1)*100;
      for(int row=0;row<ArrayRange(arr,1);row++)
        {
         row_base=(row+1)*10;
         for(int column=0;column<ArrayRange(arr,0);column++)
           {
            arr[column][row][sheet]=sheet_base+row_base+column;
            Print("arr[",column,"][",row,"][",sheet,"]: ",arr[column][row][sheet]);
           }
        }
     }

   WriteData();

   ReadData();

   Print("After ReadData:");
   Print("column arr_to_read: ",ArrayRange(arr_to_read,0)
         ,"\nrow arr_to_read: ",ArrayRange(arr_to_read,1)
         ,"\nsheet arr_to_read: ",ArrayRange(arr_to_read,2));

   Print("column arr: ",ArrayRange(arr,0)
         ,"\nrow arr: ",ArrayRange(arr,1)
         ,"\nsheet arr: ",ArrayRange(arr,2));

   for(int sheet=0;sheet<ArrayRange(arr_to_read,2);sheet++)
     {
      for(int row=0;row<ArrayRange(arr_to_read,1);row++)
        {
         for(int column=0;column<ArrayRange(arr_to_read,0);column++)
           {
            Print("arr_to_read[",column,"][",row,"][",sheet,"]: ",arr_to_read[column][row][sheet]);
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Write n elements of the array to file                            |
//+------------------------------------------------------------------+
void WriteData()
  {
//--- open the file
   ResetLastError();
   int handle=FileOpen(path,FILE_READ|FILE_WRITE|FILE_BIN);
   if(handle!=INVALID_HANDLE)
     {
      //--- write array data to the end of the file
      FileSeek(handle,0,SEEK_END);
      FileWriteArray(handle,arr,0,WHOLE_ARRAY);
      //--- close the file
      FileClose(handle);
     }
   else
      Print("Failed to open the file, error ",GetLastError());
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ReadData()
  {
   ResetLastError();
   int file_handle=FileOpen(path,FILE_READ|FILE_BIN);
   if(file_handle!=INVALID_HANDLE)
     {
      //--- read all data from the file to the array
      Alert(FileReadArray(file_handle,arr_to_read));

      //--- close the file
      FileClose(file_handle);
     }
   else
      Print("File open failed, error ",GetLastError());
  }
//+------------------------------------------------------------------+

Your kind guidance is highly appreciated.

 
parham.trader:

The problem is that when I don't define the arraysize of the array and use a dynamic array, the code won't work properly but as soon as I define the array size for the array, it works properly.

Show us actual behavior versus expected behavior. Every problem description needs to contain at least this information, without it no one might be able to help you.

 
lippmaje:

Show us actual behavior versus expected behavior. Every problem description needs to contain at least this information, without it no one might be able to help you.

To be fair, OP has posted a full script. 

 
lippmaje:

Show us actual behavior versus expected behavior. Every problem description needs to contain at least this information, without it no one might be able to help you.

I didn't get what you mean. I send the whole code and I think it is clear what I'm looking for.

let me explain my problem again thoroughly:

HERE IS WHAT I WANT TO DO ==> I want to copy a .bin file which contains the contents of a dynamic array named "arr", into another dynamic array (named "arr_to_read). Suppose that when I want to use the function FileReadArray to copy the file contents into the new array (named "arr_to_read") I do not know the number of columns of the "arr" that was previously saved in the .bin file, therefore I have to use a dynamic type array (named "arr_to_read") to do so.

HERE IS MY PROBLEM ==> Now the problem is that when I use FileReadArray to copy the .bin file contents in the dynamic array (named "arr_to_read"), the array resize properly to the size of the array copied previously in the .bin file (in my example the array size was 10) BUT the .bin file contents can not be copied in the "arr_to_read" properly.

I hope I could clarify my problem to you correctly.

Thanking in advance for your guidance. 

 

I myself found a solution to the issue which is using the "FileReadArray(file_handle,arr_to_read)" twice so that for the first use it resize the destination array ("arr_to_read") properly and on the second use it copy the .bin file contents in the destination array ("arr_to_read") properly. Below you can find my code:

//+------------------------------------------------------------------+
//|                                                Test 1 script.mq4 |
//|                                                        Parham.PM |
//|                                          Parham.trader@yahoo.com |
//+------------------------------------------------------------------+
#property copyright "Parham.PM"
#property link      "Parham.trader@yahoo.com"
#property version   "1.00"
#property strict
#property show_inputs

input string InpFileName="data.bin";
input string InpDirectoryName="SomeFolder";
string path=InpDirectoryName+"//"+InpFileName;
int arr[][3][5],arr_to_read[][3][5];
int row_base,sheet_base;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---

   ArrayResize(arr,10);
   //ArrayResize(arr_to_read,10);

   for(int sheet=0;sheet<ArrayRange(arr,2);sheet++)
     {
      sheet_base=(sheet+1)*100;
      for(int row=0;row<ArrayRange(arr,1);row++)
        {
         row_base=(row+1)*10;
         for(int column=0;column<ArrayRange(arr,0);column++)
           {
            arr[column][row][sheet]=sheet_base+row_base+column;
            Print("arr[",column,"][",row,"][",sheet,"]: ",arr[column][row][sheet]);
           }
        }
     }

   WriteData();

   ReadData();

   Print("After ReadData:");
   Print("column arr_to_read: ",ArrayRange(arr_to_read,0)
         ,"\nrow arr_to_read: ",ArrayRange(arr_to_read,1)
         ,"\nsheet arr_to_read: ",ArrayRange(arr_to_read,2));

   Print("column arr: ",ArrayRange(arr,0)
         ,"\nrow arr: ",ArrayRange(arr,1)
         ,"\nsheet arr: ",ArrayRange(arr,2));

   for(int sheet=0;sheet<ArrayRange(arr_to_read,2);sheet++)
     {
      for(int row=0;row<ArrayRange(arr_to_read,1);row++)
        {
         for(int column=0;column<ArrayRange(arr_to_read,0);column++)
           {
            Print("arr_to_read[",column,"][",row,"][",sheet,"]: ",arr_to_read[column][row][sheet]);
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Write n elements of the array to file                            |
//+------------------------------------------------------------------+
void WriteData()
  {
//--- open the file
   ResetLastError();
   int handle=FileOpen(path,FILE_READ|FILE_WRITE|FILE_BIN);
   if(handle!=INVALID_HANDLE)
     {
      //--- write array data to the end of the file
      FileSeek(handle,0,SEEK_END);
      FileWriteArray(handle,arr,0,WHOLE_ARRAY);
      //--- close the file
      FileClose(handle);
     }
   else
      Print("Failed to open the file, error ",GetLastError());
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ReadData()
  {
   ResetLastError();
   int file_handle=FileOpen(path,FILE_READ|FILE_BIN);
   if(file_handle!=INVALID_HANDLE)
     {
      //--- read all data from the file to the array 

      Alert("First try result: ",FileReadArray(file_handle,arr_to_read));

      Alert("Second try result: ",FileReadArray(file_handle,arr_to_read));

      //--- close the file
      FileClose(file_handle);
     }
   else
      Print("File open failed, error ",GetLastError());
  }
//+------------------------------------------------------------------+
But frankly speaking, I don't find it as logical as I want.
 

Without your output it is difficult to follow your problem.

You have posted full code, that is fine, but in order to get the output it would be required to compile and run your code, then make a guess of what you might have wanted as desired output.

Could even be that it works nice here with my build, but on yours doesn't. How would we now what you experienced if you withhold this information?

Now, to your topic, look at the place where you write your array into the file. Notice the file seek? You are appending your array to the file content. But in the function where you read it in, you are reading the array from the beginning of the file. That is you never get the latest array you've written. And this is why it probably worked with reading twice. The first array version was some crap from a previous try, the second now had the right content. In order to fix this you either need to reset the file contents when writing, or seek to the file end when reading (that is, read arrays as long as you can and keep the last one.)

 
lippmaje:

Without your output it is difficult to follow your problem.

You have posted full code, that is fine, but in order to get the output it would be required to compile and run your code, then make a guess of what you might have wanted as desired output.

Could even be that it works nice here with my build, but on yours doesn't. How would we now what you experienced if you withhold this information?

Now, to your topic, look at the place where you write your array into the file. Notice the file seek? You are appending your array to the file content. But in the function where you read it in, you are reading the array from the beginning of the file. That is you never get the latest array you've written. And this is why it probably worked with reading twice. The first array version was some crap from a previous try, the second now had the right content. In order to fix this you either need to reset the file contents when writing, or seek to the file end when reading (that is, read arrays as long as you can and keep the last one.)

Thank you so much for your kind guidance,

As you correctly pointed, I changed the file pointer in the WriteData function from "SEEK_END" to "SEEK_SET" so that the array would always be copied from the beginning of the file and not appending the array to the file from the end of the file.

I also set the file pointer in the ReadData function at the beginning of the file using the "FileSeek(file_handle,0,SEEK_SET)". BUT I'm still facing with the same issue that with the first try of the "FileReadArray(file_handle,arr_to_read)" it doesn't copy the file content successfully in the array but with the second try it works properly.

 
parham.trader:

Thank you so much for your kind guidance,

As you correctly pointed, I changed the file pointer in the WriteData function from "SEEK_END" to "SEEK_SET" so that the array would always be copied from the beginning of the file and not appending the array to the file from the end of the file.

I also set the file pointer in the ReadData function at the beginning of the file using the "FileSeek(file_handle,0,SEEK_SET)". BUT I'm still facing with the same issue that with the first try of the "FileReadArray(file_handle,arr_to_read)" it doesn't copy the file content successfully in the array but with the second try it works properly.

If you intend to overwrite the file there is no need to use FileSeek. By default array will be written from the beginning of file overwriting previous contents and will be read from the beginning as well. Check the return value of FileReadArray and last error.

 
parham.trader:

I myself found a solution to the issue which is using the "FileReadArray(file_handle,arr_to_read)" twice so that for the first use it resize the destination array ("arr_to_read") properly and on the second use it copy the .bin file contents in the destination array ("arr_to_read") properly. Below you can find my code:

But frankly speaking, I don't find it as logical as I want.

Any other idea about the issue ?!

 
parham.trader:

Any other idea about the issue ?!

Apparently the FileReadArray function cannot handle multi-dimensional arrays well. I tried using a single dimensional array, and one FileReadArray is enough to get all the data out. Once I increase to two dimension, the same problem comes. And when I print the error code, it says 4053 - ERR_SOME_ARRAY_ERROR, which is VERY INFORMATIVE... LOL

You can make your code nicer (somewhat) if u repeat the read only when the previous one returns error 4053... which, it appears, is only causing slight inconvenience at the moment.

 
Maybe you should point this out to MetaQuotes so they can fix it.
Reason: