跳轉到內容

Rust 新手程式設計師指南/CSV 程式/CSV 檔案和解析

來自華夏公益教科書,開放的書籍,開放的世界

新增 CSV 檔案和解析

[編輯 | 編輯原始碼]

好的,讓我們再次使用 'cargo new csv-program' 建立一個新的 cargo 程式。

對於我們的測試 csv 檔案,我們將使用這個簡單的字母頻率 csv 檔案

"Letter","Frequency","Percentage"
"A",24373121,8.1
"B",4762938,1.6
"C",8982417,3.0
"D",10805580,3.6
"E",37907119,12.6
"F",7486889,2.5
"G",5143059,1.7
"H",18058207,6.0
"I",21820970,7.3
"J",474021,0.2
"K",1720909,0.6
"L",11730498,3.9
"M",7391366,2.5
"N",21402466,7.1
"O",23215532,7.7
"P",5719422,1.9
"Q",297237,0.1
"R",17897352,5.9
"S",19059775,6.3
"T",28691274,9.5
"U",8022379,2.7
"V",2835696,0.9
"W",6505294,2.2
"X",562732,0.2
"Y",5910495,2.0
"Z",93172,0.0

只需將此複製並貼上到專案根目錄下的一個新檔案中,即直接在 csv-program 下,名為 'letter_frequency.csv'。然後我們可以開始編碼。

首先,我們將用 Rust 將檔案讀入字串。為此,我們可以使用非常方便的函式 std::fs::read_to_string。 再次,我們將 'use std::fs;' 以便在呼叫函式時更加方便。

use std::fs;
fn main() {
    let csv_file = fs::read_to_string("letter_frequency.csv").unwrap();
   
    println!("{}", csv_file);
}

如果我們執行它,我們應該看到檔案內容被列印到終端!

現在我們想逐行解析檔案。第一行應該以不同的方式處理,因為它應該是檔案標題。為此,我們可以使用 str 上的 lines() 函式。 這給了我們一個迭代器,但我們需要學習迭代器的基礎知識才能將其用於我們想要的東西。

迭代器的工作原理
[編輯 | 編輯原始碼]

迭代器是一個實現了 'Iter' 特徵的結構體。這個特徵只要求結構體具有以下函式

fn next(&mut self) -> Option<Self::Item>;

所有其他行為都可以從此函式推匯出。關於此函式值得注意的是,它需要結構體的可變引用,這意味著一旦迭代器使用過一次,它就被用完了,不能再使用。另一個值得注意的事情是,它返回一個迭代器型別的 Option,這就是我們如何知道它是否完成的方式;如果迭代器還有剩餘專案,它會返回 Some() 的專案,如果迭代器已完成,則返回 None。

因此,我們可以這樣做來獲取第一行

fn main() {
     let csv_file = fs::read_to_string("letter_frequency.csv").unwrap();
     
     let mut lines_iter = csv_file.lines();
     let first_line = lines_iter.next().unwrap();
     for line in lines_iter {
         //parse individual line
     }
}

注意,我們仍然可以在去除第一行後在正常的 for 迴圈中使用迭代器,它將遍歷除第一行之外的所有行。此外,我們只簡單地解包第一行,因為我們提供的是檔案,我們可以假設它會有第一行,但這可能不適用於所有檔案。

為了根據逗號分割每行,我們可以使用 split 函式,它可以接收一個字串或字元,並輸出一個包含字串不同部分的迭代器。但我們想將這些部分儲存在一個向量中,這可以透過使用 collect() 函式來完成,所以讓我們將其全部封裝到自己的函式中

fn split_string(input: &str) -> Vec<&str> {
    input.split(',').collect()
}

然後我們像這樣更改 main 函式

fn main() {
    let csv_file = fs::read_to_string("letter_frequency.csv").unwrap();
    let mut lines_iter = csv_file.lines();
    let first_line = lines_iter.next().unwrap();
    let headers = split_string(first_line);
    // do something with headers??
    for line in lines_iter {
        //parse individual line
        let values = split_string(line);
       
        // do something with values??
    }
}

下一步:從我們的 csv 檔案解析數字

華夏公益教科書