欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Rust 配置文件內(nèi)容及使用全面講解

 更新時(shí)間:2023年10月20日 08:51:23   作者:garfileo  
這篇文章主要為大家介紹了Rust 配置文件內(nèi)容及使用全面講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

問題

在之前的程序中,文本分割符皆以硬編碼的方式出現(xiàn),導(dǎo)致程序靈活性較差。rzeo 項(xiàng)目解析的文本,我傾向?yàn)橄吕拘问剑?/p>

以下 Rust 程序
@ hello world #
fn main() {
    println!("Hello world!");
}
@
可在終端打印「Hello world!」。

但是對于其他 rzeo 的用戶而言,未必喜歡使用 @ 和 # 之類的符號(hào)。為了最大程度兼容所有人的偏好,rzeo 使用的文本分割符需以配置文件的方式進(jìn)行定義,在其運(yùn)行時(shí)方知文本分割符的具體形式。

rzeo 的配置文件采用 YAML 語言撰寫,例如:

border: '\n[ \t]*@[ \t\n]*'
code_snippet_neck: '[ \t]*#[ \t]*\n'

假設(shè) rzeo 配置文件為 rzeo.conf,編寫一個(gè)程序從該文件獲取分割符。

讀取文件

首先,考慮如何使用 Rust 標(biāo)準(zhǔn)庫提供的文件讀寫功能,讀取配置文件 rzeo.conf,并輸出其內(nèi)容,以熟悉文件讀寫功能的基本用法。

以下代碼可讀取 rzeo.conf 文件并逐行打印其內(nèi)容:

use std::fs::File;
use std::io::{BufRead, BufReader};
fn main() -> Result<(), std::io::Error> {
    let f = File::open("rzeo.conf")?;
    let reader = BufReader::new(f);
    for line in reader.lines() {
        println!("{}", line?);
    }
    return Ok(());
}

BufRead 是特性。BufReader 是實(shí)現(xiàn)了 BufRead 特性的結(jié)構(gòu)體類型,用于將硬盤中的文件內(nèi)容讀入到內(nèi)存緩沖區(qū)以降低硬盤讀取次數(shù)。需要注意的是,File 的 open 方法和 BufReader 的 lines 方法皆返回 Result<T, std::io::Error> 類型,T 為 String 類型——Rust 的又一種字符串類型,相當(dāng)于 Vec<char> 類型。在此不對 String 給予講解,可在使用中逐漸熟悉其用法。

以下代碼可將 rzeo.conf 文件中的內(nèi)容寫入另一個(gè)文件:

use std::fs::File;
use std::io::{BufRead, BufReader, Write};
fn main() -> Result<(), std::io::Error> {
    let f = File::open("rzeo.conf")?;
    let mut g = File::create("foo.txt")?;
    let reader = BufReader::new(f);
    for line in reader.lines() {
        let content = line?;
        g.write_all(content.as_bytes())?;
        g.write_all("\n".as_bytes())?;
    }
    return Ok(());
}

注意,File 的 write_all 方法,其參數(shù)類型為 &[u8],即字節(jié)數(shù)組切片,故而需要使用 &str 或 String 類型的 as_bytes 將字符串轉(zhuǎn)化為字節(jié)數(shù)組切片。write_all 的返回值是 Result<()> 類型,需使用 unwrap 解包或使用 ? 進(jìn)行錯(cuò)誤傳播。

路徑

為了保持不同操作系統(tǒng)中文件路徑的兼容性,Rust 標(biāo)準(zhǔn)庫提供了一種特殊的字符串類型 std::path::Path 以及一些用于處理文件路徑的方法。為了程序的可移植性,建議使用 std::path::Path 代替普通的字符串作為文件路徑。

以下代碼演示了 std::path::Path 的基本用法:

use std::path::Path;
use std::fs::File;
use std::io::{BufRead, BufReader};
fn main() -> Result<(), std::io::Error> {
    let path = Path::new("/tmp/rzeo.conf");
    println!("{:?}", path);
    let f = File::open(path)?;
    let reader = BufReader::new(f);
    for line in reader.lines() {
        println!("{}", line?);
    }
    return Ok(());
}

引入 serde 庫

讀取 rzeo.conf 文件并不困難,困難的是對其內(nèi)容的解析。當(dāng)前的 rzeo.conf 文件中的內(nèi)容,僅僅用到了 YAML 最為基礎(chǔ)的語法——鍵值對,即便如此,要對其予以解析,免不了要寫許多代碼。Rust 第三方庫 serde 能夠?qū)崿F(xiàn) Rust 語言的值與特定格式的數(shù)據(jù)文件的交換,即值的序列化(Serialize)和反序列化(Deserialize)。

serde 只是一個(gè)框架,對于特定格式的數(shù)據(jù)文件,需要引入 serde 的相應(yīng)實(shí)現(xiàn)。下面使用 cargo 構(gòu)建一個(gè)項(xiàng)目,引入 serde 和 serde_yaml 庫,實(shí)現(xiàn) Rust 結(jié)構(gòu)體的序列化。

