6

我在生产中的某个地方有一个文件,我无法访问该文件,当由 ruby​​ 脚本加载时,针对内容的正则表达式失败并带有ArgumentError => invalid byte sequence in UTF-8.

我相信我已经根据此处所有要点的答案进行了修复:ruby 1.9: invalid byte sequence in 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

但是,我现在想构建我的 rspec 来验证代码是否有效。我无权访问导致问题的文件,因此我想以编程方式创建一个编码错误的字符串。

我尝试了以下变化:

bad_str = (100..1000).to_a.inject('') {|s,c| s << c; s}
bad_str.length.should > safe_str(bad_str).length

或者,

bad_str = (100..1000).to_a.pack(c*)
bad_str.length.should > safe_str(bad_str).length

但长度始终相同。我也尝试过不同的字符范围;并不总是 100 到 1000。

关于如何在 ruby​​ 1.9.3 脚本中使用无效编码构建字符串的任何建议?

4

5 回答 5

4

许多单字节字符串会生成无效的 UTF-8 字符串,从 0x80 开始。所以128.chr应该工作。

于 2013-08-14T18:33:20.297 回答
3

您的safe_str方法(当前)永远不会对字符串实际执行任何操作,它是无操作的。Ruby 1.9.3的文档String#encode

请注意,从编码 enc 到相同编码 enc 的转换是无操作的,即返回接收器时不做任何更改,并且不会引发异常,即使存在无效字节也是如此。

这对于当前版本的 2.0.0(补丁级别 247)来说是正确的,但是最近对 Ruby 主干的提交改变了这一点,并且还引入了scrub一种几乎可以满足您需求的方法。

在发布新版本的 Ruby 之前,您需要将文本字符串往返传输到另一个编码并返回以清理它,如您链接到的问题的答案中的第二个示例所示,例如:

def safe_str str
  s = str.encode('utf-16', 'utf-8', invalid: :replace, undef: :replace, replace: '')
  s.encode!('utf-8', 'utf-16')
end

请注意,您尝试创建无效字符串的第一个示例将不起作用:

bad_str = (100..1000).to_a.inject('') {|s,c| s << c; s}
bad_str.valid_encoding? # => true

<<文档

如果对象是整数,则将其视为代码点,并在连接之前转换为字符。

所以你总是会得到一个有效的字符串。

您的第二种方法, usingpack将创建一个带有 encoding 的字符串ASCII-8BIT。如果您随后更改此force_encoding设置,则可以使用无效编码创建 UTF-8 字符串:

bad_str = (100..1000).to_a.pack('c*').force_encoding('utf-8')
bad_str.valid_encoding? # => false
于 2013-08-14T20:02:37.913 回答
2

尝试s = "hi \255"

s.valid_encoding?
# => false
于 2020-07-23T09:33:53.150 回答
1

以下示例可用于测试目的:

describe TestClass do
  let(:non_utf8_text) { "something\255 english." }

  it 'is not raise error on invalid byte sequence string' do
    expect(non_utf8_text).not_to be_valid_encoding
    expect { subject.call(non_utf8_text) }.not_to raise_error
  end
end

感谢 Iwan B. 的“\255”建议。

于 2022-02-01T07:23:50.697 回答
0

在我编写的规范测试中,我还没有找到解决这种错误编码的方法:

期间%基础

%B字符串始终产生ArgumentError: invalid byte sequence in UTF-8.

于 2013-08-14T18:58:21.487 回答