Ruby String:存储包含反斜杠和十六进制表示法的字符串

Posted

技术标签:

【中文标题】Ruby String:存储包含反斜杠和十六进制表示法的字符串【英文标题】:Ruby String: store a string containing backslashes and hexadecimal notation 【发布时间】:2019-12-03 18:12:20 【问题描述】:

找不到更好的标题,所以还是务实一点吧:

目标:通过将 PNG 的 8 个首字节与匹配字符串进行比较来检查 PNG 是否有效

问题: PNG 文件应以 \x89PNG\r\n\x1A\n (why ?) 开头。将此作为字符串存储在变量中会导致一些意外行为:

使用",将\x1A替换为\u001A(SUBSTITUTE)
s = "\x89PNG\r\n\x1A\n"
=> "\x89PNG\r\n\u001A\n"
使用',反斜杠被转义
s = '\x89PNG\r\n\x1A\n'
=> "\\x89PNG\\r\\n\\x1A\\n"
转义替换字符也不起作用:
s = "\x89PNG\r\n\\x1A\n"
=> "\x89PNG\r\n\\x1A\n"
使用force_encoding 失败:
s = "\x89PNG\r\n\x1A\n".force_encoding('UTF-8')
=> "\x89PNG\r\n\u001A\n"

我最近开始了这个项目,开始使用字节,到目前为止我并不失望:D

我错过了什么?我应该使用单引号然后gsub 过滤反斜杠吗?我应该使用位表示而不是 hexa 吗? 理想情况下,我希望在变量中精确值(以十六进制表示),而不必对其调用任何方法

祝你有美好的一天!

【问题讨论】:

为什么要强制使用 utf-8?它是字节流,而不是 unicode 字符串。 "\x89PNG\r\n\x1A\n".force_encoding('ASCII-8BIT') 无论如何,不​​要混淆实际内容及其表示。这些字符串是相同的,按字节计算。 "\x89PNG\r\n\x1A\n".force_encoding('UTF-8').bytes == "\x89PNG\r\n\x1A\n".force_encoding('ASCII-8BIT').bytes 啊哈,一切都很简单(我很沮丧没有看到它)!非常感谢 感谢您的建议,考虑到这一点,我将花更多时间玩它。因此,如果我不想让我的脚本更健壮,我应该比较字节而不是字符串(因为它们可能会有所不同,并且文件头中的字节是以可预测的方式构造的)? @SergioTulentsev .force_encoding(Encoding::BINARY) 在语义上更合适。 【参考方案1】:

不幸的是,Ruby 将字符串和二进制数据混为一谈,但您不必在代码中这样做。改用打包/解包:

data.unpack("C8") == [0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa]
# or
png_header = [0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa].pack("C8")

【讨论】:

感谢您的回答! packunpack 看起来超级强大,我得努力练习才能熟练!【参考方案2】:

按照 Sergio Tulentsev 的建议,我决定在实例方法中比较签名的字节数。它一定不是最好的解决方案(ima n00b),但这是我的代码:

SIGNATURE = "\x89PNG\r\n\x1A\n"

# inside the initialize methode 
  raise ArgumentError, 'File is not a PNG' unless self.png_sig?


def png_sig?
  bytes_slice(limit: 7) == SIGNATURE.bytes
end

def bytes_slice(first_byte: 0, limit: -1)
  @content.bytes[first_byte..limit]
end

【讨论】:

以上是关于Ruby String:存储包含反斜杠和十六进制表示法的字符串的主要内容,如果未能解决你的问题,请参考以下文章

Hive regexp_replace 无法替换反斜杠

如何编码 Azure 存储表行键和分区键?

使用包含单个反斜杠的字符串的 Python 格式字符串

Jackson ObjectMapper writeValueAsBytes方法为已包含反斜杠的字符串添加另一个反斜杠

Ruby gsub 替换值的单反斜杠?

在数据库中,文件路径应该存储斜杠/,还是反斜杠呢?