#Writing u8 To File

15 messages · Page 1 of 1 (latest)

quaint summit
#

Apologies for the simple question...

My goal is to write a program that accepts a directory as input, iterates over two files at a time, and whenever a byte matches between the two it writes that byte to the same position in a new file and otherwise it writes "\x00".

Simple example: A directory has files A == b41 aa ab and B == b41 fa fb, then the program would create a file with the content b41 00 00

I am using Vecs and zip to accomplish this like so:

  1 use std::io::{Result,Seek};
  2 use std::io::prelude::*; // Required for file.read_to_end
  3 use std::fs::{read_dir,File};
  4 
  5 fn main() -> Result<()> {
  6   let mut file = File::create("./result.bin")?;
  7   let paths = read_dir("./test").unwrap(); // Make the dir a cli arg. Use ./test dir for now
  8 
  9   for path in paths {
 10     let mut new_buffer = Vec::new();
 11     let mut new_file = File::open(path.unwrap().path())?;
 12     new_file.read_to_end(&mut new_buffer)?;
 13 
 14     let mut old_buffer = Vec::new();
 15     let mut old_file = File::open("./output.bin")?; // Example file containing `41 fa fb`
 16     old_file.read_to_end(&mut old_buffer)?;
 17 
 18     // Use zip to iterate over both buffers
 19     old_buffer.iter().zip(&new_buffer).filter(|&(old, new)| {
 20       if old == new {
 21         file.write(new).unwrap();
 22       } else {
 23         file.write(b"\x00").unwrap();
 24       }
 25       return true;
 26     });
 27     file.rewind()?;
 28   }
 29   Ok(())
 30 }

When I try to cargo build, I get the error:

error[E0308]: mismatched types
  --> src/main.rs:21:20
   |
21 |         file.write(new).unwrap();
   |                    ^^^ expected slice `[u8]`, found `u8`
   |
   = note: expected reference `&[u8]`
              found reference `&u8`

I've tried several different things to get this to work, but I had that using new.to_vec() would have worked. Can I get a nudge in the correction to write the byte of interest to a file?

heady zealot
#

All you need to do is &[new]. However, this doesn't do anything. You should be using a for loop or for_each, otherwise the iterator never runs.

#

actually &[*new]

quaint summit
#

Sorry for the dumb question, but isn't that what the iter call is doing? If I replace new with "b'\x01'", the output I get in the test file is expected

#

so I can accurately compare files and create a file that highlights where the bytes are the same. I just can't get it to work with bytes from the file.

#

Also, thank you for that answer. I will try that. Sorry, I know that has to be a very beginner question

heady zealot
#

b'\x01' also won't work, it needs to be b"\x01"

quaint summit
#

yes, I did use b"\x01". Sorry, I didn't copy and paste that. Just typed it

heady zealot
#

Iterators are lazy. Most methods (including filter) on iterators only adapt it into another iterator. For example, map just combines it with a function, which runs each time you call next.

quaint summit
#

ah. I had to add a count() call to the end of the filter call.

#

yes, that makes sense

#

I forgot I removed the final call.

#

thanks so much for your help.

#

that seems to have cleared up what I was missing

heady zealot
#

Also, you should use write_all instead of write, and you should wrap the output file in BufWriter so that you aren't writing every byte to the file individually.