在Rust中逐行读取大文件

在Rust中逐行读取大文件,rust,Rust,我的Rust程序打算逐行读取一个非常大(高达几GB)的简单文本文件。问题是,此文件太大,无法立即读取,也无法将所有行传输到Vec 在Rust中处理此问题的惯用方法是什么?您想使用,尤其是函数: 您想使用,特别是功能: 请注意,新行被视为LF或CR后跟LF。如果文件大小大于可用大小,则这不一定是最有效的方法memory@Awalias我更新了我的答案以便更清楚。如果你不明白一些具体的东西,请告诉我什么。开始学习Rust,这是非常有用的信息。注意,新行被认为是LF或CR后跟LF。如果文件大小大于可用

我的Rust程序打算逐行读取一个非常大(高达几GB)的简单文本文件。问题是,此文件太大,无法立即读取,也无法将所有行传输到
Vec

在Rust中处理此问题的惯用方法是什么?

您想使用,尤其是函数:

您想使用,特别是功能:


请注意,新行被视为LF或CR后跟LF。如果文件大小大于可用大小,则这不一定是最有效的方法memory@Awalias我更新了我的答案以便更清楚。如果你不明白一些具体的东西,请告诉我什么。开始学习Rust,这是非常有用的信息。注意,新行被认为是LF或CR后跟LF。如果文件大小大于可用大小,这不一定是最有效的方法memory@Awalias我更新了我的答案以便更清楚。如果你不明白一些具体的东西,请告诉我什么。开始学习生锈,这是非常有帮助的informative@Kroltan-没有那么多;根据谷歌在“rust中高效读取文件行”上的搜索,该页面现在是排名第一的条目。(:@HuwWalters这不是在发帖的时候!当前的读者将被引导到这些副本中的任何一个。而且我敢说,这样的帖子仍然符合“示例”的条件,所以评论仍然是最新的(:这是我的观点;这是一个有用的页面!(尽管讽刺可能有点平淡)我不同意这个问题已经得到了回答,当然不是通过现在的链接。OP特别要求为非常大的文件提供一种方法,其中文件太大,无法一次读取或逐行读取,必须存在一种更有效的方法,这使得此方法有效question@Kroltan-不太多;这一页现在是最热门的r根据谷歌在“rust中高效读取文件中的行”上的搜索,anking条目(-:@HuwWalters这不是发布时的内容!当前的读者将被定向到这些重复的内容中的任何一个。我敢说,这样的文章仍然符合“示例”的条件,因此评论仍然是最新的(-:这是我的观点;这是一个有用的页面!(讽刺的是可能有点平淡)我不同意这个问题已经得到了回答,当然不是通过现在的链接。OP特别要求对非常大的文件提供一种方法,其中文件太大,无法一次读取或逐行读取,必须存在一种更有效的方法,这使得这是一个有效的问题
use std::fs::File;
use std::io::{self, prelude::*, BufReader};

fn main() -> io::Result<()> {
    let file = File::open("foo.txt")?;
    let reader = BufReader::new(file);

    for line in reader.lines() {
        println!("{}", line?);
    }

    Ok(())
}
fn main() -> std::io::Result<()> {
    let mut reader = my_reader::BufReader::open("Cargo.toml")?;
    let mut buffer = String::new();

    while let Some(line) = reader.read_line(&mut buffer) {
        println!("{}", line?.trim());
    }

    Ok(())
}

mod my_reader {
    use std::{
        fs::File,
        io::{self, prelude::*},
    };

    pub struct BufReader {
        reader: io::BufReader<File>,
    }

    impl BufReader {
        pub fn open(path: impl AsRef<std::path::Path>) -> io::Result<Self> {
            let file = File::open(path)?;
            let reader = io::BufReader::new(file);

            Ok(Self { reader })
        }

        pub fn read_line<'buf>(
            &mut self,
            buffer: &'buf mut String,
        ) -> Option<io::Result<&'buf mut String>> {
            buffer.clear();

            self.reader
                .read_line(buffer)
                .map(|u| if u == 0 { None } else { Some(buffer) })
                .transpose()
        }
    }
}
fn main() -> std::io::Result<()> {
    for line in my_reader::BufReader::open("Cargo.toml")? {
        println!("{}", line?.trim());
    }

    Ok(())
}

mod my_reader {
    use std::{
        fs::File,
        io::{self, prelude::*},
        rc::Rc,
    };

    pub struct BufReader {
        reader: io::BufReader<File>,
        buf: Rc<String>,
    }
    
    fn new_buf() -> Rc<String> {
        Rc::new(String::with_capacity(1024)) // Tweakable capacity
    }

    impl BufReader {
        pub fn open(path: impl AsRef<std::path::Path>) -> io::Result<Self> {
            let file = File::open(path)?;
            let reader = io::BufReader::new(file);
            let buf = new_buf();

            Ok(Self { reader, buf })
        }
    }

    impl Iterator for BufReader {
        type Item = io::Result<Rc<String>>;

        fn next(&mut self) -> Option<Self::Item> {
            let buf = match Rc::get_mut(&mut self.buf) {
                Some(buf) => {
                    buf.clear();
                    buf
                }
                None => {
                    self.buf = new_buf();
                    Rc::make_mut(&mut self.buf)
                }
            };

            self.reader
                .read_line(buf)
                .map(|u| if u == 0 { None } else { Some(Rc::clone(&self.buf)) })
                .transpose()
        }
    }
}