Правильное экранирование очень больших строк
На esp8266 я хочу создать небольшой веб-сервер, который показывает мне панель мониторинга с диаграммами и прочим. Для этого я хочу включитьбиблиотеку echarts, поскольку она работает в автономном режиме. Чтобы получить к нему доступ, единственный способ увидеть, как это работает, - это написать `
const char libData[784674] PROGMEM = "the entire 700 KB library goes here";
А затем доставить его по запросу с сервера.on('./echarts.min.js ', handleLibRequest)
или что-то в этом роде.
Теперь моя проблема в том, что в этом 700КБ текста есть символы "
и "
, разбросанные по всему периметру. C ++ 11 способ R("hard escapable """'" string")
не работает в моей среде. Как бы это сделать, чтобы включить этот файл в мой код?
Есть ли какой-то способ использовать препроцессор для этого? Или, может быть, онлайн-инструмент, который преобразует "str" в ["s", "t", "r"]
?
@Cowboy_Patrick, 👍0
Обсуждение4 ответа
Лучший ответ:
Это просто: вставьте всю страницу между "()" в строке ниже
const char live_html[] PROGMEM = R"rawliteral(your date here)rawliteral";
Вы можете написать простую программу, которая экранирует все оскорбительные символы и использует их вывод в вашем const char libData[]
; список escape-последовательностей см. Здесь;
Вы можете обслуживать библиотеку непосредственно из (псевдо) файловой системы на ESP8266, не копируя ее "вручную" в переменную; вы просто копируете файл в файловую систему;
Вы можете Base64-закодировать библиотеку и вручную скопировать результат в const char libData[]
, а затем Base64-декодировать перед отправкой;
Что мне нравится делать, если нет файловой системы, но достаточно памяти:
- Gzip библиотеки;
- Base64 - кодировать файл .gz;
- Скопируйте результат в кодировке Base-64 вручную в
const char libData[]
.
Несмотря на кодировку Base64, gzipping делает конечный результат меньше оригинала, что помогает с использованием памяти и скоростью передачи, и у него не будет никаких "проблем с цитатами".
Когда необходимо обслужить libData, Base64-декодирует его и отправляет полученные (gzipped) данные клиенту; все известные мне браузеры примут это, если вы добавите заголовок Content-Encoding: gzip
.
Пример кода на необработанном клиенте без библиотеки веб-сервера: unsigned int sendBase64Page()
(обратите внимание на тип содержимого).
Это все равно что скопировать его в переменную, но, на мой взгляд, излишне сложно. Но спасибо за идею., @Cowboy_Patrick
Я только что написал себе python-скрипт, который создает массив символов с числами, представляющими символы. Может быть, это поможет кому-то еще:
import sys
def arrayify(sourceFile, targetFile):
with open(sourceFile, 'rb') as sf:
contents = sf.read()
charArray = ""
for char in contents:
charArray += str(char) + ","
# end array
with open(targetFile, 'w') as tf:
tf.write(charArray)
if __name__ == "__main__":
sourceFile = sys.argv[1]
targetFile = sys.argv[2]
arrayify(sourceFile, targetFile)
Вы можете использовать "objcopy" для создания объектного файла из содержимого файла, если вы объявите его двоичным.
objcopy -I binary echarts.min.js -O <your-bfd-format> echarts.min.js.o
Чтобы узнать, какой формат BFD вам нужен, запустите objdump -t <любой объектный файл>
и посмотрите на его вывод.
Результирующий объектный файл содержит объект, названный в честь входного файла в разделе .data
. В таблице символов есть 3 символа:
- _binary_echarts_min_js_start
- _binary_echarts_min_js_end
- _binary_echarts_min_js_size
Символ "start" обозначает начало содержимого файла, а символ "end" - адрес после последнего байта. Символ "size" трудно использовать в C или C ++, потому что это абсолютное значение.
Обычно я просто использую "начало" и "конец" следующим образом:
extern const char _binary_x_bin_start[];
extern const char _binary_x_bin_end[];
Вместо objcopy
вы можете использовать ld -r -b binary echarts.min.js -o echarts.min.js.o
Таким образом, вам не нужно знать формат BFD, если вы используете ld
двоичный файл, соответствующий целевой архитектуре., @Edgar Bonet
- Преобразование строки в IP-адрес
- Как составить URL-адрес HTTP-запроса GET с параметрами ключ/значение
- Какова цель F() и FPSTR() в ESP8266WebServer -> FSBrowser?
- Как исправить код утечки памяти в ESP8266/NodeMCU, вызванный концентрацией строк?
- Как заменить объекты String массивами символов, продолжая использовать строковые методы
- Утечка памяти, вызванная конкатенацией строк
- Как отсортировать строку с числом по возрастанию
- Чтение строки из Firebase и сохранение ее в виде CString
обслуживание статических файлов из файловой системы, @Juraj
Как бы я добавил эти статические файлы в файловую систему? Без необходимости использовать какой-либо код c ++, где я столкнулся бы с теми же проблемами, упомянутыми в моем вопросе?, @Cowboy_Patrick
с помощью плагина IDE для загрузки esp8266 FS. https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html, @Juraj