使用外部文件中的二进制数据(utf-8中的字符串)

时间:2013-07-24 11:10:55

标签: ruby encoding

我在使用UTF-8格式的字符串时遇到问题,例如“\ u016​​1 \ u010D \ u0159 \ u017E \ u00FD”。 当这样的字符串在我的程序中定义为变量时,它可以正常工作。但是当我通过从一些外部文件中读取它来使用这样的字符串时,我得到错误的输出(我没有得到我想要/期望的东西)。我肯定错过了一些必要的编码......

我的代码:

file  = "c:\\...\\vlmList_unicode.txt" #\u306b\u3064\u3044\u3066
data = File.open(file, 'rb') { |io| io.read.split(/\t/) }
puts data
data_var = "\u306b\u3064\u3044\u3066"
puts data_var

输出:

\u306b\u3064\u3044\u3066 # what I don't want
について # what I want

我试图通过指定'rb'来读取二进制形式的文件,但显然还有其他一些问题...... 我使用JRuby 1.7.3中的构建在Netbeans 7.3.1中运行我的代码(我也尝试过Ruby 2.0.0但没有任何影响。)

因为我是红宝石世界的新人,所以欢迎任何想法......

2 个答案:

答案 0 :(得分:1)

如果您的文件包含文字转义字符串:

\u306b\u3064\u3044\u3066

然后你需要在阅读后解开它。 Ruby使用字符串文字为您完成此操作,这就是为什么第二种情况适合您。取自“Is this the best way to unescape unicode escape sequences in Ruby?”的答案,您可以使用:

file  = "c:\\...\\vlmList_unicode.txt" #\u306b\u3064\u3044\u3066
data = File.open(file, 'rb') { |io| 
  contents = io.read.gsub(/\\u([\da-fA-F]{4})/) { |m| 
    [$1].pack("H*").unpack("n*").pack("U*")
  }
  contents.split(/\t/)
}

或者,如果您希望使其更具可读性,请将替换提取到新方法中,然后将其添加到String类:

class String
  def unescape_unicode
    self.gsub(/\\u([\da-fA-F]{4})/) { |m| 
      [$1].pack("H*").unpack("n*").pack("U*")
    }
  end
end

然后你可以打电话:

file  = "c:\\...\\vlmList_unicode.txt" #\u306b\u3064\u3044\u3066
data = File.open(file, 'rb') { |io| 
  io.read.unescape_unicode.split(/\t/)
}

答案 1 :(得分:0)

就像一个FYI:

data = File.open(file, 'rb') { |io| io.read.split(/\t/) }

可以更简单地写成以下之一:

data = File.read(file, 'rb').split(/\t/)
data = File.readlines(file, "\t", 'mode' => 'rb')

(请记住,File继承自IO,这是定义这些方法的地方,因此请查看IO以获取有关它们的文档。)

readlines采用“separator”参数,在上面的示例中为“\ t”。 Ruby会将它替换为* nix或Mac OS上的常用“\ n”或Windows上的“\ r \ n”,因此将使用制表符分隔符检索记录。

这让我想知道为什么你想要这样做呢?我从来没有看到制表符作为记录分隔符,只有“TSV”(Tab-Seperated-Value)文件中的列/字段分隔符。所以这让我觉得你应该使用Ruby的CSV类,并使用“\ t”作为列分隔符。但是,如果没有您正在阅读的实际文件的样本,我无法肯定地说。