Rust獲取命令行參數(shù)及IO操作方法
Rust獲取命令行參數(shù)以及IO操作
Rust作為一門系統(tǒng)編程語言,提供了強大且安全的I/O操作支持。與C/C++不同,Rust通過所有權(quán)系統(tǒng)和豐富的類型系統(tǒng),在編譯期就能避免許多常見的I/O錯誤。Rust的標準庫std::io模塊包含了大多數(shù)I/O功能,而std::fs模塊則專門處理文件系統(tǒng)操作。
1、接收命令行參數(shù)
1.1 讀取參數(shù)值
Rust 標準庫提供的std::env::args 能夠獲取傳遞給它的命令行參數(shù)的值
這個函數(shù)返回一個傳遞給程序的命令行參數(shù)的 迭代器(iterator)。
use std::env; fn main() { let args: Vec<String> = env::args().collect(); println!("{:?}", args); }
首先使用 use 語句來將 std::env 模塊引入作用域以便可以使用它的 args 函數(shù)。
注意 std::env::args 函數(shù)被嵌套進了兩層模塊中。
當(dāng)所需函數(shù)嵌套了多于一層模塊時,通常將父模塊引入作用域,而不是其自身。
這便于我們利用 std::env 中的其他函數(shù)。這比增加了 use std::env::args; 后僅僅使用 args 調(diào)用函數(shù)要更明確一些,因為 args 容易被錯認成一個定義于當(dāng)前模塊的函數(shù)。
得到的第一個參數(shù)是生成的程序本身,后面都是命令行參數(shù)
在 main 函數(shù)的第一行,我們調(diào)用了 env::args,并立即使用 collect 來創(chuàng)建了一個包含迭代器所有值的 vector。
collect 可以被用來創(chuàng)建很多類型的集合,所以這里顯式注明 args 的類型來指定我們需要一個字符串 vector。
雖然在 Rust 中我們很少會需要注明類型,然而 collect 是一個經(jīng)常需要注明類型的函數(shù),因為 Rust 不能推斷出你想要什么類型的集合。
最后,我們使用調(diào)試格式 :? 打印出 vector。
注意 vector 的第一個值是 “target\debug\myargs.exe”,它是我們二進制文件的名稱。這與 C 中的參數(shù)列表的行為相匹配,讓程序使用在執(zhí)行時調(diào)用它們的名稱。
如果要在消息中打印它或者根據(jù)用于調(diào)用程序的命令行別名更改程序的行為,通常可以方便地訪問程序名稱,不過考慮到本章的目的,我們將忽略它并只保存所需的兩個參數(shù)。
注意args 函數(shù)和無效的 Unicode
注意 std::env::args 在其任何參數(shù)包含無效 Unicode 字符時會 panic。
如果你需要接受包含無效 Unicode 字符的參數(shù),使用 std::env::args_os 代替。這在某些操作系統(tǒng)中可能發(fā)生
這個函數(shù)返回 OsString 值而不是 String 值。
OsString 值每個平臺都不一樣而且比 String 值處理起來更為復(fù)雜。
use std::env; fn main() { for arg in env::args_os() { println!("{:?}", arg); } }
1.2 將參數(shù)值保存進變量
打印出參數(shù) vector 中的值展示了程序可以訪問指定為命令行參數(shù)的值?,F(xiàn)在需要將這兩個參數(shù)的值保存進變量這樣就可以在程序的余下部分使用這些值了。
use std::env; fn main() { //獲取命令行參數(shù) let args: Vec<String> = env::args().collect(); //獲取查詢字符串和文件名 let query = &args[1]; let filename = &args[2]; println!("Searching for {}", query); println!("In file {}", filename); }
正如之前打印出 vector 時所看到的,程序的名稱占據(jù)了 vector 的第一個值 args[0],所以我們從索引 1 開始。
myargs2 獲取的第一個參數(shù)是需要搜索的字符串,所以將其將第一個參數(shù)的引用存放在變量 query 中。第二個參數(shù)將是文件名,所以將第二個參數(shù)的引用放入變量 filename 中。
2、Rust讀取文件
在 Rust 中讀取文件是常見的 I/O 操作,標準庫提供了多種方法來處理文件讀取。下面我將詳細介紹各種文件讀取方法及其適用場景
2.1. 基本文件讀取
2.1.1 一次性讀取整個文件到字符串
use std::fs; use std::io; //讀取文件內(nèi)容 fn read_file(filename: &str) -> io::Result<String> { // 使用?來處理錯誤 // ?會將錯誤傳遞給調(diào)用者 // ?只能在返回Result的函數(shù)中使用 // ?會將錯誤類型從io::Error轉(zhuǎn)換為io::Result<String> //fs::read_to_string返回Result<String, io::Error> let content = fs::read_to_string(filename)?; Ok(content) } fn main() { let filename = "hello.txt"; match read_file(filename) { Ok(content) => println!("File content: {}", content), Err(e) => println!("Error: {}", e), } }
2.1.2 一次性讀取整個文件到字節(jié)向量
用于讀取二進制文件
//讀取文件到字節(jié)向量 use std::fs; use std::io; //讀取二進制文件內(nèi)容 fn read_file(filename: &str) -> io::Result<Vec<u8>> { // 使用?來處理錯誤 // ?會將錯誤傳遞給調(diào)用者 // ?只能在返回Result的函數(shù)中使用 // ?會將錯誤類型從io::Error轉(zhuǎn)換為io::Result<Vec<u8>> //fs::read返回Result<Vec<u8>, io::Error> let content = fs::read(filename)?; Ok(content) } fn main() { let filename = "123.vip"; match read_file(filename) { //打印文件的字節(jié)長度 Ok(content) => println!("File clength: {}", content.len()), Err(e) => println!("Error: {}", e), } }
2.2. 逐行讀取文件
對于大文件,逐行讀取更高效且內(nèi)存友好。
2.2.1 使用 BufReader 逐行讀取
//讀取大文件 use std::fs::File; use std::io::{ BufRead, BufReader }; //讀取大文件內(nèi)容 fn read_file(filename: &str) -> std::io::Result<()> { let file = File::open(filename)?; let reader = BufReader::new(file); for line in reader.lines() { println!("{}", line?); } Ok(()) } fn main() { let filename = "hello.txt"; match read_file(filename) { Ok(()) => println!("File content: {}", filename), Err(e) => println!("Error: {}", e), } }
特點:
內(nèi)存效率高
自動處理換行符
lines() 返回 Result<String>
,需要處理可能的錯誤
2.2.2 使用 BufReader 讀取字節(jié)塊
//使用 BufReader 讀取字節(jié)塊 use std::io::{ self, Read }; use std::fs::File; //讀取字節(jié)塊 fn read_file(filename: &str) -> io::Result<()> { let file = File::open(filename)?; let mut reader = io::BufReader::new(file); //定義一個字節(jié)緩沖區(qū) //緩沖區(qū)的大小為1024字節(jié) let mut buffer = [0; 10]; //循環(huán)讀取字節(jié)塊 //read方法會將字節(jié)塊讀取到緩沖區(qū)中 //read方法返回讀取的字節(jié)數(shù) //如果讀取到文件末尾,就退出循環(huán) loop { let n = reader.read(&mut buffer)?; if n == 0 { break; //讀取到文件末尾,退出循環(huán) } println!("Read {} bytes: {:?}", n, &buffer[..n]); // 處理 buffer[..n] } Ok(()) } fn main() { match read_file("Cargo.toml") { Ok(()) => println!("Read file successfully"), Err(e) => println!("Error: {}", e), } }
特點:
適用于二進制文件
可以控制緩沖區(qū)大小
適合網(wǎng)絡(luò)傳輸或處理大文件
2.3 使用內(nèi)存映射文件 (memmap2)
對于超大文件,內(nèi)存映射可以提高性能:
use std::fs::File; use memmap2::Mmap; fn main() -> std::io::Result<()> { let file = File::open("Cargo.toml")?; //使用memmap2映射文件到內(nèi)存,需要使用unsafe,需要注意 let mmap = unsafe { Mmap::map(&file)? }; // 假設(shè)我們搜索某個字節(jié)模式 let pattern = b"\xDE\xAD\xBE\xEF"; if let Some(pos) = mmap.windows(pattern.len()).position(|w| w == pattern) { println!("Pattern found at offset: {}", pos); } else { println!("Pattern not found"); } Ok(()) }
注意:內(nèi)存映射涉及 unsafe 代碼,需要謹慎使用。
3、Rust向文件中寫內(nèi)容
//寫入文件 use std::fs; use std::io; fn write_file(filename: &str, content: &str) -> io::Result<()> { fs::write(filename, content) } fn main() { let filename = "hello.txt"; let content = "你好,景天"; match write_file(filename, content) { Ok(()) => println!("Write file successfully"), Err(e) => println!("Error: {}", e), } }
4、Rust序列化與反序列化
使用 serde 庫可以方便地進行 I/O 操作:
需要安裝第三方庫
cargo add serde
cargo add serde_json
并且在Cargo.toml中配置
//序列化和反序列化 use serde::{ Serialize, Deserialize }; use std::fs; use serde_json; #[derive(Serialize, Deserialize, Debug)] #[allow(dead_code)] struct Person { name: String, age: u8, phones: Vec<String>, } fn main() { let person = Person { name: "John".to_string(), age: 30, phones: vec!["1234567890".to_string(), "0987654321".to_string()], }; //序列化 let json = serde_json::to_string(&person).unwrap(); //將結(jié)構(gòu)體序列化為json字符串 println!("json: {}", json); //將序列化后的數(shù)據(jù)寫入文件 fs::write("person.json", json).unwrap(); //將數(shù)據(jù)寫入文件,json的所有權(quán)已經(jīng)移動到write中了 //反序列化 // let person2: Person = serde_json::from_str(&json).unwrap(); //這里json所有權(quán)已不存在 // println!("person2: {:?}", person2); //從文件中讀取數(shù)據(jù)并反序列化 let json2 = fs::read_to_string("person.json").unwrap(); let person3: Person = serde_json::from_str(&json2).unwrap(); println!("person3: {:?}", person3); }
到此這篇關(guān)于Rust獲取命令行參數(shù)以及IO操作的文章就介紹到這了,更多相關(guān)Rust獲取命令行參數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Rust語言從入門到精通系列之Iterator迭代器深入詳解
這篇文章主要為大家介紹了Rust語言從入門到精通系列之Iterator迭代器深入詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04

解讀Rust的Rc<T>:實現(xiàn)多所有權(quán)的智能指針方式

關(guān)于Rust編譯時報link.exe?not?found錯誤問題