如何在 R 中解压缩 base64 编码的字符串?

Ude*_* VH 6 base64 decode r unzip

目标

目标是在从以 base64 编码和 gzip-ped 格式存储此数据的应用程序导出后使配置和代码可读。

在 Linux-shell 中测试

带有代码的字符串示例

"H4sIAAAAAAAAAIWSS0vEMBSF9/0VIYvubHUnNGlhfIDCwOCMuCyhTeOVTBLzGPTfmzY60yKju+Tc8N1z7o2RQYBqmTESuGthaDuHXJpWTRknzsZfowK0DrSi+Ki4x4qrTPShB8fPu/uIaN3VGVsGB4s49BcnrDKGjsJlwaF5P0sMtxY/swLadBeN/6jda9eBjrxfwrytQvcMjLgI3zLI999FJEuYSGmHpNdp9Gk7xWyQXkilRbL2NXnGdS18twuTvQfsqJkqHU6x0n7KlY5MLX2UjYOyxZqacBFIeDZyxdGettusYiwn+h7X/QadBnadY7oNVaGDS8eoXciZMAyTlckNxh+Vyid//4Qv+y3JeLwIAAA=="
Run Code Online (Sandbox Code Playgroud)

使用以下命令在 Linux shell 中解码和压缩:

echo $1 | base64 -d | gunzip -c
Run Code Online (Sandbox Code Playgroud)

结果是:

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>
Run Code Online (Sandbox Code Playgroud)

任务完成。...几乎。

转成R脚本

由于我有数百个这样的字符串,因此我想在脚本中执行与 Linux shell 中类似的命令。因为我只知道一些 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)
Run Code Online (Sandbox Code Playgroud)
# an array of raw-types. Maybe i need to convert to a string?
paste(decoded, collapse = "")
Run Code Online (Sandbox Code Playgroud)

看起来不像 Linux shell 中的 base64 解码数据,但让我们尝试解压缩......

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)
Run Code Online (Sandbox Code Playgroud)

显然,'gzip' 的输入不是它所期望的。它必须是某种二进制字符串。

但是如何到达那里?我究竟做错了什么?感谢您的意见!

MrF*_*ick 6

memDecompress功能在 R 版本 4.0.0 中得到改进以正常工作。你现在应该能够做到

memDecompress(base64enc::base64decode(what=encoded), "gzip", asChar=TRUE)
Run Code Online (Sandbox Code Playgroud)

以前的版本很麻烦,因为它们忽略了标准标题。这是旧版本 R 的一个词。基本上我们创建一个原始字节流,然后用于gzcon解压缩它们

con <- rawConnection(base64enc::base64decode(what=encoded))
readLines(gzcon(con))
close(con)
Run Code Online (Sandbox Code Playgroud)

您将收到一条警告,指出存在“不完整的最后一行”,但这只是因为文件末尾似乎没有新行。否则数据似乎没问题。