I have an issue with trying to check if a file exists and reading it if it exists.
My code:
use std::{env, fs};
use std::fs::{File, read};
use std::path::Path;
use std::process::exit;
let arg = env::args().next().expect("Please open a file via the command line!");
let path = Path::new(
&arg
);
if !path.exists() {
error!("The specified path does not exist!");
exit(101);
}
let file = read(path).expect("Could not read file!");
let content = String::from_utf8(file).expect("The file does not contain valid characters!");
Run the program like this ./program.exe a_vali_file_path.txt
Expectation: If you run the program with a valid file path as the first argument, the program will check if it exists. If it does, the program reads the file content and just returns.
What actually happened:
The program doesn't even really check for the file (it does not panic, even if the path is not valid) and if it tries to read it prints a bunch of bytes into the console followed by the error
error: Utf8Error { valid_up_to: 2, error_len: Some(1) } }
.
This behavior occurs if the file exists or not.
CodePudding user response:
env::args.next() references the executable, which doesn't contain UTF-8 bytes. If you want to point to the next argument you must use another .next()
call, or better yet use a Vector to store your args.
Example of a vector being used to store args ->
fn main() {
let args: Vec<String> = env::args().collect()
...
}
To solve it your way:
fn main() {
let args = env::args()
args.next() //Points to executable (argv[0])
args.next() //Points to file (argv[1])
}
As you can see the second solution is not very elegant, but hey, to each their own.