学习Rust的第29天: cat in Rust

今天即将是这个系列的最后一次内容,我们正在catRust 中从 GNU 核心实用程序进行重建。cat用于将文件内容打印到STDOUT.听起来很容易构建,所以让我们开始吧。

GitHub 存储库:GitHub - shafinmurani/gnu-core-utils-rust

伪代码

ba 复制代码
function read(path)->result{
  read contents of path
  propogate any errors to the caller
}

args = command_line_arguments
remove the first element of the args vector

if args.length == 0 {
  print error_message
}
else if args.contains("--help") {
  print help_message
} else {
  for path in args {
    result = remove(path);
    error handling
  }
}

设置任务

正如我们往常所做的那样,让我们impl在库箱中创建一个结构体和一个块。

ba 复制代码
pub struct Config<'a> {
  file_names: &'a Vec<String>,
}

impl Config<'_> {
  pub fn new(args: &Vec<String>){
    Config{ file_names: args }
  }

  fn not_enough_arguments(){
    eprintln!("cat: missing operand");
    eprintln!("for help: cat --help");
  }

  fn help(){
    eprintln!("Welcome to cat in Rust, This is a a little copy of the cat utility present in the GNU core utilities. I made this to practice my rust skills. Check out my articles at https://shafinmurani.medium.com");
    eprintln!("To use: cat file_name1 file_name2 file_name3");
  }

  fn read_documents(){}

  pub fn run(&self){
    if self.file_names.len() == 0 {
      Self::not_enough_arguments();
    } else if self.file_names.contain(&String::from("--help")){
      Self::help();
    } else {
      //We call the read_documents function here
    }
  }
}
  • 该代码定义了一个Config带有生命周期参数的结构体'a,其中包含一个file_names对字符串向量的引用的字段。
  • Config结构有一个关联的实现块 ( impl),用于与 相关的方法Config
  • new方法是 的构造函数Config,将对字符串向量的引用args作为输入,并返回一个设置为 的Config实例。file_names``args
  • not_enough_arguments方法向 stderr 打印一条错误消息,指示该cat命令缺少操作数,建议使用cat --help.
  • help方法打印欢迎消息和cat命令的使用说明。
  • read_documents方法当前留空,可能会被实现来读取和打印指定文件的内容。
  • run方法是执行命令的主要函数cat
  • 它首先检查是否没有提供文件名,在这种情况下它调用not_enough_arguments.
  • 然后它检查--help文件名中是否存在该标志,如果存在,则调用该help方法。
  • 否则,假设提供了文件名,并且它将继续读取和打印这些文件的内容,当前将其作为注释保留。

read_documents() 方法

我们将向此函数传递一个文件路径,它将输出文件的内容,为此,我们使用以下内容:

  1. std::fs::File: 打开文件
  2. std::io::Read:将内容读取到字符串变量

让我们导入这些东西并编写read_document()函数并使用它

ba 复制代码
use std::fs::File;
use std::io::Read;

pub struct Config<'a> {
  file_names: &'a Vec<String>,
}

impl Config<'_> {
  pub fn new(args: &Vec<String>){
    Config{ file_names: args }
  }

  fn not_enough_arguments(){
    eprintln!("cat: missing operand");
    eprintln!("for help: cat --help");
  }

  fn help(){
    eprintln!("Welcome to cat in Rust, This is a a little copy of the cat utility present in the GNU core utilities. I made this to practice my rust skills. Check out my articles at https://shafinmurani.medium.com");
    eprintln!("To use: cat file_name1 file_name2 file_name3");
  }

  fn read_documents(file: String) -> std::io::Result<String>{
    let mut file_buffer = File::open(file)?;
    let mut file_content = String::new();

    file_buffer.read_to_string(&mut file_content)?;
    Ok(file_content)
  }

  pub fn run(&self){
    if self.file_names.len() == 0 {
      Self::not_enough_arguments();
    } else if self.file_names.contain(&String::from("--help")){
      Self::help();
    } else {
      for file in self.file_names {
        let result = Self::read_document(file.to_string());
        match result {
          Ok(data) => println!("{}",data),
          Err(e) => eprintln!("Application Error: `{}` {}", file, e),
        };
      }
    }
  }
}

现在这一切都完成了,我们可以处理我们的二进制箱并专注于运行它......

二进制箱

