Fix some issues, reorgenize

This commit is contained in:
2023-07-29 16:25:44 +02:00
parent eda7d043f9
commit 0e06422b35
10 changed files with 405 additions and 230 deletions
-37
View File
@@ -1,37 +0,0 @@
name: csv-compare
version: "1.0"
author: Mathias Rothenhaeusler <safemind@posteo.net>
about: Compares two csv files.
args:
- source:
short: s
long: source
value_name: FILE1
help: Defines the base csv file
takes_value: true
required: true
- compared:
short: f
long: compare
value_name: FILE2
help: Defines the csv file to compare
takes_value: true
required: true
- delimiter:
short: d
long: delimiter
help: Csv delimiter character
required: false
takes_value: true
- column:
short: c
long: column
help: CSV column to compare
required: true
takes_value: true
- output:
short: o
long: output
help: Filename to write the result set
required: false
takes_value: true
+20
View File
@@ -0,0 +1,20 @@
use clap::Parser;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct MyArgs {
#[arg(name = "source")] // Define the argument without a short or long version
pub source: String,
#[arg(name = "compare")] // Define the argument without a short or long version
pub compare: String,
#[arg(short, long)]
pub column: usize,
#[arg(short, long)]
pub output: Option<String>,
#[arg(short, long, default_value_t = ';'.to_string())]
pub delimiter: String,
}
+120
View File
@@ -0,0 +1,120 @@
use std::io::Write as IoWrite;
use std::{
fs::File,
io::{BufRead, BufReader},
};
use super::args::MyArgs;
#[derive(Debug)]
pub struct Params {
delimiter: String,
source: String,
compared: String,
column: usize,
output: Option<String>,
}
impl Params {
pub fn new_from_matches(matches: MyArgs) -> Self {
Self {
delimiter: matches.delimiter,
source: matches.source,
compared: matches.compare,
column: matches.column,
output: {
let this = matches.output;
this.map(|x| x.to_string())
},
}
}
pub fn delimiter(&self) -> &String {
&self.delimiter
}
pub fn source(&self) -> &String {
&self.source
}
pub fn compared(&self) -> &String {
&self.compared
}
pub fn column(&self) -> usize {
self.column
}
pub fn output_mut(&mut self) -> &Option<String> {
&self.output
}
}
pub struct CsvLine {
pub line: String,
}
impl CsvLine {
pub fn new(line: String) -> Self {
Self { line }
}
}
pub fn print_lines(vector: Vec<CsvLine>) {
for line in vector.iter() {
println!("{}", line.line);
}
}
pub fn write_to_file(filename: String, diff: Vec<CsvLine>) {
let mut file = File::create(filename).unwrap();
for line in diff.iter() {
writeln!(&mut file, "{}", line.line).unwrap();
}
}
pub fn compare(reader: BufReader<File>, reader2: BufReader<File>, params: &Params) -> Vec<CsvLine> {
let vec1: Vec<CsvLine> = reader
.lines()
.map(|line| {
let bla = line.unwrap();
CsvLine::new(bla.to_string())
})
.collect();
let vec2: Vec<CsvLine> = reader2
.lines()
.map(|line| {
let bla = line.unwrap();
CsvLine::new(bla.to_string())
})
.collect();
let mut diff: Vec<CsvLine> = Vec::new();
find_diff(&vec1, &vec2, &mut diff, params);
find_diff(&vec2, &vec1, &mut diff, params);
diff
}
fn find_diff(vec1: &[CsvLine], vec2: &[CsvLine], diff: &mut Vec<CsvLine>, params: &Params) {
for i in vec1.iter() {
let splitter: Vec<&str> = i.line.split(params.delimiter()).collect();
let value = splitter[params.column];
let found = !matches!(
vec2.iter().position(|r| {
let splitter_b: Vec<&str> = r.line.split(params.delimiter()).collect();
let search = splitter_b[params.column()];
search == value
}),
None
);
if !found {
diff.push(CsvLine::new(i.line.parse().unwrap()));
}
}
}
+2
View File
@@ -0,0 +1,2 @@
pub mod compare;
pub mod args;
-79
View File
@@ -1,79 +0,0 @@
pub mod csv_compare {
use std::io::Write as IoWrite;
use std::{
fs::File,
io::{BufRead, BufReader},
};
use clap::ArgMatches;
pub struct Params {
delimiter: String,
source: String,
compared: String,
column: usize,
output: String,
}
impl Params {
pub fn new_from_matches(matches: ArgMatches) -> Self {
Self {
delimiter: matches.value_of("delimiter").unwrap_or(";").to_string(),
source: matches.value_of("source").unwrap().to_string(),
compared: matches.value_of("compared").unwrap().to_string(),
column: matches.value_of("column").unwrap().parse().unwrap(),
output: matches.value_of("output").unwrap().to_string(),
}
}
pub fn delimiter(&self) -> &String {
&self.delimiter
}
pub fn source(&self) -> &String {
&self.source
}
pub fn compared(&self) -> &String {
&self.compared
}
pub fn output(&self) -> &String {
&self.output
}
pub fn column(&self) -> usize {
self.column
}
}
pub struct CsvLine {
pub line: String,
}
impl CsvLine {
pub fn new(line: String) -> Self {
Self { line }
}
}
pub fn load_vector(vector: &mut Vec<CsvLine>, reader: BufReader<File>) {
// Read the file line by line using the lines() iterator from std::io::BufRead.
for (_index, line) in reader.lines().enumerate() {
let line = line.unwrap();
vector.push(CsvLine::new(line.to_string()));
}
}
pub fn print_lines(vector: Vec<CsvLine>) {
for line in vector.iter() {
println!("{}", line.line);
}
}
pub fn write_to_file(params: Params, diff: Vec<CsvLine>) {
let mut file = File::create(params.output).unwrap();
for line in diff.iter() {
writeln!(&mut file, "{}", line.line).unwrap();
}
}
}
+23 -34
View File
@@ -1,47 +1,36 @@
use clap::{load_yaml, App};
use csvcompare::csv_compare::{load_vector, print_lines, write_to_file, CsvLine, Params};
mod csv;
use std::fs::File;
use std::io::BufReader;
fn main() {
let yaml = load_yaml!("cli.yml");
let matches = App::from_yaml(yaml).get_matches();
let params = Params::new_from_matches(matches);
let file = File::open(&params.source()).expect("Can't find source file");
let file2 = File::open(&params.compared()).expect("Cant't find compared file");
use clap::Parser;
use csv::compare;
use crate::csv::compare::{Params, write_to_file, print_lines};
use crate::csv::args::MyArgs;
fn main() {
let args = MyArgs::parse();
let mut params = Params::new_from_matches(args);
let file = File::open(params.source()).expect("Can't find source file");
let file2 = File::open(params.compared()).expect("Cant't find compared file");
let reader = BufReader::new(file);
let reader2 = BufReader::new(file2);
let mut vec1: Vec<CsvLine> = Vec::new();
let mut vec2: Vec<CsvLine> = Vec::new();
let mut diff: Vec<CsvLine> = Vec::new();
let diff = compare::compare(reader, reader2, &params);
load_vector(&mut vec1, reader);
load_vector(&mut vec2, reader2);
let option_string_ref = params.output_mut();
for i in vec1.iter() {
let splitter: Vec<&str> = i.line.split(params.delimiter()).collect();
let value = splitter[params.column()];
let found = !matches!(
vec2.iter().position(|r| {
let splitter_b: Vec<&str> = r.line.split(params.delimiter()).collect();
let search = splitter_b[params.column()];
search == value
}),
None
);
if !found {
diff.push(CsvLine::new(i.line.parse().unwrap()));
}
}
if params.output().is_empty() == false {
write_to_file(params, diff);
// Now, check if the option is Some and dereference it to get the String
if let Some(string_ref) = option_string_ref {
// Clone the underlying String since process_string expects ownership
write_to_file(string_ref.clone(), diff);
// Alternatively, you can pass the ownership directly and consume the String
// process_string(string_ref);
} else {
print_lines(diff);
}