GSP*_*GSP 5 ruby character-encoding
我有一个生产中的某个文件,我无法访问它,当由ruby脚本加载时,针对内容的正则表达式失败了ArgumentError => invalid byte sequence in UTF-8.
我相信我有一个基于所有要点的答案:ruby 1.9:UTF-8中的无效字节序列
# Remove all invalid and undefined characters in the given string
# (ruby 1.9.3)
def safe_str str
# edited based on matt's comment (thanks matt)
s = str.encode('utf-16', 'utf-8', invalid: :replace, undef: :replace, replace: '')
s.encode!('utf-8', 'utf-16')
end
Run Code Online (Sandbox Code Playgroud)
但是,我现在想构建我的rspec以验证代码是否有效.我无法访问导致问题的文件,所以我想以编程方式创建一个带有错误编码的字符串.
我尝试过以下方面的变化:
bad_str = (100..1000).to_a.inject('') {|s,c| s << c; s}
bad_str.length.should > safe_str(bad_str).length
Run Code Online (Sandbox Code Playgroud)
要么,
bad_str = (100..1000).to_a.pack(c*)
bad_str.length.should > safe_str(bad_str).length
Run Code Online (Sandbox Code Playgroud)
但长度总是一样的.我也尝试过不同的角色范围; 并不总是100到1000.
有关如何在ruby 1.9.3脚本中使用无效编码构建字符串的任何建议?
您的safe_str方法(当前)实际上永远不会对字符串执行任何操作,它是一个无操作。String#encodeRuby 1.9.3的文档说:
\n\n\n请注意,从编码 enc 到相同编码 enc 的转换是无操作,即返回接收者而不进行任何更改,并且不会引发异常,即使存在无效字节也是如此。
\n
对于当前版本的 2.0.0(补丁级别 247)来说确实如此,但是最近对 Ruby trunk 的提交改变了这一点,并且还引入了一种scrub几乎可以满足您需求的方法。
在发布新版本的 Ruby 之前,您将需要将文本字符串往返到另一种编码并返回以清理它,如您链接到的问题的答案中的第二个示例所示,如下所示:
\n\ndef safe_str str\n s = str.encode(\'utf-16\', \'utf-8\', invalid: :replace, undef: :replace, replace: \'\')\n s.encode!(\'utf-8\', \'utf-16\')\nend\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,尝试创建无效字符串的第一个示例不会\xe2\x80\x99 工作:
\n\nbad_str = (100..1000).to_a.inject(\'\') {|s,c| s << c; s}\nbad_str.valid_encoding? # => true\nRun Code Online (Sandbox Code Playgroud)\n\n来自<<文档:
\n\n\n如果对象是整数,则将其视为代码点,并在连接之前转换为字符。
\n
所以你\xe2\x80\x99总会得到一个有效的字符串。
\n\n第二种方法,使用pack将创建一个带有编码的字符串ASCII-8BIT。如果您随后使用以下命令更改此设置,force_encoding则可以创建具有无效编码的 UTF-8 字符串:
bad_str = (100..1000).to_a.pack(\'c*\').force_encoding(\'utf-8\')\nbad_str.valid_encoding? # => false\nRun Code Online (Sandbox Code Playgroud)\n