Tìm hiểu thư viện xử lý file CSV trong Ruby
Giới thiệu chung Trong các ứng dụng quản lý việc xử lý nhập/xuất dữ liệu từ file có định dạng như xlsx hay csv là công việc cơ bản và cần thiết. Công việc xử lý của ứng dụng với những định dạng file này không chỉ tạo sự tiện lợi trong quá trình trao đổi, lưu trữ thông tin giữa người dùng với ứng ...
Giới thiệu chung
Trong các ứng dụng quản lý việc xử lý nhập/xuất dữ liệu từ file có định dạng như xlsx hay csv là công việc cơ bản và cần thiết. Công việc xử lý của ứng dụng với những định dạng file này không chỉ tạo sự tiện lợi trong quá trình trao đổi, lưu trữ thông tin giữa người dùng với ứng dụng mà còn giúp lập trình viên thao tác với dữ liệu nhanh chóng và dễ dàng hơn. Bài viết này trình bày cách nhập/xuất dữ liệu và các thao tác xử lý dữ liệu từ file CSV.
Xử lý file CSV trong Ruby
Giả xử ta có một bảng tính để quản lý thông tin tất cả khách hàng của một nhà hàng, mỗi hàng bao gồm các thông tin sau.
- Tên khách hàng
- Tổng số lần khách hàng đã đến nhà hàng và sử dụng đồ ăn
- Tổng số tiền chi tiêu
- Đánh giá của khách hàng về món ăn của nhà hàng.
Ví dụ với 4 khách khách hàng
Dan,34,2548,Lovin it! Maria,55,5054,"Good, delicious food" Carlos,22,4352,"I am ""pleased"", but could be better" Stephany,34,6542,I want bigger steaks!!!!!
Ta thấy ở phần đánh giá khách hàng ở hàng 2 và 3, có chứa dấu phẩy, ta cần đưa toàn bộ chuỗi đó vào trong dấu nháy kép. Phức tạp hơn ở hàng 3, ta muốn đưa từ "pleased" vào nháy kép thì phải gấp đôi nháy kép đó lên.
Ví dụ trên cũng là cấu trúc cơ bản một file định dạng CSV, tiếp theo ta sẽ tìm hiểu Ruby xử lý một file CSV như thếo nào.
Giả sử ta có file customers.csv chứa dữ liệu khách hàng như ở ví dụ trên. Làm thế nào để nhập dự liệu từ file đó vào vào ứng dụng Ruby. Trong Ruby bạn có thể nhập tất cả nội dung một file vào trong bộ nhớ, hoặc nhập từng hàng. Mỗi phuơng pháp đều có ưu điểm và khuyết điểm của nó. Ví dụ với file có 300.000 dòng và máy tính có cấu hình khiêm tốn (ram 512Mb) thì việc nhập đồng thời toàn bộ nội dung file vào bộ nhớ là điều không nên, vì chuơng trình của bạn sẽ crash ngay lập tức. Ruby lưu trữ mỗi hàng của bảng thành một mảng, mỗi phần tử mảng là một string chứa nội dung từng ô (cell).
Để minh họa, ta sẽ nhập dữ liệu từ file customers.csv. Ta thực hiện với phuơng thức "read" tham số là đường dẫn đến file. Phuơng thức này sẽ đọc toàn bộ tập tin và lưu trữ nó vào trong biến customers.
require 'csv' customers = CSV.read('customers.csv')
Biến customers trở thành một mảng lớn, là mảng chứa mảng, mỗi mảng con là một hàng trong file csv.
Bằng cách khác, ta đọc file trên bằng cách đọc từng dòng. Chúng ta có thể làm điều đó bằng cách sử dụng phuơng thức CSV.foreach, đối số truyền vào là chuỗi đường dẫn file csv.
CSV.foreach('customers.csv') do |row| puts row.inspect end
Kết quả như sau:
["Dan", "34", "2548", "Lovin it!"] ["Maria", "55", "5054", "Good, delicious food"] ["Carlos", "22", "4352", "I am "pleased", but could be better"] ["Stephany", "34", "6542", "I want bigger steaks!!!!!"]
Mọi xử lý với file CSV đều duơí dạng string.
Thư viện CSV cũng có thể xử lý chuỗi
Xử dụng phuơng thức CSV.parse để đưa một chuỗi thành dạng thể hiện cho dữ liệu file csv.
a_string = "Dan,34 Maria,55" CSV.parse(a_string) #=> [["Dan", "34"], ["Maria", "55"]]
Ví dụ
Nhập dữ liệu từ file csv
Nhập dữ liệu từ file csv và lưu và database
Bước 1: Tạo model có tên customer gồm các thuộc tính là: name, total_visited, total_money, feedback
rails g model customer name:string total_visited:integer total_money:float feedback:string rake db:migrate
Bước 2: Tạo task
# create lib/tasks/import.rake
rails g task import customer
Bước 3: Đọc dữ liệu từ file csv vào lưu cào database
customers.csv file
Name,Times arrived,Total $ spent,Food feedback Dan,34,2548,Lovin it! Maria,55,5054,"Good, delicious food" Carlos,22,4352,"I am ""pleased"", but could be better" Stephany,34,6542,I want bigger steaks!!!!!
require "csv" namespace :import do desc "Import customer from csv file" task customer: :environment do # get customers.csv customers_file = Rails.root + "public/customers.csv" # Read line-by-line and save it to database as a customer object CSV.foreach(customers_file, headers: true) do |row| Customer.create!(name: row[1], total_visited: row[2], total_money: row[3], feedback: row[4]) end end end
Run task: rake import:customer
Buớc 5: Kiểm tra database
- Mở cửa sổ console rails c
- Gõ lệnh Customer.all để kiểm tra
Xuất dữ liệu ra file Excel hoặc CSV
Bước 1: Config
# /config/application.rb require "csv"
# /config/initializers/mime_types.rb Mime::Type.register "application/xls", :xls
Bước 2: Tạo controller CustomersController
rails g controller customers index
class CustomersController < ApplicationController def index @customers = Customer.order(:name) respond_to do |format| format.html format.csv {send_data @customers.to_csv} format.xls {send_data @customers.to_csv(col_sep: " ")} end end end
Bước 3: Xây dựng phuơng thức to_csv cho model Customer
class Customer < ActiveRecord::Base def self.to_csv(options = {}) CSV.generate(options) do |csv| csv << column_names all.each do |customer| csv << customer.attributes.values_at(*column_names) end end end end
Bước 4: Xây dựng giao diện
<h1>Customers</h1> <p> Download: <%= link_to "CSV", customers_path(format: "csv") %> | <%= link_to "Excel", customers_path(format: "xls") %> </p> <table border="1"> <tr> <th>ID</th> <th>Name</th> <th>Release Date</th> <th>Price</th> </tr> <% @customers.each do |customer| %> <tr> <td><%= customer.name %></td> <td><%= customer.total_visited %></td> <td><%= customer.total_money %></td> <td><%= customer.feedback %></td> </tr> <% end %> </table>
Kết quả
Kết luận
Trong bài viết này đã trình bày cấu trúc một file CSV, những phuơng thức cơ bản cung cấp bởi thư viện CSV Ruby để thao tác với nhưng file bảng tính như csv, excel ...
Nguồn tham khảo
https://www.sitepoint.com/guide-ruby-csv-library-part/
http://railscasts.com/episodes/396-importing-csv-and-excel?view=asciicast