Expand description
dbase is rust library meant to read and write dBase / FoxPro files.
Theses files are nowadays generally found in association with shapefiles.
§Reading
The Reader is the struct that you’ll need to use in order to read the content of a dBase file.
Once you have access to the records, you will have to match
against the real
FieldValue
§Examples
use dbase::FieldValue;
let records = dbase::read("tests/data/line.dbf")?;
for record in records {
for (name, value) in record {
println!("{} -> {:?}", name, value);
match value {
FieldValue::Character(Some(string)) => println!("Got string: {}", string),
FieldValue::Numeric(value) => println!("Got numeric value of {:?}", value),
_ => {}
}
}
}
You can also create a Reader and iterate over the records.
let mut reader = dbase::Reader::from_path("tests/data/line.dbf")?;
for record_result in reader.iter_records() {
let record = record_result?;
for (name, value) in record {
println!("name: {}, value: {:?}", name, value);
}
}
§Other Codepages / Encodings
As baseline, dbase-rs only suppors Utf8 and Utf8-lossy encodings, meaning only files using strings in ASCII encoding will properly be deccoded. However, two optional features exist to work with non-ASCII encodings:
- yore: uses the yore crate supports most code pages
- encoding_rs: uses the encoding_rs crate, supports notably the GBK encoding
If both feature are activated, “yore” takes the priority.
To force the use of a particular encoding:
use yore::code_pages::CP850;
let mut reader = dbase::Reader::from_path_with_encoding("tests/data/cp850.dbf", CP850)?;
let records = reader.read()?;
assert_eq!(records[0].get("TEXT"), Some(&dbase::FieldValue::Character(Some("Äöü!§$%&/".to_string()))));
The functions that do not take an encoding as parameter, use UnicodeLossy
by default,
they try to read all data as Unicode and replace unrepresentable characters with the unicode
replacement character. Alternatively Unicode
is available, to return an Err
when data
can’t be represented as Unicode.
§Deserialisation
If you know what kind of data to expect from a particular file you can use implement the ReadbableRecord trait to “deserialize” the record into your custom struct:
use std::io::{Read, Seek};
use dbase::Encoding;
struct StationRecord {
name: String,
marker_col: String,
marker_sym: String,
line: String,
}
impl dbase::ReadableRecord for StationRecord {
fn read_using<R1, R2>(field_iterator: &mut dbase::FieldIterator<R1, R2>) -> Result<Self, dbase::FieldIOError>
where R1: Read + Seek,
R2: Read + Seek,
{
use dbase::Encoding;
Ok(Self {
name: field_iterator.read_next_field_as()?.value,
marker_col: field_iterator.read_next_field_as()?.value,
marker_sym: field_iterator.read_next_field_as()?.value,
line: field_iterator.read_next_field_as()?.value,
})
}
}
let mut reader = dbase::Reader::from_path("tests/data/stations.dbf")?;
let stations = reader.read_as::<StationRecord>()?;
assert_eq!(stations[0].name, "Van Dorn Street");
assert_eq!(stations[0].marker_col, "#0000ff");
assert_eq!(stations[0].marker_sym, "rail-metro");
assert_eq!(stations[0].line, "blue");
If you use the serde
optional feature and serde_derive crate you can have the
ReadbableRecord impletemented for you
extern crate serde_derive;
use std::io::{Read, Seek};
use serde_derive::Deserialize;
#[derive(Deserialize)]
struct StationRecord {
name: String,
marker_col: String,
marker_sym: String,
line: String,
}
let mut reader = dbase::Reader::from_path("tests/data/stations.dbf")?;
let stations = reader.read_as::<StationRecord>()?;
assert_eq!(stations[0].name, "Van Dorn Street");
assert_eq!(stations[0].marker_col, "#0000ff");
assert_eq!(stations[0].marker_sym, "rail-metro");
assert_eq!(stations[0].line, "blue");
§Writing
In order to get a TableWriter you will need to build it using its TableWriterBuilder to specify the fields that constitute a record.
As for reading, you can serialize structs into a dBase file, given that they match the declared fields in when building the TableWriterBuilder by implementing the WritableRecord.
§Examples
let mut reader = dbase::Reader::from_path("tests/data/stations.dbf")?;
let mut stations = reader.read()?;
let mut writer = dbase::TableWriterBuilder::from_reader(reader)
.build_with_file_dest("stations.dbf").unwrap();
stations[0].get_mut("line").and_then(|_old| Some("Red".to_string()));
writer.write_records(&stations)?;
use dbase::{TableWriterBuilder, FieldName, WritableRecord, FieldWriter, FieldIOError, Encoding};
use std::convert::TryFrom;
use std::io::{Cursor, Write};
struct User {
nick_name: String,
age: f64
}
impl WritableRecord for User {
fn write_using<'a, W>(&self, field_writer: &mut FieldWriter<'a, W>) -> Result<(), FieldIOError>
where W: Write
{
field_writer.write_next_field_value(&self.nick_name)?;
field_writer.write_next_field_value(&self.age)?;
Ok(())
}
}
let mut writer = TableWriterBuilder::new()
.add_character_field(FieldName::try_from("Nick Name").unwrap(), 50)
.add_numeric_field(FieldName::try_from("Age").unwrap(), 20, 10)
.build_with_dest(Cursor::new(Vec::<u8>::new()));
let records = User{
nick_name: "Yoshi".to_string(),
age: 32.0,
};
writer.write_record(&records).unwrap();
If you use the serde optional feature and serde_derive crate you can have the WritableRecord implemented for you.
extern crate serde_derive;
use serde_derive::Serialize;
use dbase::{TableWriterBuilder, FieldName, WritableRecord, FieldWriter};
use std::convert::TryFrom;
use std::io::{Cursor, Write};
#[derive(Serialize)]
struct User {
nick_name: String,
age: f64
}
let writer = TableWriterBuilder::new()
.add_character_field(FieldName::try_from("Nick Name").unwrap(), 50)
.add_numeric_field(FieldName::try_from("Age").unwrap(), 20, 10)
.build_with_dest(Cursor::new(Vec::<u8>::new()));
let records = vec![User{
nick_name: "Yoshi".to_string(),
age: 32.0,
}];
writer.write_records(&records);
§File
This crate also has a third option to handle dbase files, the File struct.
This struct allows to read/write an existing or new file without having to fully read it first.
Re-exports§
pub use crate::encoding::Encoding;
pub use crate::encoding::Unicode;
pub use crate::encoding::UnicodeLossy;
pub use yore;
Modules§
- encoding
- Support for working with different codepages / encodings.
Macros§
- dbase_
record - macro to define a struct that implements the ReadableRecord and WritableRecord
Structs§
- BufRead
Write File - Date
- dBase representation of date
- Date
Time - FoxBase representation of a DateTime
- Error
- The error type for this crate
- FieldIO
Error - Field
Index - Index to a field in a record
- Field
Info - Struct giving the info for a record field
- Field
Iterator - Iterator over the fields in a dBase record
- Field
Name - Wrapping struct to create a FieldName from a String.
- Field
Ref - ‘reference’ to a field in a dBase file.
- Field
Writer - Struct that knows how to write a record
- File
- Handle to a dBase File.
- Named
Value - Simple struct to wrap together the value with the name of the field it belongs to
- Reader
- Struct with the handle to the source .dbf file Responsible for reading the content
- Reader
Builder - Convenience builder to create a reader directly from file sources
- Reading
Options - Options related to reading
- Record
- Type definition of a generic record. A .dbf file is composed of many records
- Record
Index - Index to a record in a dBase file
- Record
Iterator - Iterator over records contained in the dBase
- Record
Ref - ‘reference’ to a record in a dBase file.
- Table
Info - Structs containing the information allowing to create a new TableWriter which would write file with the same record structure as another dbase file.
- Table
Writer - Structs that writes dBase records to a destination
- Table
Writer Builder - Builder to be used to create a TableWriter.
- Time
- FoxBase representation of a time
Enums§
- Code
Page Mark - Error
Kind - Field
Conversion Error - Errors that can happen when trying to convert a FieldValue into a more concrete type
- Field
Type - Enum listing all the field types we know of
- Field
Value - Enum where each variant stores the record value
- Trim
Option
Traits§
- Readable
Record - Trait to be implemented by structs that represent records read from a dBase file.
- Writable
Record - Trait to be implemented by struct that you want to be able to write to (serialize) a dBase file
Functions§
- read
- One-liner to read the content of a .dbf file