Способы хранения информации: текстовый и двоичный

Как мы видели во многих предыдущих разделах, одна и та же информация может быть представлена в текстовом и двоичном виде. Например, числа форматов int, long, double, дата и время (datetime) или цвет (color) хранятся в памяти как последовательность байтов определенной длины. Этот способ компактный и хорошо подходит для интерпретации компьютером, но для человека удобнее анализировать информацию в текстовом виде, хотя он и длиннее. Поэтому мы уделили много внимания преобразованию чисел в строки и обратно и функциям для работы со строками.

На уровне файлов разделение на двоичное и текстовое представление данных тоже сохраняется. Двоичный файл предназначен для хранения данных в том же внутреннем представлении, какое используется в памяти. Текстовый файл содержит строковое представление.

Текстовые файлы обычно используются для стандартных форматов, таких как CSV (Comma Separated Values), JSON (JavaScript Object Notation), XML (Extensible Markup Language), HTML (HyperText Markup Language).

Двоичные (или по-другому, бинарные) файлы, конечно, тоже имеют стандартные форматы для многих применений, в частности, для изображений (PNG, GIF, JPG, BMP), звуков (WAV, MP3) или сжатых архивов (ZIP). Однако бинарный формат изначально предполагает большую закрытость и низкоуровневую работу с данными и потому чаще применяется для решения внутренних задач, когда важна лишь эффективность хранения и доступность данных для конкретной программы. Иными словами, объекты любых прикладных структур и классов могут легко сохранять и восстанавливать свое состояние в двоичном файле, фактически делая слепок памяти и не заботясь о совместимости с каким-либо стандартом.

В принципе, мы могли бы вручную конвертировать данные в строки при записи в двоичный файл и затем обратно преобразовывать их из строк в числа (или структуры, или массивы) при чтении файла. Это стало бы аналогом того, что для нас автоматически предоставляет режим текстовых файлов, но требовало бы дополнительных усилий. Режим текстового файла избавляет нас от подобной рутины. И более того, файловая подсистема MQL5 выполняет неявным образом несколько дополнительных, но важных операций, которые необходимы при работе с текстом.

Во-первых, понятие текста основывается на неких общеупотребительных правилах использования символов-разделителей. В частности, подразумевается, что все тексты состоят из строк — так их удобнее читать и анализировать алгоритмически. Следовательно, существуют специальные символы, отделяющие одну строку от другой.

Здесь нас ожидают первые сложности, связанные с тем, что в разных операционных системах приняты различные комбинации этих символов. В Windows разделителем строк является последовательность двух символов '\r\n' (или в виде шестнадцатеричных кодов: 0xD 0xA, или в виде названия CRLF, которое расшифровывается как возврат каретки ("Carriage Return") и перевод строки ("Line Feed")). В Unix и Linux стандартом является единичный символ '\n', а в некоторых версиях и программах под MacOS может использоваться единичный символ '\r'.

Хотя MetaTrader 5 работает под Windows, у нас нет гарантии, что какой-либо полученный текстовый файл не будет сохранен с "непривычными" разделителями. Если бы мы его читали в двоичном режиме и сами проверяли на наличие разделителей, чтобы сформировать строки, указанные разночтения потребовали бы специфической обработки. А текстовый режим работы файлов в MQL5 приходит здесь на помощь: он автоматически нормализует переводы строк при чтении и записи.

Нужно помнить, что MQL5 обеспечивает исправление переносов строк не во всех случаях. В частности, одиночный символ '\r' не будет при чтении текстового файла интерпретирован как '\r\n'. В отличие от этого, одиночный '\n' правильно воспринимается как '\r\n'.