首先,使用 cargo 建立新項(xiàng)目并進(jìn)入項(xiàng)目目錄:

$ cargo new foo
$ cd foo

然后使用 cargo add 命令添加 serde(同時(shí)開啟 serde 的 derive 特性)和 serde_yaml 庫:

$ cargo add -F derive serde
$ cargo add serde_yaml

上述命令可在項(xiàng)目根目錄下的 Cargo.toml 文件的 [dependencies] 部分添加以下內(nèi)容:

serde = { version = "1.0.171", features = ["derive"] }
serde_yaml = "0.9.22"

隨著 serde 和 serde_yaml 庫的更新,等你看到這份文檔時(shí),也動(dòng)手搭建這個(gè)項(xiàng)目時(shí),庫的版本號(hào)應(yīng)該是與上述內(nèi)容不同。

序列化與反序列化

編輯上一節(jié)構(gòu)建的 foo 項(xiàng)目的 src/main.rs 文件,令其內(nèi)容為

use std::fs::File;
#[derive(serde::Serialize)]
struct Foo<'a> {
    id: u32,
    data: &'a str
}
fn main() -> Result<(), std::io::Error> {
    let foo = Foo { id: 1, data: "Hello world!" };
    let f = File::create("foo.yml")?;
    serde_yaml::to_writer(f, &foo)?;
    return Ok(());
}

執(zhí)行以下命令,編譯并運(yùn)行程序:

$ cargo run

但是上述的 main.rs 中存在錯(cuò)誤,導(dǎo)致 Rust 編譯器報(bào)錯(cuò)。錯(cuò)誤的原因是 File::create 和 sert_yaml::to_writer 返回的 Result<T, E> 類型不一致,導(dǎo)致無法給出 main 函數(shù)的返回值類型的正確定義。對于上述代碼快速而臟的修復(fù)是

serde_yaml::to_writer(f, &foo).unwrap();

即放棄 serde_yaml::to_write 的錯(cuò)誤進(jìn)行傳播。

上述程序通過編譯,運(yùn)行結(jié)果是在當(dāng)前目錄創(chuàng)建 foo.yml 文件,其內(nèi)容為

id: 1
data: Hello world!

以下代碼實(shí)現(xiàn)了 YAML 文件 foo.yml 的反序列化:

use std::fs::File;
#[derive(Debug, serde::Deserialize)]
struct Foo {
    id: u32,
    data: String
}
fn main() -> Result<(), std::io::Error> {
    let f = File::open("foo.yml")?;
    let foo: Foo = serde_yaml::from_reader(f).unwrap();
    println!("{:?}", foo);
    return Ok(());
}

foo.yml 中的內(nèi)容被轉(zhuǎn)換為 Rust 結(jié)構(gòu)體類型 Foo 的實(shí)例 foo。需要注意的是,上述 Foo 的 data 域,其類型不再是 &str,而是 String,原因 serde_yaml::from_reader 方法并不占有數(shù)據(jù),導(dǎo)致存儲(chǔ)反序列化結(jié)果的結(jié)構(gòu)體實(shí)例中的引用無效。

分割符

現(xiàn)在,定義一個(gè)結(jié)構(gòu)體類型 Separator,用于存儲(chǔ)從 rzeo.conf 中獲取的分割符:

#[derive(Debug, serde::Deserialize)]
struct Separator {
    border: String,
    code_snippet_neck: String
}

使用以下代碼便可解析 rzeo.conf 相應(yīng)的信息并將解析結(jié)果作為 Separator 類型的值:

fn main() -> Result<(), std::io::Error>  {
    let f = std::fs::File::open("rzeo.conf")?;
    let foo: Separator = serde_yaml::from_reader(f).unwrap();
    println!("{:?}", foo);
    return Ok(()); 
}

至此,本章開頭提出的問題便得以解決。

C 版本

有一些采用 C 語言編寫的庫也能夠?qū)崿F(xiàn)對 YAML 文件的解析,例如能夠支持 C 語言結(jié)構(gòu)體的 YAML 序列化和反序列化的庫 libcyaml,在 Ubuntu 系統(tǒng)可使用以下命令安裝該庫:

$ sudo apt install libyaml-dev libcyaml-dev

以下是反序列化 rzeo.conf 文件的 C 程序:

#include <stdlib.h>
#include <stdio.h>
#include <cyaml/cyaml.h>
typedef struct {
        char *border;
        char *code_snippet_neck;
} Foo;
/* 構(gòu)造結(jié)構(gòu)體類型 Foo 與 rzeo.conf 之間的聯(lián)系 */
static const cyaml_schema_field_t top_mapping[] = {
        CYAML_FIELD_STRING_PTR(
                "border", CYAML_FLAG_POINTER, Foo, border, 0, CYAML_UNLIMITED),
        CYAML_FIELD_STRING_PTR(
                "code_snippet_neck", CYAML_FLAG_POINTER, Foo,
                code_snippet_neck, 0, CYAML_UNLIMITED),
        CYAML_FIELD_END
};
static const cyaml_schema_value_t top = {
        CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, Foo, top_mapping)
};
/* 解析器設(shè)置 */
static const cyaml_config_t config = {
        .log_fn = cyaml_log,
        .mem_fn = cyaml_mem,
        .log_level = CYAML_LOG_WARNING
};
/* 反序列化 */
int main(void) {
        Foo *foo;
        cyaml_err_t err = cyaml_load_file("rzeo.conf", &config, &top,
                                          (cyaml_data_t **)&foo, NULL);
        if (err != CYAML_OK) {
                fprintf(stderr, "ERROR: %s\n", cyaml_strerror(err));
        return EXIT_FAILURE;
        }
        printf("border: %s\n", foo->border);
        printf("code_snippet_neck: %s\n", foo->code_snippet_neck);
        cyaml_free(&config, &top, foo, 0);
        return 0;
}

