fs_utils/read.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
//! Functions to read from files.
use std::{
self, fs,
io::{self, Read},
path::Path,
};
/// Reads the first N bytes from a file.
///
/// It is equivalent to `head -c limit` *nix utility.
pub fn head(path: impl AsRef<Path>, limit: usize) -> io::Result<Vec<u8>> {
let file_size = fs::metadata(&path)?.len();
let file_size: usize = if file_size <= std::usize::MAX as u64 {
file_size as usize
} else {
std::usize::MAX
};
let (read_buffer_size, read_limit) = if file_size <= limit {
(file_size, file_size)
} else {
(limit, limit)
};
let mut read_buffer = vec![0; read_buffer_size];
fs::File::open(&path)?.read_exact(&mut read_buffer[..read_limit])?;
Ok(read_buffer)
}
/// Reads the first `N` bytes from a file and return them as a string.
///
/// It assumes that the file is encoded with UTF-8, so any invalid UTF-8 sequences will be
/// replaced with `U+FFFD REPLACEMENT CHARACTER`, which looks like this: �, learn more
/// [here](https://doc.rust-lang.org/std/string/struct.string.html#method.from_utf8_lossy)).
///
/// It is equivalent to `head -c limit` *nix utility.
pub fn head_to_string(path: impl AsRef<Path>, limit: usize) -> io::Result<String> {
Ok(String::from_utf8_lossy(&head(path, limit)?).into_owned())
}
/// Reads the first `N` bytes from a file and return them as a string. If the file size is greater
/// than `N` bytes, the truncation message will be put at the end of the String.
///
/// It assumes that the file is encoded with UTF-8, so any invalid UTF-8 sequences will be
/// replaced with `U+FFFD REPLACEMENT CHARACTER`, which looks like this: �, learn more
/// [here](https://doc.rust-lang.org/std/string/struct.string.html#method.from_utf8_lossy)).
pub fn head_to_string_with_message(
path: impl AsRef<Path>,
limit: usize,
truncation_message: &str,
) -> io::Result<String> {
let mut read_buffer = head(path, limit + 1)?;
if read_buffer.len() > limit {
read_buffer[(limit - truncation_message.len())..limit]
.copy_from_slice(truncation_message.as_bytes());
}
read_buffer.truncate(limit);
Ok(String::from_utf8_lossy(&read_buffer).into_owned())
}