Во-вторых, строки могут храниться в памяти в нескольких представлениях. По-умолчанию строка (тип string) состоит в MQL5 из двухбайтовых символов. Это обеспечивает поддержку универсальной кодировки Unicode, которая хороша тем, что включает в себя все национальные алфавиты. Однако во многих случаях такой "интернационал" не требуется (например, при хранении чисел или англоязычных сообщений), и тогда экономнее использовать строки из однобайтовых символов в той или иной кодировке ANSI. Функции MQL5 API позволяют выбирать для файлов в текстовом режиме предпочтительный способ записи строк. Однако, если в своей MQL-программе мы сами контролируем запись и можем гарантировать обоснованность и надежность переключения с Unicode на однобайтовые символы, то при интеграции с неким внешним программным обеспечением или веб-сервисом, кодовая страница ANSI в его файлах может быть любой. В связи с этим, возникает следующий пункт.

В-третьих, из-за наличия множества национальных языков нужно быть готовым к текстам в различных ANSI-кодировках. Без правильной интерпретации кодировки текст может быть записан или прочитан с искажениями или вовсе стать нечитаемым. Мы видели это в разделе Работа с символами и кодовыми страницами. Поэтому файловые функции уже включают в себя средства для корректной обработки символов: достаточно лишь указать в параметрах желаемую или ожидаемую кодировку. О выборе кодировки более подробно рассказано в отдельном разделе.

Наконец, в-четвертых, текстовый режим имеет встроенную поддержку известного формата CSV. Поскольку в трейдинге часто приходится оперировать табличными данными, CSV для этого хорошо подходит. В текстовом файле в режиме CSV функции MQL5 API обрабатывают не только разделители для переноса строк текста, но и дополнительный разделитель для границы столбцов (полей в каждом ряду таблицы). Обычно это символ табуляции '\t', запятая ',' или точка с запятой ';'. Например, вот как выглядит CSV-файл с новостями Forex (разделитель — запятая, показан фрагмент):

Title,Country,Date,Time,Impact,Forecast,Previous
Bank Holiday,JPY,08-09-2021,12:00am,Holiday,,
CPI y/y,CNY,08-09-2021,1:30am,Low,0.8%,1.1%
PPI y/y,CNY,08-09-2021,1:30am,Low,8.6%,8.8%
Unemployment Rate,CHF,08-09-2021,5:45am,Low,3.0%,3.1%
German Trade Balance,EUR,08-09-2021,6:00am,Low,13.9B,12.6B
Sentix Investor Confidence,EUR,08-09-2021,8:30am,Low,29.2,29.8
JOLTS Job Openings,USD,08-09-2021,2:00pm,Medium,9.27M,9.21M
FOMC Member Bostic Speaks,USD,08-09-2021,2:00pm,Medium,,
FOMC Member Barkin Speaks,USD,08-09-2021,4:00pm,Medium,,
BRC Retail Sales Monitor y/y,GBP,08-09-2021,11:01pm,Low,4.9%,6.7%
Current Account,JPY,08-09-2021,11:50pm,Low,1.71T,1.87T

И вот он же, для наглядности, в виде таблицы:

Title

Country

Date

Time

Impact

Forecast

Previous

Bank Holiday

JPY

08-09-2021

12:00am

Holiday

 

 

CPI y/y

CNY

08-09-2021

1:30am

Low

0.8%

1.1%

PPI y/y

CNY

08-09-2021

1:30am

Low

8.6%

8.8%

Unemployment Rate

CHF

08-09-2021

5:45am

Low

3.0%

3.1%

German Trade Balance

EUR

08-09-2021

6:00am

Low

13.9B

12.6B

Sentix Investor Confidence

EUR

08-09-2021

8:30am

Low

29.2

29.8

JOLTS Job Openings

USD

08-09-2021

2:00pm

Medium

9.27M

9.21M

FOMC Member Bostic Speaks

USD

08-09-2021

2:00pm

Medium

 

 

FOMC Member Barkin Speaks

USD

08-09-2021

4:00pm

Medium

 

 

BRC Retail Sales Monitor y/y

GBP

08-09-2021

11:01pm

Low

4.9%

6.7%

Current Account

JPY

08-09-2021

11:50pm

Low

1.71T

1.87T