如何在 R 中解压缩 base64 编码的字符串?
How can I unzip a base64 encoded string in R?
目标
目标是在从以 base64 编码和 gzip 格式存储此数据的应用程序中导出配置和代码后,使配置和代码可读。
测试在Linux-shell
带代码的字符串示例
"H4sIAAAAAAAAAIWSS0vEMBSF9/0VIYvubHUnNGlhfIDCwOCMuCyhTeOVTBLzGPTfmzY60yKju+Tc8N1z7o2RQYBqmTESuGthaDuHXJpWTRknzsZfowK0DrSi+Ki4x4qrTPShB8fPu/uIaN3VGVsGB4s49BcnrDKGjsJlwaF5P0sMtxY/swLadBeN/6jda9eBjrxfwrytQvcMjLgI3zLI999FJEuYSGmHpNdp9Gk7xWyQXkilRbL2NXnGdS18twuTvQfsqJkqHU6x0n7KlY5MLX2UjYOyxZqacBFIeDZyxdGettusYiwn+h7X/QadBnadY7oNVaGDS8eoXciZMAyTlckNxh+Vyid//4Qv+y3JeLwIAAA=="
使用以下命令在 Linux shell 中解码和 gunzip:
echo | 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>
任务完成。 ...差不多。
转换为 R 脚本
因为我有数百个这样的字符串,所以我想在脚本中执行与 Linux shell 中类似的命令。因为我只知道一些 R,所以我尝试使用 R。我成功地从从应用程序导出的 XML-文档中提取了字符串,并将它们转换为包含 ID、名称和代码列的数据框。
以下是一个简化示例,我尝试逐步重现 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 = "")
看起来不像Linuxshell中的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)
显然 'gzip' 的输入不是它所期望的。它必须是某种二进制字符串。
但是怎么去呢?我究竟做错了什么?谢谢你的建议!
memDecompress
函数在 R 版本 4.0.0 中得到改进,可以正常工作。您现在应该可以做到
memDecompress(base64enc::base64decode(what=encoded), "gzip", asChar=TRUE)
以前的版本很麻烦,因为它们忽略了标准 headers。这里有一个关于旧版本 R 的词。基本上我们创建一个原始字节流,然后使用 gzcon
来解压缩它们
con <- rawConnection(base64enc::base64decode(what=encoded))
readLines(gzcon(con))
close(con)
您会收到一条警告,指出存在“最后一行不完整”,但这只是因为看起来文件末尾没有换行。否则数据似乎没问题。
目标
目标是在从以 base64 编码和 gzip 格式存储此数据的应用程序中导出配置和代码后,使配置和代码可读。
测试在Linux-shell
带代码的字符串示例
"H4sIAAAAAAAAAIWSS0vEMBSF9/0VIYvubHUnNGlhfIDCwOCMuCyhTeOVTBLzGPTfmzY60yKju+Tc8N1z7o2RQYBqmTESuGthaDuHXJpWTRknzsZfowK0DrSi+Ki4x4qrTPShB8fPu/uIaN3VGVsGB4s49BcnrDKGjsJlwaF5P0sMtxY/swLadBeN/6jda9eBjrxfwrytQvcMjLgI3zLI999FJEuYSGmHpNdp9Gk7xWyQXkilRbL2NXnGdS18twuTvQfsqJkqHU6x0n7KlY5MLX2UjYOyxZqacBFIeDZyxdGettusYiwn+h7X/QadBnadY7oNVaGDS8eoXciZMAyTlckNxh+Vyid//4Qv+y3JeLwIAAA=="
使用以下命令在 Linux shell 中解码和 gunzip:
echo | 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>
任务完成。 ...差不多。
转换为 R 脚本
因为我有数百个这样的字符串,所以我想在脚本中执行与 Linux shell 中类似的命令。因为我只知道一些 R,所以我尝试使用 R。我成功地从从应用程序导出的 XML-文档中提取了字符串,并将它们转换为包含 ID、名称和代码列的数据框。
以下是一个简化示例,我尝试逐步重现 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 = "")
看起来不像Linuxshell中的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)
显然 'gzip' 的输入不是它所期望的。它必须是某种二进制字符串。
但是怎么去呢?我究竟做错了什么?谢谢你的建议!
memDecompress
函数在 R 版本 4.0.0 中得到改进,可以正常工作。您现在应该可以做到
memDecompress(base64enc::base64decode(what=encoded), "gzip", asChar=TRUE)
以前的版本很麻烦,因为它们忽略了标准 headers。这里有一个关于旧版本 R 的词。基本上我们创建一个原始字节流,然后使用 gzcon
来解压缩它们
con <- rawConnection(base64enc::base64decode(what=encoded))
readLines(gzcon(con))
close(con)
您会收到一条警告,指出存在“最后一行不完整”,但这只是因为看起来文件末尾没有换行。否则数据似乎没问题。