ðŸ Rustã§ãããããªãã©ãŒãããã®CSVãæ±ã(csvã¯ã¬ãŒã)
ããã¯äœ
Rustã§ãããããªãã©ãŒãããã®CSVãèªã¿æžãããæ©äŒããã£ãã®ã§ãåå¿é²ããŠãæžããŠããã
å
¬åŒã®ããã¥ã¡ã³ãããã¥ãŒããªã¢ã«ã«æžããŠããå
容ãã»ãšãã©ã ãããã£ãšç解ããã®ãé£ããã£ããã
ããããããšããéåŒãã§æ¢ããããã«ãŸãšããŠã¿ã(ã€ãã)ã
BurntSushi/rust-csv (csvã¯ã¬ãŒã)
BurntSushi/rust-csvã¯Rustã§CSVããŒã¿ãèªã¿æžãããããšãã§ãã人æ°ã®ã©ã€ãã©ãªãäœè
ã®BurntSushiæ°ã¯é«éãªgrep代æ¿ã³ãã³ãã©ã€ã³ããŒã« ripgrep ã®éçºè
ãšããŠãç¥ãããŠããã
ã¯ã¬ãŒãå㯠csv
ãšãªã£ãŠããã
以äžã䟿å®äžcsvã¯ã¬ãŒããšåŒç§°ããã
crates.io
docs.rs
BurntSushiæ°ã®ããã°
docs.rsã®ãã¥ãŒããªã¢ã«
ããã°ã®æ¥æ¬èªèš³ (Qiita)
æºå
ãµã³ãã«çšã®ãããžã§ã¯ããäœæããã
mkdir rust-csv-example && cd rust-csv-example
cargo init
cargo add csv
Cargo.tomlã¯æ¬¡ã®ããã«ãªã£ãŠããã
[package]
name = "rust-csv-example"
version = "0.1.0"
edition = "2021"
[dependencies]
csv = "1.3.1"
æµã
csvã¯ã¬ãŒãã䜿ã£ãCSVããŒã¿ã®èªã¿æžãã®æµãã¯ããããŸãã«äžèšã®ããã«ãªãã
ãªããä»äžããŠãããçªå·ã¯ãããŸã§æµãã説æããããã®ãã®ãªã®ã§ãå®éã®åŠçé ãã³ãŒãã®èšè¿°é ãšäžèŽãããšã¯éããªãã
èªã¿èŸŒã¿
CSVããŒã¿ã®èªã¿èŸŒã¿(Read)ã¯æ¬¡ã®ãããªæµãã§è¡ããåæ§ã«ãªãã·ã§ãã«ãªæäœã¯ã«ãã³ã§ç€ºãã
- (ãããã³ã°ããããã®æ§é äœã¯HashMapã®çšæ)
- å ¥åããããã¡ã€ã«ãã¹ããªãŒã ã®çšæ
- (ãšã³ã³ãŒãã£ã³ã°çã®ååŠç)
-
csv::Reader
ã®åæå (ã«ã¹ã¿ã Readerãäœãå Žåã¯csv::ReaderBuilder
ã䜿ã) - ã¬ã³ãŒãã®èªã¿åã
- (æ§é äœãHashMapãžã®ãããã³ã°:
serde
)
æžã蟌ã¿
ãŸããCSVããŒã¿ã®æžã蟌ã¿(Write)ã¯æ¬¡ã®ãããªæµãã§è¡ããåæ§ã«ãªãã·ã§ãã«ãªæäœã¯ã«ãã³ã§ç€ºããŠããã
- æžã蟌ã¿ããã¬ã³ãŒãã®å€ãåã®çšæ
- åºåããããã¡ã€ã«ãã¹ããªãŒã ã®çšæ
- (ãšã³ã³ãŒãã£ã³ã°çã®ååŠç)
-
csv::Writer
ã®åæå(ã«ã¹ã¿ã Writerãäœãå Žåã¯csv::WriterBuillder
ã䜿ã) - ã¬ã³ãŒãã®æžã蟌ã¿
- Writerã
.flush()
ããŠæ®ãã®ããŒã¿ãæžã蟌ã¿
ãã€ã³ã
csvã¯ã¬ãŒãã䜿ãäžã§ãã€ã³ãã«ãªãã®ã¯ãcsv::ReaderBuilder
ã csv::WriterBuilder
ã«ããæåã®èª¿æŽãšã¬ã³ãŒããè¡šãå csv::StringRecord
ã csv::ByteRecord
ã®åãåãã«ãªãã
CSVããŒã¿ã®èªã¿åã(Read)
Readerãäœã
CSVããŒã¿ãèªã¿èŸŒãã«ã¯ããŸã csv::Reader
ãåæåããã
ãã¡ã€ã«ããèªã¿èŸŒãå Žå㯠fn from_path<P: AsRef<Path>>(path: P) -> Result<Reader<File>>
ã¡ãœããã䜿ãã std::io::Reader
ããèªã¿èŸŒãå Žå㯠fn from_reader(rdr: R) -> Reader<R>
ã¡ãœããã䜿ãã
æšæºå
¥å std::io::Stdin
㯠std::io::Reader
ãæºãããããfrom_reader
ã«ã¯ std::io::stdin()
ãæž¡ãããšãã§ããã
let mut reader = csv::Reader::from_path("path/to/file.csv")?; // csv::Reader<File>
let mut reader = csv::Reader::from_reader(std::io::stdin()); // csv::Reader<Stdin>
ã«ã¹ã¿ã Readerãäœã
ããã©ã«ãã®CSVãªãŒããŒã®æåãã«ã¹ã¿ãã€ãºããã«ã¯ãcsv::ReaderBuilder
ã䜿ããã¡ãœãããã§ãŒã³ã®åŒæ°ã§è©³çŽ°ãªãªãã·ã§ã³ãæå®ããŠããã
csv::ReaderBuilder
ããfrom_path
ãfrom_reader
ãåŒã³åºãããšã§ãcsv::Reader
ãåæåã§ããã
let mut reader_builder = csv::ReaderBuilder::new()
.has_headers(false) // ããããŒãªã: 1è¡ç®ãç¡èŠããªã
.delimiter(b';') // ããªãã¿(åºåãæå)ãã»ãã³ãã³ãšãã
.double_quote(false) // ããã«ã¯ãªãŒãã«ãããšã¹ã±ãŒããç¡å¹ãšãã
.escape(Some(b'\\')) // ãšã¹ã±ãŒãæå
.flexible(true) // ãã¬ãã·ãã«ã¢ãŒãæå¹: åæ°ãåçã§ãã£ãŠããšã©ãŒãšããªã
.comment(Some(b'#')); // ã#ãã§å§ãŸãè¡ãã³ã¡ã³ããšã¿ãªãç¡èŠãã
let mut reader = reader_builder.from_path("path/to/file.csv")?; // csv::Reader<File>
空è¡ãç¡èŠããªãããã«ãã
csvã¯ã¬ãŒãã¯ãããã©ã«ãã§ã¯ç©ºè¡ãç¡èŠããããã«ãªã£ãŠããPythonã®csvã¢ãžã¥ãŒã«ãªã©ä»ã®ã©ã€ãã©ãªãšã¯ç°ãªãæåã«ãªã£ãŠããã
å
ã®csvã¯ã¬ãŒãã®ä»£ããã«ããã©ãŒã¯ããããªããžããªYarn/rust-csvãCargo.tomlã«è¿œå ããããšã§ csv::ReaderBuilder
ã® .skip_blank_lines(yes: bool)
ã䜿ããããã«ãªãã
.skip_blank_lines(false)
ãæå®ããããšã§CSVãèªã¿åãéã«ç©ºè¡ãç¡èŠããªãããã«ãªãã
[dependencies]
csv = { git = "https://github.com/Yarn/rust-csv.git" }
ã¬ã³ãŒããèªã¿åã
csv::Reader
ããæååã¬ã³ãŒããååŸããã«ã¯ .records()
ã¡ãœãããåŒã³åºãã
.records()
ã¯Resultã§å
ãŸãã csv::StringRecord
ã®ã€ãã¬ãŒã¿ãè¿ããnçªç®ã®å€(ã®Option)㯠record.get(n)
ã§ååŸã§ããããã®ãã£ãŒã«ãã®å€ãååšããªããã° None
ã«ãªãã
for result in reader.records() {
let record = result?;
if let Some(first_field) = record.get(0) {
dbg!(first_field);
}
if let Some(second_field) = record.get(1) {
dbg!(second_field);
}
if let Some(third_field) = record.get(2) {
dbg!(third_field);
}
}
æååã®ä»£ããã«ãã€ãåãååŸããã«ã¯ csv::Reader
ã® .byte_records()
ã¡ãœãããåŒã³åºããrecord.get(n)
ã§ãã£ãŒã«ãã®å€ãåã£ãŠãããš&[u8]
ã®Optionãšãªãã
æ§é äœã«ã¬ã³ãŒãããããã³ã°ãã
CSVã®ãã£ãŒã«ãã決ãŸããã£ãŠããå Žåã¯ã¬ã³ãŒããæ§é äœã«ãããã³ã°ãããšéœåãè¯ãã
ãã·ãªã¢ã©ã€ãºãè¡ãããã« serde ã¯ã¬ãŒããè¿œå ããã
cargo add serde -F derive
TODO
HashMapã«ã¬ã³ãŒãããããã³ã°ãã
TODO
æ¬å®¶ã«åã蟌ãŸãããšãããªã...ã
CSVããŒã¿ã®æžã蟌ã¿(Write)
Writerãäœã
ã«ã¹ã¿ã Writerãäœã
TODO
éUTF-8ã®ãã¡ã€ã«ãèªã¿æžããã
Rustã§æåã³ãŒãã®ãšã³ã³ãŒãïŒãã³ãŒããè¡ãã«ã¯ãäžè¬ã« encoding_rs ãšããã¯ã¬ãŒãã䜿ãããã
cargo add encoding_rs
encoding_rsã®åºæ¬
åãšã³ã³ãŒãã£ã³ã°æ¹åŒãè¡šã encoding_rs::Encoding
åã§å®£èšãããå€(äŸãã° SHIFT_JIS
)ã® .encode()
ã.decode()
ã¡ãœãããåŒã³åºãã
åã·ã°ããã£ã¯æ¬¡ã®ããã«ãªã£ãŠããã
pub fn encode<'a>(
&'static self,
string: &'a str,
) -> (
Cow<'a, [u8]>,
&'static Encoding,
bool
)
pub fn decode<'a>(
&'static self,
bytes: &'a [u8],
) -> (
Cow<'a, str>,
&'static Encoding,
bool
)
Shift_JISãã¡ã€ã«ãèªã¿èŸŒã
TODO
Shift_JISãã¡ã€ã«ã«æžã蟌ã
TODO
ç¹æ®ãªãã©ãŒãããã®CSVãèªã¿èŸŒã
ã·ã¹ãã éã®é£æºãIoTæ©åšã®åºåããããŒã¿ãæ±ãéã«çžŠæã¡ã®CSVãè¡ããšã«ã¬ã³ãŒãã®æå³ãåçã«å€ãããããªãããããªãã©ãŒãããã®é»æã«ééããããšããã£ãã
ãã®ãããªãã©ãŒãããã®CSVãããŒã¹ããå Žåã¯æ¬¡ã®ãããªæ¹æ³ãèããããã
- A: ãããããè¡ïŒåã®ã€ã³ããã¯ã¹ã«ã©ã®å€ãå ¥ããã®å®çŸ©ãçšæããŠããããã«åã£ãŠå€ãååŸãã
- B: ç¹å®ã®ãã£ãŒã«ãã®å€ãååŸããŠãã®å€ãããšã«ãã¿ãŒã³ãæ¯ãåãã
TODO