FileWriteArray: Что он пишет в начале файла?

 
struct Bar
{
   double O;
   double H;
   double L;
   double C;
   int DT; 
};
Bar Bares[];
Bar bar[1];
............
      int size = CopyRates(symbolValue[0], timeframeValue[0], startpose[0], count[0], Mtbars);
      ArrayResize(Bares, size);
      for (i = 0; i < size; i++)
      {
         Bares[i].O = Mtbars[i].open;
         Bares[i].H = Mtbars[i].high;
         Bares[i].L = Mtbars[i].low;
         Bares[i].C = Mtbars[i].close;
         Bares[i].DT = Mtbars[i].time;
      }
..........
bool pipewriteBarArray(Bar &s[])
{
   FileFlush(ExtPipe);
   FileSeek(ExtPipe,0,SEEK_SET);
   uint size = ArraySize(s); 
   pipewrite(IntegerToString(size));
   
   if(FileWriteArray(ExtPipe, s, 0, WHOLE_ARRAY) < size)
........

Передаю с помощью FileWriteArray массив структур Bar. Пишу в Pipe.

Перед передачей массива  FileWriteArray(ExtPipe, s, 0, WHOLE_ARRAY)
передаю размер массива pipewrite(IntegerToString(size)); своей функцией

Читаю из проги  на C#

        BinaryReader br;

.....................
                ret = new List<TBar>[2];
                ret[0] = new List<TBar>();
                ret[1] = new List<TBar>();
                try
                {
                    br.ReadDouble();//какая-то хрень написана в первых байтах
                    for (int i = 0; i < size; i++)
                    {
                        bar = new TBar();
                        bar.Open = br.ReadDouble();
                        bar.High = br.ReadDouble();
                        bar.Low = br.ReadDouble();
                        bar.Close = br.ReadDouble();
                        bar.DT = MtApiTimeConverter.ConvertFromMtTime(br.ReadInt32());
                        bar.X = bar.Bar = size - i - 1;
                        ret[0].Insert(0, bar);//массив в МТ задом наперед, поэтому вставляем всегда в начало
                        bar1 = new TBar(bar, true);
                        ret[1].Insert(0, bar1);

 Так вот, при чтении в первых байтах записано что-то, но не первый член структуры первого члена массива, а нечто мне не известное.

Поясните, плиз, что пишет  FileWriteArray в начале файла?

 

Когда пишутся 5 тысяч бар, помогает прочитать/пропустить первые 8 байт. Дальше правильно считывается массив структуры.

Если 200 с копейками баров, то пропуск первых 8-ми байт приводит к тому, что на чтение последнего элемента последнего члена массива не хватает байт в файле. Если пропустить первые 4 байта - то криво читаются бары.

В общем, в начале что-то записано размером в 8 байт, если массив баров от 200 с копейками до 5000. И больше 4, но меньше 8 байт, если массив 200 с лишним баров.

Пишется что-то плавающей длины. 

 
В доках нет ни слова о структуре файла после записи, значит нет никаких гарантий. Может размер, может признак таймсерии, а может завтра ещё что-нибудь добавят. Я бы формировал файл самостоятельно через FileWriteStruct.
 

Что за функция перед вызовом FileWriteArray?

pipewrite(IntegerToString(size));
 
stringo:

Что за функция перед вызовом FileWriteArray?

Отправляет размер массива. И в проге считывается до чтения массива. Отправляется в виде string. Перед ним передается длина этой string целым числом. В проге считывается соответственно. Хвостов не должно оставаться - это стандартный способ обмена, всегда работает без проблем.

 

В общем, при размере массива из 256 баров (по 36 байт каждый), перед массивом пишется 7 байт чего-то... Когда больше - 8.

256 - это у меня так попалось. Четкой границы перехода с 8 на 7 байт не знаю. 

 
Pavlick:
В доках нет ни слова о структуре файла после записи, значит нет никаких гарантий. Может размер, может признак таймсерии, а может завтра ещё что-нибудь добавят. Я бы формировал файл самостоятельно через FileWriteStruct.
А FileWriteStruct ниче лишнего не пишет?
 
AKC:
А FileWriteStruct ниче лишнего не пишет?
Нет
 
AKC:

Отправляет размер массива. И в проге считывается до чтения массива. Отправляется в виде string. Перед ним передается длина этой string целым числом. В проге считывается соответственно. Хвостов не должно оставаться - это стандартный способ обмена, всегда работает без проблем.

 

В общем, при размере массива из 256 баров (по 36 байт каждый), перед массивом пишется 7 байт чего-то... Когда больше - 8.

256 - это у меня так попалось. Четкой границы перехода с 8 на 7 байт не знаю. 

Похоже, это таки мой хвост. После запроса длины массива. 4 байта - целое, длина стринга. И плюс длина стринга, в которой число - размер массива.

 

Так что это мой косяк!

Спасибо за помощь! 

 
AKC:

Отправляет размер массива. И в проге считывается до чтения массива. Отправляется в виде string. Перед ним передается длина этой string целым числом. В проге считывается соответственно. Хвостов не должно оставаться - это стандартный способ обмена, всегда работает без проблем.

 

В общем, при размере массива из 256 баров (по 36 байт каждый), перед массивом пишется 7 байт чего-то... Когда больше - 8.

256 - это у меня так попалось. Четкой границы перехода с 8 на 7 байт не знаю. 

Получается мешанина из форматов - текстовый и бинарный.

Запишите вместо <длина строки целым число><строка произвольной длины><массив структур>

<размер массива целым числом><массив структур>

Со структурой я бы тоже немного поработал. Дату-время в структуре представить не в виде int32(int), а в виде int64(long), тем более, что тип datetime в MQL4 - 8-байтовый. В таком случае размер структуры будет кратным 8 и все её члены во всех элементах массива всегда будут выровнены на границу 8

 

Советы правильные. С датой так и сделаю. Просто подстраивался под то, что уже было в программе.

"Запишите вместо <длина строки целым число><строка произвольной длины><массив структур>

<размер массива целым числом><массив структур>"  - у меня строится полноценное API , <длина строки целым число><строка произвольной длины> - это стандартный "протокол" обмена. Менять пока не вижу смысла. В советнике около 4 тысяч строк, в API не меньше.

Вообще, на самом деле текстового формата нет. Все передается в бинарном потоке. Просто "протокол" идет строками. А массив в строку не зашьешь, поэтому он как-бы идет вне протокола. 

Я по-другому вышел из положения:

            int u;

                        u = br.ReadInt32();//в пайпе остается ответ от запроса длины массива: int - размер string
                        br.ReadBytes(u);//и string - длина в виде строки

 Таким образом сдвигаю указатель на конец ответа с длиной массива, и потом начинаю читать сам массив.

Причина обращения: