2015-05-26 24 views
0

我試圖導入使用the csv crate一個CSV文件,但問題是,有些字段包含非UTF8值,所以我得到一個運行時的恐慌:處理運行時的恐慌與嘗試宏

thread '<main>' panicked at 'called `Result::unwrap()` on an `Err` value: Decode("Could not convert bytes \'FromUtf8Error { bytes: [75, 108, 105, 110, 63, 101, 107, 111, 118, 225], error: Utf8Error { valid_up_to: 9 } }\' to UTF-8.")', /home/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libcore/result.rs:729 

這是我的代碼看起來像:

extern crate csv; 

fn main() { 
    let mut rdr = csv::Reader::from_file("data.csv").unwrap(); 
    for record in rdr.decode() { 
     let rec: Vec<String> = record.unwrap(); 
     println!("{}", rec[0]); 
    } 
} 

我想錯誤處理是驚情不知何故,所以我在想,也許我應該用try!宏是什麼?事情是這樣的:

let rec: Vec<String> = try!(record.unwrap()); 

當然,這是產生錯誤

error: the trait `rustc_serialize::serialize::Decodable` is not implemented for the type `core::result::Result<_, _>` [E0277] 

什麼是正確的語法?

+2

如果你想在編碼方面更健壯,'rust-encoding'應該有所幫助:https://lifthrasiir.github.io/rust-encoding/encoding/ ---或者,你可以解碼爲'Vec >'如果你只是想完全忽略編碼。 – BurntSushi5

回答

5

您所面臨的兩個問題:

  1. 這不是如何try!宏工作
  2. 不能在main

try! macro使用try!是非常簡單的。它所做的只是看看參數是否爲Result::Err。如果是,則從當前函數返回錯誤。如果參數是Result::Ok,則提取內部值並且是評估try!的結果。請注意,參數必須始終爲Result

第二個問題是main被定義爲不返回任何值。這意味着你不能主要使用try!,因爲try!想要返回一個值。相反,你需要處理錯誤「手動」方式:

extern crate csv; 

fn main() { 
    let mut rdr = match csv::Reader::from_file("data.csv") { 
     Ok(file) => file, 
     Err(e) => println!("Put nicer error handling here"), 
    }; 

    for record in rdr.decode() { 
     let rec: Vec<String> = match record { 
      Ok(rec) => rec, 
      Err(e) => println!("Put nicer error handling here"), 
     }; 
     println!("{}", rec[0]); 
    } 
} 

我想出錯處理這種恐慌局面在某種程度上

這是一個普遍的誤解。你不能處理恐慌。它們不是例外(Rust沒有例外)。恐慌意味着線程死亡。你可以做的最好的是產生一個線程並處理那個線程正在死亡。你真的不需要做任何具體的事情。這就是Result類型的全部內容。 Result::unwrapOption::unwrap是表示「如果這不是{Ok,Some},那麼現在恐慌」的方法。