使用以下命令編譯上述程序:

$ gcc -o foo foo.c $(pkg-config --cflags --libs libcyaml)

運(yùn)行程序:

$ ./foo
border: \n[ \t]*@[ \t\n]*
code_snippet_neck: [ \t]*#[ \t]*\n

小結(jié)

Rust 第三方庫對 YAML 序列化和反序列化的支持優(yōu)于 C 的第三方庫。必須要承認(rèn),C 語言在文本處理方面,若想變得更為優(yōu)雅,最好的辦法是先基于它實(shí)現(xiàn)一門小巧的動(dòng)態(tài)語言(例如 Lua 語言),由后者負(fù)責(zé)處理文本。

以上就是Rust 配置文件內(nèi)容及使用全面講解的詳細(xì)內(nèi)容,更多關(guān)于Rust 配置文件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Rust使用lettre實(shí)現(xiàn)郵件發(fā)送功能

    Rust使用lettre實(shí)現(xiàn)郵件發(fā)送功能

    這篇文章主要為大家詳細(xì)介紹了Rust如何使用lettre實(shí)現(xiàn)郵件發(fā)送功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • Rust中的Struct使用示例詳解

    Rust中的Struct使用示例詳解

    這篇文章主要介紹了Rust中的Struct使用示例,代碼分為結(jié)構(gòu)體和實(shí)例化與訪問,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • 深入了解Rust中泛型的使用

    深入了解Rust中泛型的使用

    所有的編程語言都致力于將重復(fù)的任務(wù)簡單化,并為此提供各種各樣的工具。在?Rust?中,泛型(generics)就是這樣一種工具,本文就來聊聊Rust中泛型的使用,需要的可以參考一下
    2022-11-11
  • 使用vscode配置Rust運(yùn)行環(huán)境全過程

    使用vscode配置Rust運(yùn)行環(huán)境全過程

    VS Code對Rust有著較完備的支持,這篇文章主要給大家介紹了關(guān)于使用vscode配置Rust運(yùn)行環(huán)境的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • rust閉包的使用

    rust閉包的使用

    閉包在Rust中是非常強(qiáng)大的功能,允許你編寫更靈活和表達(dá)性的代碼,本文主要介紹了rust閉包的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Rust可迭代類型迭代器正確創(chuàng)建自定義可迭代類型的方法

    Rust可迭代類型迭代器正確創(chuàng)建自定義可迭代類型的方法

    在 Rust 中, 如果一個(gè)類型實(shí)現(xiàn)了 Iterator, 那么它會(huì)被同時(shí)實(shí)現(xiàn) IntoIterator, 具體邏輯是返回自身, 因?yàn)樽陨砭褪堑?這篇文章主要介紹了Rust可迭代類型迭代器正確創(chuàng)建自定義可迭代類型的方法,需要的朋友可以參考下
    2023-12-12
  • Rust調(diào)用C程序的實(shí)現(xiàn)步驟

    Rust調(diào)用C程序的實(shí)現(xiàn)步驟

    本文主要介紹了Rust調(diào)用C程序的實(shí)現(xiàn)步驟,包括創(chuàng)建C函數(shù)、編譯C代碼、鏈接Rust和C代碼等步驟,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Rust?所有權(quán)機(jī)制原理深入剖析

    Rust?所有權(quán)機(jī)制原理深入剖析

    這篇文章主要為大家介紹了Rust?所有權(quán)機(jī)制原理深入剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Rust?duckdb和polars讀csv文件比較情況

    Rust?duckdb和polars讀csv文件比較情況

    duckdb在數(shù)據(jù)分析上,有非常多不錯(cuò)的特質(zhì),1、快;2、客戶體驗(yàn)好,特別是可以同時(shí)批量讀csv在一個(gè)目錄下的csv等文件,今天來比較下Rust?duckdb和polars讀csv文件比較的情況,感興趣的朋友一起看看吧
    2024-06-06
  • 利用rust實(shí)現(xiàn)一個(gè)命令行工具

    利用rust實(shí)現(xiàn)一個(gè)命令行工具

    這篇文章主要為大家詳細(xì)介紹了如何使用?Rust?和?clap?4.4.0?創(chuàng)建一個(gè)命令行工具?my_dev_tool,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考下
    2023-12-12

最新評論