【问题标题】:How to set a particular encoding for stdin and stdout using open3 in Ruby如何在 Ruby 中使用 open3 为标准输入和标准输出设置特定编码
【发布时间】:2016-12-05 13:42:38
【问题描述】:

是否可以在分别通过标准输入和标准输出发送输入和捕获输出时将编码设置为 utf-8,以便保留 (™)、à 等特殊字符?

这是我的代码(我使用的是 Windows,我认为输出具有这种编码:IBM866):

require 'open3'
require 'pragmatic_segmenter' # just a gem that segments paragraphs to sentences

Open3.popen3("tagger") do |stdin, stdout, stderr, wait_thread|
  tokenized_group = Proc.new do |sentences|
    sentences_array = PragmaticSegmenter::Segmenter.new(text: sentences).segment

    sentences_array.map do |sentence|
      stdin.puts "#{sentence}" 
      stdout.gets.gsub(/\n$/,"").encode("utf-8") #=> is it possible to get this utf-8, right now its IBM866?
    end
  end

  puts tokenized_group.call "Some random sentence with ™. Another random sentence with à." 
  #output => Some/DT random/JJ sentence/NN with/IN тДв/NN ./. Another/DT random/JJ sentence/NN with/IN ├а/NN ./.

  stdin.close
end

正如您所见,由于编码不同,输出中不会保留特殊字符。那么,我怎样才能找回标准输出中的那些字符呢?

【问题讨论】:

  • 为什么你认为输出有 IBM866 编码? stdout.internal_encoding.external_encoding 返回什么? sentences_array 中的项目的编码是什么?返回字符串中相关字符的实际字节值是多少?
  • @Jordan 当我尝试做 string.match 时,它给出了错误incompatible encoding regexp match (UTF-8 regexp with IBM866 string) (Encoding::CompatibilityError)internal_encoding 返回零,external_encoding returns IBM866。对于 ™(返回 тДв),它的 [209, 130, 208, 148, 208, 178] 对于 à(返回 ├а)它的 [226, 148, 156, 208, 176]

标签: ruby encoding utf-8


【解决方案1】:

这是一个奇怪的小问题。我认为这会起作用:

stdout.gets.encode(Encoding::IBM866, Encoding::UTF_8)

这告诉encode 源和目标编码。请注意,您需要在调用gsub 或字符串上的任何其他正则表达式方法之前执行此操作。

您可以通过使用set_encoding 告诉stdout 对象为您进行转换来跳过此操作:

stdout.set_encoding(Encoding::IBM866, Encoding::UTF_8)

在您的 popen3 块中做第一件事。

对于它的价值,这是我用来测试它的代码:

# ™(returns тДв)
a = [209, 130, 208, 148, 208, 178] 

# à(returns ├а)
b = [226, 148, 156, 208, 176]

a_str = a.pack("c*")
puts a_str.encode(Encoding::IBM866, Encoding::UTF_8)
# => ™

b_str = b.pack("c*")
puts b_str.encode(Encoding::IBM866, Encoding::UTF_8)
# => à

【讨论】:

  • 刚试过,但第一个给U+00E9 from UTF-8 to IBM866 (Encoding::UndefinedConversionError)第二个(即在打开块开始下设置编码)没有给出错误,但它给出了相同的错误字符。
猜你喜欢
  • 2020-06-11
  • 1970-01-01
  • 2023-04-01
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多