这里的逻辑很简单

  1. 导入Config结构体
  2. 获取命令行参数
  3. 删除第一个参数
  4. 实例化配置
  5. 配置.run()

让我们实践并运行它。

ba 复制代码
use cat::Config;
use std::env;

fn main(){
  let mut args: Vec<String> = env::args().collect();
  args.remove(0);
  
  let config = Config::new(args);
  config.run();
}

运行它

cat我们将使用该工具来阅读我们工具的源代码cat。谈论 Catception 💀

ba 复制代码
# ./cat lib.rs

use std::fs::File;
use std::io::Read;

pub struct Config<'a>{
    file_names: &'a Vec<String>,
}

impl Config<'_>{
    pub fn new(args: &Vec<String>) -> Config{
        Config{ file_names: args }
    }

    fn help(){
        eprintln!("Welcome to cat in Rust, This is a little copy of the cat utility present in the GNU core utilities. I made this to practice my rust skills. Check out my articles at https://shafinmurani.medium.com");
        eprintln!("To use: cat file_name1 file_name2 ... file_nameN");
    }

    fn not_enough_arguments(){
        eprintln!("cat: missing operand");
        eprintln!("for help: cat --help");
    }

    fn read_document(file: String) -> std::io::Result<String>{
        let mut file_buffer = File::open(file)?;
        let mut file_content = String::new();

        file_buffer.read_to_string(&mut file_content)?;
        Ok(file_content)
    }

    pub fn run(&self){
        if self.file_names.len() == 0 {
            Self::not_enough_arguments();
        } else if self.file_names.contains(&String::from("--help")) {
            Self::help();
        } else {
            for file in self.file_names {
               let result = Self::read_document(file.to_string());
                match result {
                    Ok(r) => println!("{}",r),
                    Err(e) => eprintln!("Application Error: `{}` {}",file,e)
                };
            }
        }
    }
}

结论

库文件

  • lib.rs文件定义了 crate 的主要功能cat
  • 它从标准库(std::fs::Filestd::io::Read)导入必要的模块以进行文件处理。
  • 它声明了一个Config带有生命周期参数的结构体'a,其中包含一个file_names对字符串向量的引用的字段。
  • impl与 相关的方法有一个实现块 ( ) Config
  • new方法是 的构造函数Config,将对字符串向量的引用args作为输入,并返回一个设置为 的Config实例。file_names``args
  • help方法打印欢迎消息和cat命令的使用说明。
  • not_enough_arguments方法向 stderr 打印一条错误消息,指示该cat命令缺少操作数,建议使用cat --help.
  • read_document方法读取由名称指定的文件的内容并将其作为 a 返回String,处理潜在的 IO 错误。
  • run方法是执行命令的主要函数cat
  • 它检查是否没有提供文件名,在这种情况下它调用not_enough_arguments.
  • 然后它检查--help文件名中是否存在该标志,如果存在,则调用该help方法。
  • 否则,它会迭代每个文件名,使用 读取其内容read_document,并将其打印到标准输出。

主程序.rs

  • main.rs文件充当可执行文件的入口点。
  • 它从板条箱Config中导入结构catenv从标准库中导入模块。
  • main函数将命令行参数收集到字符串向量中,删除第一个参数(程序名称本身),然后Config使用剩余参数创建一个实例Config::new
  • 最后,它调用实例run上的方法Config来执行cat命令。
相关推荐
蜗牛hb6 分钟前
VMware Workstation虚拟机网络模式
开发语言·学习·php
汤姆和杰瑞在瑞士吃糯米粑粑21 分钟前
【C++学习篇】AVL树
开发语言·c++·学习
Biomamba生信基地28 分钟前
R语言基础| 功效分析
开发语言·python·r语言·医药
手可摘星河30 分钟前
php中 cli和cgi的区别
开发语言·php
小池先生40 分钟前
springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失
java·spring boot·后端
brrdg_sefg1 小时前
Rust 在前端基建中的使用
前端·rust·状态模式
CT随1 小时前
Redis内存碎片详解
java·开发语言
anlog1 小时前
C#在自定义事件里传递数据
开发语言·c#·自定义事件
m0_748230941 小时前
Rust赋能前端: 纯血前端将 Table 导出 Excel
前端·rust·excel
奶香臭豆腐1 小时前
C++ —— 模板类具体化
开发语言·c++·学习