2

我在使用 UTF-8 格式的字符串时遇到问题,例如“\u0161\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'以二进制形式读取文件,但显然还有其他问题......我在Netbeans 7.3.1中运行我的代码并在JRuby 1.7.3中构建(我也试过Ruby 2.0.0但没有任何影响。)

由于我是红宝石世界的新手,欢迎任何想法......

4

2 回答 2

1

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

\u306b\u3064\u3044\u3066

然后你需要在阅读后取消它。Ruby 使用字符串文字为您执行此操作,这就是为什么第二种情况适合您的原因。取自“这是在 Ruby 中对 unicode 转义序列进行转义的最佳方法吗? ”的答案,您可以使用它:

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/)
}
于 2013-07-24T11:30:11.687 回答
0

仅供参考:

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接受一个“分隔符”参数,在上面的例子中是“\t”。Ruby 会将它替换为 *nix 或 Mac OS 上通常的“\n”,或 Windows 上的“\r\n”,因此将使用制表符分隔符检索记录。

这让我有点想知道你为什么要这样做?我从未将制表符视为记录分隔符,只有“TSV”(制表符分隔值)文件中的列/字段分隔符。所以这让我认为您可能应该使用 Ruby 的CSV类,并使用“\t”作为列分隔符。但是,如果没有您正在阅读的实际文件的样本,我不能肯定地说。

于 2013-07-24T15:48:43.013 回答