Цель состоит в том, чтобы сделать конфигурацию и код читаемыми после того, как они были экспортированы из приложения, которое хранит эти данные в кодировке base64 и формате gzip.
Пример строки с кодом
"H4sIAAAAAAAAAIWSS0vEMBSF9/0VIYvubHUnNGlhfIDCwOCMuCyhTeOVTBLzGPTfmzY60yKju+Tc8N1z7o2RQYBqmTESuGthaDuHXJpWTRknzsZfowK0DrSi+Ki4x4qrTPShB8fPu/uIaN3VGVsGB4s49BcnrDKGjsJlwaF5P0sMtxY/swLadBeN/6jda9eBjrxfwrytQvcMjLgI3zLI999FJEuYSGmHpNdp9Gk7xWyQXkilRbL2NXnGdS18twuTvQfsqJkqHU6x0n7KlY5MLX2UjYOyxZqacBFIeDZyxdGettusYiwn+h7X/QadBnadY7oNVaGDS8eoXciZMAyTlckNxh+Vyid//4Qv+y3JeLwIAAA= = "
Декодируется и архивируется в оболочке Linux с помощью команды:
echo $1 | base64 -d | gunzip -c
Что приводит к:
plugin_applies_if_config<split>plugin_config=<?xml version = "1.0" encoding = "UTF-8"?>
<BusinessRule>
<BusinessPlugin BusinessRulePluginID = "JavaScriptBusinessConditionWithBinds">
<Parameters>
<Parameter ID = "Binds" Type = "java.lang.String"><?xml version="1.0" encoding="UTF-8"?>
<BindMap/>
</Parameter>
<Parameter ID = "ErrorMessages" Type = "java.lang.String"></Parameter>
<Parameter ID = "JavaScript" Type = "java.lang.String">return false;</Parameter>
</Parameters>
</BusinessPlugin>
</BusinessRule>
<split>
Задача выполнена. ...почти.
Так как у меня есть несколько сотен таких строк, я хочу выполнять в скрипте те же команды, что и в оболочке Linux. И поскольку я знаю только немного R, я попытался использовать R. Я успешно извлек строки из XML-документа, который был экспортирован из приложения, и превратил их во фрейм данных с идентификатором столбцов, именем и кодом.
Ниже приведен упрощенный пример, в котором я пытаюсь шаг за шагом воспроизвести команды Linux.
encoded = "H4sIAAAAAAAAAIWSS0vEMBSF9/0VIYvubHUnNGlhfIDCwOCMuCyhTeOVTBLzGPTfmzY60yKju+Tc8N1z7o2RQYBqmTESuGthaDutBhDERcHXJpWTRknzsZfowK0DrSi+Ki4x4qrTPShB8fPu/uIaN3VGVsGB4s49BcnrDKGjsJlwaF5P0sMtxY/swLadBeN/6jda9eBjrxfwrytQvcMjLgI3zLI999FJEuYSGmHpNdp9Gk7xWyQXkilRbL2NXnGdS18twuTvQfsqJkqHU6x0n7KlY5MLX2UjYOyxZqacBFIeDZyxdGettusYiwn+h7X/QadBnadY7oNVaGDS8eoXciZMAyTlckNxh+Vyid//4Qv+y3JeLwIAAA= = "
decoded = base64enc::base64decode(what=encoded)
# decoded = openssl::base64_decode(encoded)
# decoded = jsonlite::base64_dec(encoded)
# 3 times the same result
str(decoded)
# an array of raw-types. Maybe i need to convert to a string?
paste(decoded, collapse = "")
Не похоже на расшифрованные данные base64 в оболочке Linux, но давайте попробуем разархивировать...
decompressed <-
tryCatch({
memDecompress(from = paste(decoded, collapse = ""),
type = "gzip",
asChar = TRUE)
},
error = function(cond) {
message(cond)
return(NA)
})
# fails with "internal error -3 in memDecompress(2)"
(decompressed)
Очевидно, что ввод для «gzip» не соответствует ожиданиям. Это должна быть какая-то двоичная строка.
Но как туда добраться? Что я делаю неправильно? Спасибо за ваш совет!
Функция memDecompress
была улучшена в версии R 4.0.0 для правильной работы. Теперь вы должны быть в состоянии сделать
memDecompress(base64enc::base64decode(what=encoded), "gzip", asChar=TRUE)
Предыдущие версии вызывали затруднения, поскольку игнорировали стандартные заголовки. Вот несколько слов о более старых версиях R. В основном мы создаем необработанный поток байтов, а затем используем gzcon
для их распаковки.
con <- rawConnection(base64enc::base64decode(what=encoded))
readLines(gzcon(con))
close(con)
Вы получите предупреждение о том, что есть «неполная последняя строка», но это только потому, что похоже, что в конце файла не было новой строки. В противном случае данные кажутся прекрасными.
См. также: stackoverflow.com/questions/39707388/…
Я превратил ваши 3 строки кода в функцию, добавил try-catch, чтобы избавиться от предупреждения, применил его к фрейму данных и получил читаемый код и конфигурацию! :) Спасибо!
@MrFlick Мне понравился твой ответ здесь, потому что ты мне очень помог. Огромное спасибо
Вы всегда можете использовать
system
с командой оболочки. Если вам нужно сделать это в R, вы можете попробовать записать необработанный объект в файл и посмотреть, является ли файл допустимым zip-архивом. Если это так, вы можете попробовать последний шаг - разархивировать... Удачи!