Skip to content

Instantly share code, notes, and snippets.

@mamantoha
Last active December 10, 2015 06:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mamantoha/4397089 to your computer and use it in GitHub Desktop.
Save mamantoha/4397089 to your computer and use it in GitHub Desktop.
Convert Dbase (.dbf) file to SQLite3 database on Ruby. My special case.
# 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