簡體   English   中英

如何阻止Sequel的postgres-pr適配器以錯誤的編碼返回數據?

[英]How do I stop Sequel's postgres-pr adaptor from returning data in the wrong encoding?

我從jeremyevans-postgres-pr適配器得到了錯誤的編碼,這是Sequel建議的適配器之一。

我做錯什么了嗎?

示例代碼:

require 'postgres-pr/connection'
c = PostgresPR::Connection.new('blah', 'blah', 'blah')

row = c.query("select name, cost from remedium.prescription").rows.last
row.each do |f|
  #f.force_encoding(Encoding::UTF_8) #-- uncomment this to 'fix' everything ;/

  enc = f.kind_of?(String) ? f.encoding : ''
  puts [f.class, f, f.inspect, enc].join(' ')
end

輸出:

String Paracelsium "Paracelsium" ASCII-8BIT
String £0.00 "\xC2\xA30.00" ASCII-8BIT

不用說,我從Sequel本身獲得了相同的結果。 而且我的數據庫不是編碼為ASCII,而是UTF8。

  • 現在,我需要同時使用Ruby和JRuby與PostgreSQL進行對話,並且在每種情況下嘗試使用相同的工具鏈是很有意義的,因此這顯然是可以使用的適配器。 但。

  • Jeremy分叉的原始適配器的行為相同。

  • 我可以通過強制全面編碼來解決此問題,但這對我所有代碼來說都是一個皇家痛苦……


我可能應該提供一些其他答案(謝謝):

  • 版本-> Centos 7; Ruby 2.3.1和JRuby 9.1.1.0; 寶石版本0.6.6
  • 操作系統語言環境->“ LANG = en_GB.UTF-8”
  • Ruby默認值-> Encoding.default_internal = nil; default_external =編碼:: UTF-8

postgres-pr不支持編碼。 我不打算加我自己,但我願意考慮補丁。

至少在使用模型的地方,可以使用force_encoding Sequel :: Model插件來修復編碼。

我在我的一個數據庫上嘗試了您的代碼示例,並且一切正常。 可能對您的設置有些特殊嗎? 您可以使用

p c.query("SHOW client_encoding;").rows.first

並且應該能夠使用以下命令進行設置:

p c.query("SET CLIENT_ENCODING TO 'UTF-8';")

經過安迪·瓊斯的一些反饋和傑里米的評論后,我對源代碼進行了更多研究。 編輯問題,以便我有比注釋更好的格式選項。

驅動程序從流中讀取US-ASCII ,如下所示:

    buffer.copy_from_stream(stream, length-4)

源代碼

依次調用Buffer#write ,將數據插入到自己的@content

@content[@position, sz] = str

源代碼

現在@content是一個特定大小的字符串,用號填充,它的創建方式如下:

def self.of_size(size)
  raise ArgumentError if size < 0
  new('#' * size
end

給定您的系統設置為使用UTF-8,這會使@content成為UTF-8字符串。 US-ASCII字符串合並為UTF將產生__UTF-8字符串。 從那里開始,不會進行任何轉換,因此應保持該編碼狀態。 使用執行此操作的Buffer.read方法讀取列內容:

@content[@position, n]

源代碼

這個冗長的解釋只是說:我不明白為什么您會看到US-ASCII輸出:-(

除非:您的系統未設置為以某種奇怪的方式使用UTF-8。

Ruby 1.9的默認編碼為US-ASCII ,而Ruby 2.2的默認編碼為UTF-8 (或更早版本,不確定嗎?)。

你有沒有

# encoding: 

在文件開頭添加樣式注釋?

如果您這樣做會怎樣?

puts String.new.encoding

有什么價值

puts __ENCODING__

有什么價值

puts RUBY_VERSION

請檢入與運行db測試腳本相同的文件。

了解這里發生的事情的關鍵是在ruby中編碼的多種設置。 有:

  • 使用魔術注釋或-k命令行開關設置的語言環境編碼。

  • 默認的外部編碼,使用Encoding.default_external或--external-encoding或-E設置

  • 默認的內部編碼,設置為Encoding.default_internal或--internal-encoding(或冒號后面的-E)

Ruby默認會基於一些相當混亂的規則將字符串設置為內部或外部編碼。 有關詳細信息,請參見文檔 但是這里重要的是,當從二進制數據創建字符串時,它看起來是內部的而不是所使用的外部編碼。

我的內部編碼為nil,所以沒有發生。 (ASCII-8BIT是當Ruby不知道編碼是什么時得到的編碼,它的基本意思是“這只是我的數據;祝您讀好運”。)

如果我在命令行上通過--internal-encoding UTF-8 ,問題就消失了。 從某種意義上講,這與傑里米的寶石無關。

當我在命令行上放置-E UTF-8時,將設置默認的外部編碼。 在這種情況下沒有執行任何操作。

編輯:在這種情況下它可以工作,但是在某些(所有?)情況下,Ruby會將字符串轉碼為內部編碼,而不僅僅是像force_encoding那樣設置編碼值。 這東西很難。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM