English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
This chapter introduces I/O operations in the Rust language.
Command line programs are the most basic form of computer programs, and almost all operating systems support command line programs and base the execution of visual programs on command line mechanisms.
Command line programs must be able to receive parameters from the command line environment, which are often separated by space characters after a command line command.
In many languages (such as Java and C/C++), environment parameters are passed to the program as parameters of the main function (often a string array), but in Rust, the main function is a parameterless function, and environment parameters need to be retrieved by the developer through the std::env module, which is very simple:
fn main() { let args = std::env::args(); println!("{:?}", args); }
Now run the program directly:
Args { inner: ["D:\\rust\\greeting\\target\\debug\\greeting.exe"] }
Perhaps the result you get is much longer than this, which is normal. This result contains an inner array in the Args structure, which only contains a unique string, representing the location of the currently running program.
But this data structure is hard to understand, no problem, we can simply traverse it:
fn main() { let args = std::env::args(); for arg in args { println!("{}", arg); } }
Risultato dell'esecuzione:
D:\rust\greeting\target\debug\greeting.exe
General parameters are used to be traversed, aren't they?
Now let's open the long-lost launch.json, find "args": [], where you can set runtime parameters. We write it as "args": ["first", "second"], then save and run the program again. The running result is:
D:\rust\greeting\target\debug\greeting.exe first second
As a true command line program, we have never really used it, and as a language tutorial, we will not describe how to run Rust programs from the command line. But if you are a trained developer, you should be able to find the location of the executable file, and you can try to enter the directory and use command line commands to test if the program receives command line environment parameters.
Early chapters have detailed how to use command line output, which is due to the need for language learning, without output, it is impossible to debug programs. But obtaining information from the command line is still very important for a command line program.
In Rust, the std::io module provides functions related to standard input (which can be considered command line input):
use std::io::stdin; fn main() { let mut str_buf = String::new() stdin().read_line(&mut str_buf) .expect("Impossibile leggere la riga."); stampa!("La tua riga di input è {}", str_buf); }
Far supportare l'input da riga di comando all'ambiente VSCode è un processo molto complicato, che coinvolge problemi di piattaforma e problemi di debuggabilità, quindi eseguiamo direttamente il programma nel terminale di VSCode. Esegui nel terminale:
D:\rust\greeting> cd ./target/debug D:\rust\greeting\target\debug> ./greeting.exe w3codebox La tua riga di input è w3codebox
Il pacchetto std::io::Stdio contiene il metodo read_line per leggere una riga di stringa in un buffer, il valore di ritorno è un tipo di enum Result, utilizzato per trasmettere gli errori che si verificano durante la lettura, quindi si utilizzano spesso le funzioni expect o unwrap per gestire gli errori.
注意:La libreria standard di Rust non fornisce un metodo diretto per leggere numeri o dati formattati dalla riga di comando, possiamo leggere una riga di stringa e utilizzare funzioni di riconoscimento di stringhe per elaborare i dati.
Creiamo un file text.txt nella directory D:\ del computer, con il seguente contenuto:
Questo è un file di testo.
Questo è un programma che legge il contenuto di un file di testo in una stringa:
use std::fs; fn main() { let text = fs::read_to_string("D:\\text.txt").unwrap(); stampa!("{}", text); }
Risultato dell'esecuzione:
Questo è un file di testo.
Leggere un intero file che può essere contenuto in memoria in Rust è estremamente semplice, il metodo read_to_string del modulo std::fs può leggere file di testo senza problemi.
Ma se dobbiamo leggere un file binario, possiamo utilizzare la funzione std::fs::read per leggere un insieme di tipi u8:
use std::fs; fn main() { let content = fs::read("D:\\text.txt").unwrap(); stampa!("{:?}", content); }
Risultato dell'esecuzione:
[84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 120, 116, 32, 102, 105, 108, 101, 46]
Questi due modi di lettura sono letture in una volta, molto adatti per lo sviluppo di applicazioni web. Ma per alcuni programmi di basso livello, il modo tradizionale di lettura sequenziale non può essere sostituito, perché in molti casi la dimensione del file può essere molto più grande della capacità della memoria.
Modo di lettura del file stream in Rust:
use std::io::prelude::*; use std::fs; fn main() { let mut buffer = [0u8; 5]; let mut file = fs::File::open("D:\\text.txt").unwrap(); file.read(&mut buffer).unwrap(); println!("{:?}", buffer); file.read(&mut buffer).unwrap(); println!("{:?}", buffer); }
Risultato dell'esecuzione:
[84, 104, 105, 115, 32] [105, 115, 32, 97, 32]
La classe File del modulo std::fs descrive il file, può essere utilizzata per aprire un file, dopo aver aperto il file, possiamo utilizzare il metodo read di File per leggere alcuni byte inferiori del file in un buffer (un array di u8), il numero di byte letti è uguale alla lunghezza del buffer.
Attenzione: VSCode non ha ancora la funzione di aggiunta automatica delle referenze delle librerie standard, quindi a volte gli errori come "funzione o metodo non trovato" possono essere problemi di referenze delle librerie standard. Possiamo consultare la documentazione dei commenti delle librerie standard (passando il mouse sopra) per aggiungere manualmente le librerie standard.
Il metodo open di std::fs::File apre il file in modalità "sola lettura" e non ha un metodo di chiusura associato, perché il compilatore Rust può chiudere automaticamente il file quando non più utilizzato.
La scrittura del file si suddivide in scrittura in una volta e scrittura sequenziale. La scrittura sequenziale richiede l'apertura del file, che può essere "nuovo" (create) o "aggiungere" (append).
Scrittura in una volta:
use std::fs; fn main() { fs::write("D:\\text.txt", "FROM RUST PROGRAM") .unwrap(); }
È semplice ed intuitivo come leggere tutto in una volta. Dopo l'esecuzione del programma, il contenuto del file D:\text.txt sarà sovrascritto con FROM RUST PROGRAM. Quindi, usa con cautela la scrittura in una volta! Poiché cancellerà direttamente il contenuto del file (indipendentemente dalla sua dimensione). Se il file non esiste, verrà creato.
Se si desidera scrivere il contenuto del file in modo sequenziale, è possibile utilizzare il metodo create di std::fs::File:
use std::io::prelude::*; use std::fs::File; fn main() { let mut file = File::create("D:\\text.txt").unwrap(); file.write(b"FROM RUST PROGRAM").unwrap(); }
这段程序与上一个程序等价。
注意:打开的文件一定存放在可变的变量中才能使用 File 的方法!
File 类中不存在 append 静态方法,但是我们可以使用 OpenOptions 来实现用特定方法打开文件:
use std::io::prelude::*; use std::fs::OpenOptions; fn main() -> std::io::Result<()> { let mut file = OpenOptions::new() .append(true).open("D:\\text.txt")?; file.write(b" APPEND WORD")?; Ok(()) }
运行之后,D:\text.txt 文件内容将变成:
FROM RUST PROGRAM APPEND WORD
OpenOptions 是一个灵活的打开文件的方法,它可以设置打开权限,除append 权限以外还有 read 权限和 write 权限,如果我们想以读写权限打开一个文件可以这样写:
use std::io::prelude::*; use std::fs::OpenOptions; fn main() -> std::io::Result<()> { let mut file = OpenOptions::new() .read(true).write(true).open("D:\\text.txt")?; file.write(b"COVER")?; Ok(()) }
运行之后,D:\text.txt 文件内容将变成:
COVERRUST PROGRAM APPEND WORD