English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
This chapter introduces the I of the Rust language/O operation.
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 the command-line mechanism.
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 an unparameterized function, and environment parameters need to be retrieved by the developer through the std::env module, which is a very simple process:
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, it doesn't matter, we can simply traverse it:
fn main() { let args = std::env::args(); for arg in args { println!("{}", arg); } }
Running results:
D:\rust\greeting\target\debug\greeting.exe
General parameters are usually used to be traversed, aren't they?
Now we open the long-unused launch.json, find "args": [], where you can set runtime parameters. We set it to "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 actually used it, and as a language tutorial, we will not describe how to run Rust programs using the command line. But if you are a well-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 the program's reception of 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, the program cannot be debugged. However, obtaining information from the command line is still very important for a command line program.
In Rust, the std::io module provides related functions for standard input (which can be considered as command line input):
use std::io::stdin; fn main() { let mut str_buf = String::new(); stdin().read_line(&mut str_buf) .expect("Failed to read line."); println!("Your input line is {}", str_buf); }
It is a very cumbersome thing to make the VSCode environment support command line input, involving cross-platform issues and undeployable issues, so we directly run the program in the VSCode terminal. Run in the command line:
D:\rust\greeting> cd ./target/debug D:\rust\greeting\target\debug> ./greeting.exe w3codebox Your input line is w3codebox
std::io::Stdio contains the read_line method, which can read a line of string into the buffer and return a Result enumeration class, used to pass errors that occur during reading, so expect or unwrap functions are often used to handle errors.
Note: The Rust standard library does not yet provide a method to directly read numbers or formatted data from the command line. We can read a line of string and use string recognition functions to process the data.
We create a file named text.txt under the D:\ directory of the computer, with the following content:
This is a text file.
This is a program that reads the content of a text file into a string:
use std::fs; fn main() { let text = fs::read_to_string("D:\\text.txt").unwrap(); println!("{}", text); }
Running results:
This is a text file.
Reading an entire file that can be contained in memory is extremely simple in Rust, and the read_to_string method in the std::fs module can easily complete the reading of text files.
But if the file to be read is a binary file, we can use the std::fs::read function to read u8 type collection:}
use std::fs; fn main() { let content = fs::read("D:\\text.txt").unwrap(); println!("{:?}", content); }
Running results:
[84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 120, 116, 32, 102, 105, 108, 101, 46]
The above two methods are for reading all at once, which is very suitable for the development of web applications. However, for some low-level programs, the traditional streaming read method is still irreplaceable, because in more cases, the size of the file may be far larger than the memory capacity.
Rust file stream reading method:
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); }
Running results:
[84, 104, 105, 115, 32] [105, 115, 32, 97, 32]
The File class in the std::fs module is a class that describes files, which can be used to open files. After opening the file, we can use the read method of File to read some bytes from the bottom of the file into the buffer (the buffer is a u8 array), the number of bytes read is equal to the length of the buffer.
Note: VSCode currently does not have the function to automatically add standard library references, so sometimes the error of "function or method does not exist" may be due to the problem of standard library references. We can view the annotation document of the standard library (the mouse is placed on it) to manually add the standard library.
The open method of std::fs::File is to open the file in "read-only" mode, and there is no corresponding close method, because the Rust compiler can automatically close the file when it is no longer in use.
File writing is divided into write all at once and streaming write. Streaming write requires opening the file, and there are two ways to open it: "create" (create) and "append" (append).
Write all at once:
use std::fs; fn main() { fs::write("D:\\text.txt", "FROM RUST PROGRAM") .unwrap(); }
This is as simple and convenient as reading all at once. After executing the program, the content of the D:\text.txt file will be rewritten to FROM RUST PROGRAM. So, use write all at once with caution! It will directly delete the file content (regardless of how large the file is). If the file does not exist, it will be created.
If you want to write file content in a streaming manner, you can use the create method of 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(); }
This program is equivalent to the previous program.
NoteThe opened file must be stored in a mutable variable to use the File's methods!
There is no append static method in the File class, but we can use OpenOptions to implement opening a file with a specific method:
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(()) }
After running, the content of the D:\text.txt file will become:
FROM RUST PROGRAM APPEND WORD
OpenOptions is a flexible method to open a file, which can set open permissions, including read and write permissions except for append permissions. If we want to open a file with read and write permissions, we can write it like this:
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(()) }
After running, the content of the D:\text.txt file will become:
COVERRUST PROGRAM APPEND WORD