Как мне разархивировать строку в кодировке base64 в R? - PullRequest
4 голосов
/ 09 апреля 2019

Цель

Цель состоит в том, чтобы сделать конфигурацию и код читаемыми после их экспорта из приложения, которое хранит эти данные в кодировке base64 и формате gzip-ped.

Тестирование в Linux-оболочке

Пример строки с кодом

"H4sIAAAAAAAAAIWSS0vEMBSF9/0VIYvubHUnNGlhfIDCwOCMuCyhTeOVTBLzGPTfmzY60yKju+Tc8N1z7o2RQYBqmTESuGthaDuHXJpWTRknzsZfowK0DrSi+Ki4x4qrTPShB8fPu/uIaN3VGVsGB4s49BcnrDKGjsJlwaF5P0sMtxY/swLadBeN/6jda9eBjrxfwrytQvcMjLgI3zLI999FJEuYSGmHpNdp9Gk7xWyQXkilRbL2NXnGdS18twuTvQfsqJkqHU6x0n7KlY5MLX2UjYOyxZqacBFIeDZyxdGettusYiwn+h7X/QadBnadY7oNVaGDS8eoXciZMAyTlckNxh+Vyid//4Qv+y3JeLwIAAA=="

Декодируется и gunzip-ped в оболочке 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">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;BindMap/&gt;
</Parameter>
      <Parameter ID="ErrorMessages" Type="java.lang.String"></Parameter>
      <Parameter ID="JavaScript" Type="java.lang.String">return false;</Parameter>
    </Parameters>
  </BusinessPlugin>
</BusinessRule>
<split>

Задача выполнена.... почти.

Превратимся в R-скрипт

Поскольку у меня есть несколько сотен этих строк, я хочу выполнить в скрипте команды, аналогичные тем, которые используются в оболочке Linux.И поскольку я знаю только R, я попытался использовать R. Я успешно извлек строки из XML-документа, который был экспортирован из приложения, и превратил их в фрейм данных со столбцами id, name и code.

Ниже приведен упрощенный пример, где я пытаюсь воспроизвести команды 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 не тот, который он ожидает.Это должна быть какая-то двоичная строка.

Но как туда добраться?Что я делаю неправильно?Спасибо за ваш совет!

1 Ответ

3 голосов
/ 09 апреля 2019

Функции memDecompress неприятны, потому что я считаю, что они игнорируют стандартные заголовки. Вот способ сделать это, чтобы избежать этой функции. По сути, мы создаем необработанный поток байтов, а затем используем gzcon для их распаковки

con <- rawConnection(base64enc::base64decode(what=encoded))
readLines(gzcon(con))
close(con)

Вы получите предупреждение о том, что есть «неполная последняя строка», но это только потому, что похоже, что в конце файла не было новой строки. В противном случае данные выглядят нормально.

...