2012-05-18 30 views
7

Tôi sử dụng ứng dụng iPhone định kỳ gửi email cho tôi nhật ký ở định dạng CSV. Tôi có một tập lệnh ruby ​​tổng hợp dữ liệu trong nhật ký đó với các nhật ký cũ hơn. Gần đây, nhà phát triển ứng dụng đã phát hành bản cập nhật, vì một số lý do không xác định, hãy thêm một dấu xuống dòng vào cuối mỗi dòng, khiến cho tập lệnh của tôi bị lỗi. Theo tài liệu, theo mặc định, :row_end phải là :auto, phải chấp nhận \r\n hoặc \n (trong 1.9.2). Tôi đã thử sử dụng Ruby 1.8.7, 1.9.2 và FasterCSV với 1.8.7. Tôi nhận được thông báo lỗi khác nhau với những cố gắng khác nhau, bao gồmRuby CSV không hiểu r n là hàng cuối

  • CSV::IllegalFormatError
  • lĩnh vực không thể viện chứng không cho phép \r hay \n (dòng 1) (FasterCSV::MalformedCSVError)
  • không thể dup NilClass (TypeError)

trong 1.9.2. (Các \r không phải là trong một lĩnh vực, đó là sự kết thúc của dòng!) Các dữ liệu trước đây trông như thế này:

03-12-2012 07:59,120.0, 
03-11-2012 08:27,120.0, 
03-10-2012 07:57,120.0, 

Bây giờ nó trông như thế này:

03-12-2012 07:59,120.0,^M 
03-11-2012 08:27,120.0,^M 
03-10-2012 07:57,120.0,^M 

Nghĩ rằng CSV có thể nghĩ các ^M là trong lĩnh vực cuối cùng, tôi đã cố gắng thêm một dấu phẩy khác:

03-12-2012 07:59,120.0,,^M 

vô ích.

Điều duy nhất tôi có thể tưởng tượng là CSV yêu cầu tất cả các trường phải nằm trong dấu ngoặc kép? Tôi có thể nghĩ về các cách giải quyết khác nhau, chẳng hạn như đọc tập tin đầu tiên, chomping kết thúc, sau đó xử lý mảng với CSV, nhưng trước tiên tôi muốn tìm hiểu những gì tôi đang làm sai. Có vẻ như nó sẽ hoạt động.

Bằng cách mã của tôi chỉ đơn giản là:

CSV.foreach(File.join($import_dir, file)) do |record| 

và tôi đã cố gắng thiết lập :row_end => "\r\n" vô ích.

Tôi đang sử dụng Mac OS X 10.6.8.

Trả lời

3

trình cho tôi trong 1.9.3:

[email protected]:~$ irb 
1.9.3p0 :001 > require 'csv' 
=> true 
1.9.3p0 :002 > CSV.foreach("rn.csv") do |row| 
1.9.3p0 :003 > p row 
1.9.3p0 :004 > end 
["1","2","3","4","5"] 
["6","7","8","9","10"] 

Và các tập tin không thực sự có tự xuống dòng trong đó:

[email protected]:~$ od -a rn.csv 
0000000 1 , 2 , 3 , 4 , 5 cr nl 6 , 7 , 8 
0000020 , 9 , 1 0 cr nl 
0000027 
+2

Cảm ơn lời khuyên. Đã không nghĩ đến việc nhìn vào tập tin với od. Tắt dòng kết thúc bằng \ r \ r \ n. – chetstone

3

Bạn đã đề cập đến thử :row_end => '\r\n'. Dấu nháy đơn xử lý (hầu hết các trường hợp) dấu gạch chéo ngược dưới dạng ký tự gạch chéo thông thường; hãy thử :row_end => "\r\n", với dấu ngoặc kép.

+0

Lỗi của tôi. Tôi đã thử điều đó. Cùng một vấn đề. – chetstone

5

Hãy thử thiết lập các row_end để

"\r\n" 

này khác với '\ r \ n': chuỗi trích dẫn đơn chỉ cho phép bạn thoát khỏi 'và \, bất cứ điều gì khác được coi là một \ theo nghĩa đen, tức là

'\r' == "\\r" 

là đúng

+0

Xin lỗi, quên đề cập đến tôi cũng đã thử điều đó. – chetstone

2

Các dòng của tập tin thực sự kết thúc với \ r \ r \ n, không \ r \ n Đây là lúng túng, tôi nên kiểm tra tệp chi tiết hơn. Tôi giả định rằng kết thúc của dòng là \ n, vì tôi đang ở trên một hộp Unix. Nhưng khi Emacs mở tệp, nó sẽ tự động chuyển sang chế độ "DOS" để nó hiển thị \ r \ n dưới dạng dòng mới và chỉ hiển thị phần bổ sung là "^ M"

+0

Đây là trường hợp của tôi. Vim cho thấy '\ r' bổ sung là'^M' và các dòng thực sự kết thúc bằng '\ r \ r \ n'. Xem ra mọi người. – ElDog

6

Vì CSV cần đọc/phân tích cú pháp toàn bộ tệp khi row_end là tự động, tôi cần thực hiện các bước sau để ngăn chặn định dạng và mã hóa ngoại lệ.

  • Giải mã các tập tin thông qua File.read
  • Hủy bỏ những kí tự xuống dòng pesky (có thể là một hoặc nhiều)
  • Phân tích các tập tin sạch như CSV
file = File.read(temp_file.path, encoding: 'ISO-8859-1:UTF-8') 
file = file.tr("\r", '') 

CSV.parse(file, headers: true) do |row| 
    # do all the things 
end 

Lưu ý: Tôi đang sử dụng phiên bản Ruby 2.1.3 cho ứng dụng Rails 4.

Các vấn đề liên quan