Last active
December 10, 2015 06:48
-
-
Save mamantoha/4397089 to your computer and use it in GitHub Desktop.
Convert Dbase (.dbf) file to SQLite3 database on Ruby. My special case.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
require 'dbf' | |
require 'ruby-progressbar' | |
require 'sqlite3' | |
require 'getoptlong' | |
module DBF | |
module Column | |
class Base | |
attr_reader :name, :type, :length, :decimal | |
# Not strip non-ascii characters from column names | |
def initialize(name, type, length, decimal, version, encoding = nil) | |
@name, @type, @length, @decimal, @version, @encoding = clean(name, encoding), type, length, decimal, version, encoding | |
raise LengthError, "field length must be greater than 0" unless length > 0 | |
raise NameError, "column name cannot be empty" if @name.length == 0 | |
end | |
def clean(value, encoding) | |
value.force_encoding(encoding).encode('utf-8') | |
end | |
end | |
end | |
end | |
def trans | |
{ | |
0 => { ua: 'Телефон', eng: 'telephone' }, | |
1 => { ua: 'Назва', eng: 'name' }, | |
2 => { ua: 'Місто', eng: 'city' }, | |
3 => { ua: 'Вулиця', eng: 'street' }, | |
4 => { ua: 'Будинок', eng: 'house' }, | |
5 => { ua: 'Квартира', eng: 'apartment' }, | |
} | |
end | |
if __FILE__ == $0 | |
dbf_file = nil | |
sqlite3_file = nil | |
table = 'phones' | |
opts = GetoptLong.new( | |
[ '--help', '-h', GetoptLong::NO_ARGUMENT ], | |
[ '--output', '-o', GetoptLong::REQUIRED_ARGUMENT ], | |
) | |
opts.each do |opt, arg| | |
case opt | |
when '--help' | |
puts "#{File.basename(__FILE__)} [dbf file] -o [sqlite3 file] | |
" | |
exit | |
when '--output' | |
sqlite3_file = arg | |
end | |
end | |
dbf_file = ARGV.shift | |
abort "You must supply a DBF filename on the command line" unless dbf_file | |
dbf_table = DBF::Table.new(dbf_file, nil, 'cp1251') | |
dbf_columns = dbf_table.columns | |
sql = "create table #{table} (\n" | |
sql << "\tid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n" | |
sql << (0..5).map do |i| | |
"\t#{trans[i][:eng]} varchar(#{dbf_columns[i].length})" | |
end.join(",\n") | |
sql << "\n);" | |
puts sql | |
File.delete(sqlite3_file) if File.exist?(sqlite3_file) | |
sql_db = SQLite3::Database.new(sqlite3_file) | |
sql_db.execute_batch(sql) | |
pbar = ProgressBar.create(title: 'data processing', total: dbf_table.record_count, format: '%a |%b>>%i| %p%% (%c of %C) %t') | |
columns = trans.values.map{ |h| h[:eng] }.join(',') | |
sql_db.transaction do |db| | |
dbf_table.each do |record| | |
db.execute("INSERT INTO #{table} (#{columns}) VALUES (?,?,?,?,?,?)", record.attributes.values) | |
pbar.increment | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment