2013-05-10 37 views
8

我從數據庫查詢中檢索結果的大散列並將它們寫入csv文件。下面的代碼塊會獲取結果並創建CSV。使用quote_char:選項,它將用空字符替換引號,這需要我正確創建制表符分隔的文件。Ruby CSV.open需要刪除引號和空字符

但是,當NULL字符被加載到它們的目的地時會被轉換成「」,所以我想刪除它們。如果我離開quote_char:每個字段都是雙引號引起相同的結果。

如何刪除NULL字符?

begin 
    CSV.open("#{file_path}"'file.tab', "wb", Options = {col_sep: "\t", quote_char: "\0"}) do |csv| 
     csv << ["Key","channel"]   
     series_1_results.each_hash do |series_1| 
     csv << ["#{series_1['key']}","#{series_1['channel']}"] 
     end 
    end 
end 
+0

爲了讓我更清楚地知道輸出需要什麼,它必須與「另存爲...」菜單中「Windows Formatted Text.txt」提供的格式相匹配。這是一個製表符分隔格式,文件中沒有引號。 – analyticsPierce 2013-05-10 07:49:27

回答

3

正如中規定的csv documentation你必須設定quote_char一些性格,這種性格會始終用於報價空字段。

看來在這種情況下唯一的解決方案是從創建的csv文件中刪除使用的quote_chars。你可以這樣做:

quotedFile = File.read("#{file_path}"'file.tab') 
unquotedFile = quotedFile.gsub("\0", "") 
File.open("#{file_path}"'unquoted_file.tab',"w") { |file| file.puts replace } 

我在這裏假設NULL是唯一的轉義字段。如果不是這種情況,則使用默認的quote_char: '"'gsub(',"",', ''),它應該處理差不多所有可能的包含特殊字符的字段的情況。

但是,當您注意到您的查詢結果很大時,您可能會更爲實際地自行準備csv文件,並避免兩次處理輸出。你可以簡單地寫:

File.open("#{file_path}"'unquoted_file.tab',"w") do |file| 
    csv.puts ["Key","channel"]  
    series_1_results.each_hash do |series_1| 
     csv.puts ["#{series_1['key']},#{series_1['channel']}"] 
    end 
end 

再一次,你可能需要處理特殊字符的字段。

1

首先,製表符分隔的文件是「TSV」,而不是逗號分隔的文件是「CSV」。

任何時候在字段中可能出現字段分隔符時,都需要在字段周圍包裝引號。

例如,你打算如何將此字符串嵌入製表符分隔的文件中?

Foo\tbar 

\t是嵌入式標籤的表示。

使用包含逗號的字段編寫CSV文件時會發生同樣的問題。該字段必須用雙引號括起來分隔字段本身。

+0

數據中沒有任何製表符。我可以把包含一些文本引號的字段包裝起來,因爲你是對的,最好是擁有它。但是,我怎樣才能讓NULL字段沒有引號?如果我刪除quote_char:所有字段都有引號。你有什麼建議? – analyticsPierce 2013-05-10 07:34:09

1

如果您的輸入包含任何需要轉義的數據(例如列分隔符或引號字符),則您需要引用您的數據。否則,以後無法正確解析。

CSV.open('test.csv', 'wb', col_sep: "\t") do |csv| 
    csv << ["test", "'test'", '"test"', nil, "test\ttest"] 
end 

puts open('test.csv').read 
#test 'test' """test"""    "test test" 

CSV類不會不必要地引用任何內容(如上所示)。所以我不知道你爲什麼說所有的領域都被引用。它可能以某種方式force_quotes在某處被設置爲真。

如果你絕對肯定您的數據永遠不會包含\t",那麼默認quote_char")應該工作得很好。否則,如果您想避免引用任何內容,則需要選擇另一個引號字符,即,絕對確定不會出現在您的數據中。

CSV.open('test.csv', 'wb', col_sep: "\t", quote_char: "|") do |csv| 
    csv << ["test", "'test'", nil, '"test"'] 
end 

puts open('test.csv').read 
#test 'test'   "test" 
3

Ruby CSV文檔中,在選項中設置force_quotes: false似乎工作。

CSV.open("#{file_path}"'file.tab', "wb", { col_sep: "\t", force_quotes: false }) do |csv| 

以上是訣竅。我建議不要將quote_char設置爲\0,因爲這不符合預期。

雖然有一點需要注意。如果該字段爲空字符串"" - 則會強制將quote_char打印到CSV中。但奇怪的是nil的值沒有。我建議,如果根本就是在等待數據中的空字符串,那麼在寫入CSV時(可能使用ActiveSupport presence方法或類似方法),您可以將它們轉換爲nil