Rust File and IO
This chapter introduces the I/O operation of the Rust language.
Receive command line parameters
Command-line programs are the most basic form of computer programs. Almost all operating systems support command-line programs and run visual programs based on command-line mechanisms.
Command-line programs must be able to receive parameters from the command-line environment, which are often separated by spaces after a command-line command.
In many languages (such as Java and CAccord Clipper +), the environment parameters are passed to the program as the parameters of the main function (often an array of strings), but in Rust, the main function is a no-argument function, and the environment parameters need to be passed by the developer. The std::env
module is removed, and the process is very simple:
Example
fn main() {
let args = std::env::args();
println!("{:?}", args);
}
Now run the program directly:
Args { inner: ["D:\\rust\\greeting\\target\\debug\\greeting.exe"] }
Maybe you get a much longer result than this, which is normal, and there is an Args structure in this result. The inner
array, which contains only a unique string, represents the location of the currently running program.
But this data structure is hard to understand, it doesn’t matter, we can simply traverse it:
Example
fn main() {
let args = std::env::args();
for arg in args {
println!("{}", arg);
}
}
Running result:
D:\rust\greeting\target\debug\greeting.exe
General parameters are used to be traversed, aren’t they?
Now we open what we haven’t touched for a long time. launch.json
to find the "args": []
Where you can set the runtime parameters, which we write as "args": ["first", "second"]
then save, run the program again, and run the result:
D:\rust\greeting\target\debug\greeting.exe
first
second
As a real command-line program, we have never really used it, and as a language tutorial, we do not describe how to run Rust programs from the command line here. But if you are a trained developer, you should be able tofind the location of the executable, and you can try to enter the directoryand use command-line commands to test the program to receive command-line environment parameters.
Command line input
The early chapters described in detail how to use command-line output, whichis due to the need for language learning, and it is impossible to debug a program without output. However, getting input 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 thought of as command line input):
Example
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 \\n{}", str_buf);
}
Making the VSCode environment support command line input is a very tedious task, which involves cross-platform problems and non-debug problems, so we run the program directly in the VSCode terminal. Run on the command line:
D:\rust\greeting> cd ./target/debug
D:\rust\greeting\target\debug> ./greeting.exe
RUNOOB
Your input line is
RUNOOB
std::io::Stdio
include read_line
to read method, you can read a line of string to the buffer, the return values are Result enumerated classes, used to pass errors in reading, so commonly used expect
or unwrap
function to handle errors.
Note: currently, the Rust standard library does not provide a way to read numbers or format data directly from the command line, we can read a line ofstrings and use the string recognition function to process the data.
File reading
We create files in the D:directory of the computer text.txt
, the contents are as follows:
This is a text file.
This is a program that reads the contents of a text file into a string:
Example
use std::fs;
fn main() {
let text = fs::read_to_string("D:\\\\text.txt").unwrap();
println!("{}", text);
}
Running result:
This is a text file.
It is extremely simple to read a whole file that can be held in memory in Rust. std::fs
in the module read_to_string
method can easily read the text file.
But if the file to be read is binary, we can use the std::fs::read
function reading u8
type collection:
Example
use std::fs;
fn main() {
let content = fs::read("D:\\\\text.txt").unwrap();
println!("{:?}", content);
}
Running result:
[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 read at one time, which are very suitable for the development of Web applications. However, for some underlying programs, the traditional way of reading by stream is still irreplaceable, because in morecases, the size of the file may far exceed the memory capacity.
File stream reading method in Rust:
Example
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 result:
[84, 104, 105, 115, 32]
[105, 115, 32, 97, 32]
std::fs
in the module File
a class is a class that describes a fileand can be used to open a file, and after opening the file, we can use the File
of read
method reads the following bytes of the file by stream to 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 same error as “function or method does not exist” may be a problem with standard library references. We can view the comments document of the standard library (mouse over it will appear) to manually add the standard library.
std::fs::File
of open
method is to “read-only” open the file,and there is no matching close
method, because the Rust compiler can automatically close a file when it is no longer in use.
File write
File writing is divided into one-time write and streaming write. Streaming writing requires opening the file, which can be opened in two ways: “create” and “append”.
Write once:
Example
use std::fs;
fn main() {
fs::write("D:\\\\text.txt", "FROM RUST PROGRAM")
.unwrap();
}
This is as simple and convenient as one-time reading. After executing the program D:\text.txt
the contents of the file will be rewritten as FROMRUST PROGRAM. Therefore, please use it carefully when writing at one time! Because it deletes the contents of the file directly (no matter how large the file is). If the file does not exist, the file is created.
If you want to write the contents of the file using a stream, you can use the std::fs::File
of create
methods:
Example
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.
Note: open files must be stored in variable variables before they can be used File
the way!
File
does not exist in the class append
static methods, but we can use the OpenOptions
to open the file in a specific way:
Example
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 D:\text.txt
the contents of the file will be:
FROM RUST PROGRAM APPEND WORD
OpenOptions
is a flexible way to open files, it can set open permissions, except append
in addition to the authority, there are read
Permissions and write
permissions, if we want to open a file with read and write permissions, we can write like this:
Example
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 D:\text.txt
the contents of the file will be:
COVERRUST PROGRAM APPEND WORD