use std::fs::File;
use std::io::{self, Read};
use std::str::from_utf8;
fn read_file_character_by_character(path: &str) -> io::Result<()> {
// Open the file in read-only mode.
let mut file = File::open(path)?;
let mut buffer = [0; 4]; // UTF-8 character max byte length
let mut temp_buffer = vec![];
while let Ok(bytes_read) = file.read(&mut buffer[..1]) { // Read byte by byte
if bytes_read == 0 { // End of file
break;
}
temp_buffer.push(buffer[0]);
if let Ok(s) = from_utf8(&temp_buffer) {
if s.chars().count() == 1 { // Complete character read
print!("{}", s);
temp_buffer.clear(); // Clear temp buffer for next character
}
}
}
Ok(())
}
fn main() {
let path = "path/to/your/file.txt";
if let Err(e) = read_file_character_by_character(path) {
eprintln!("Error reading file: {}", e);
}
} let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;You're going to have to buffer at least a little, to figure out where the USV / grapheme boundary is, depending on our definition of "character". To me, a BufReader is appropriate here; it avoids lots of tiny reads to the kernel, which is probably the right behavior in a real case.
To me, "read character by character" vaguely implies something that's going to yield a stream of characters. (Again, for some definition there.)