rust 的 File 是有魔法吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bli22ard
V2EX    Rust

rust 的 File 是有魔法吗?

  •  
  •   bli22ard 2024-09-18 14:01:05 +08:00 2750 次点击
    这是一个创建于 440 天前的主题,其中的信息可能已经有所发展或是发生改变。
    use std::error::Error; use std::fs::File; use std::io::{BufRead, BufReader}; fn main() ->Result<(),Box<dyn Error>> { let path=r#"C:\Users\0\Downloads\123.txt"#; let fd=File::open(path)?; let fd_p=&fd; let mut br=BufReader::new(fd_p); let mut line=String::new(); br.read_line(&mut line)?; println!("{}",line); Ok(()) } 

    以上代码,BufReader::new(fd_p); 可以传入 fd_p 也可以传入 fd 都正常工作,感觉读取文件要改变数据才可以读取吧,比如文件指针位置,这个不可变引用 fd_p 读取是怎么做到的

    10 条回复    2024-09-20 12:51:20 +08:00
    Kaleidopink
        1
    Kaleidopink  
       2024-09-18 15:04:25 +08:00
    翻一下文档就能发现实现 Read trait 的是 &File, 而不是 File, 所以即便是不可变引用也可以读取. 内部实现则是用了 unsafe.
    bli22ard
        2
    bli22ard  
    OP
       2024-09-18 17:21:03 +08:00
    @Kaleidopink File 也有实现 Read trait , 不过实现方式还是用 &File 的实现。 这些其实不是重点,重点是, 为什么读取数据可以是不可变的
    nebkad
        3
    nebkad  
       2024-09-18 17:40:55 +08:00   1
    @bli22ard #2

    https://doc.rust-lang.org/stable/std/fs/struct.File.html

    Note that, although read and write methods require a &mut File, because of the interfaces for Read and Write, the holder of a &File can still modify the file, either through methods that take &File or by retrieving the underlying OS object and modifying the file that way. Additionally, many operating systems allow concurrent modification of files by different processes. Avoid assuming that holding a &File means that the file will not change.
    bli22ard
        4
    bli22ard  
    OP
       2024-09-18 22:09:00 +08:00
    @nebkad 搞这个&File 可以读取(引起数据改变)操作比较迷惑,给人的感觉就是不可变突然可以变了
    zizon
        5
    zizon  
       2024-09-19 11:50:58 +08:00
    也容易理解吧.实际 fd 的状态是 os 维护的,rust 顶多是个上层 API 调用方.
    nebkad
        6
    nebkad  
       2024-09-19 16:15:40 +08:00
    @bli22ard 如果你对 std 的设计不是很满意,你的 OS 平台支持你在 Rust 中使用 &mut 语义的话,你自己重新包装一个 File 也不是很难啊
    bli22ard
        7
    bli22ard  
    OP
       2024-09-19 16:58:24 +08:00
    @nebkad 自己实现容易吗? 主要是好奇,把&mut 搞为&,依然可以执行看起来"改变"的操作。感觉 5 楼的解释比较合理。对于 rust 来说,File 就是不可变的,变的那部分在 os 维护,读取的位置,缓冲区等等。
    nebkad
        8
    nebkad  
       2024-09-19 17:11:00 +08:00
    @bli22ard #7

    std 的源码是公开的,你甚至都不用下载直接在我发给你的链接开始点两下就看到了。
    就算你改成了支持 &mut 语义,如果 OS 不支持独占,难道你还能阻止别的调用者用同样的路径再开一个 File 吗?
    PTLin
        9
    PTLin  
       2024-09-20 10:25:33 +08:00   1
    这个属于 api 设计问题,我举个例子。
    假如有个文件 test.txt 内容是 asd
    ```rust
    let file1 = OpenOptions::new().write(true).open("test.txt").unwrap();
    let file2 = File::open("test.txt").unwrap();

    (&file1).write_all(b"zxc").unwrap();
    let mut buf = String::new();
    (&file2).read_to_string(&mut buf).unwrap();

    assert_eq!(&buf, "zxc");
    ```
    两个变量打开了同样的文件,本来 file2 读取出来的东西应该是 asd ,但是由于打开的是一个文件,file1 修改文件后 file2 就读出来 zxc 了,就是有这种副作用,file2 在根本没有操作的情况下改变了内容,这种性质在语言层面没有办法限制。
    介于 os 中 file 的这种特性,设计成非要 mut 才能 read write 就失去了意义。
    bli22ard
        10
    bli22ard  
    OP
       2024-09-20 12:51:20 +08:00
    @nebkad
    @PTLin 感谢 2 位,说明白了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1574 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 16:24 PVG 00:24 LAX 08:24 JFK 11:24
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86