【问题标题】:how read mixed binary/text file with io::Cursor and byteorder?如何使用 io::Cursor 和字节序读取混合的二进制/文本文件?
【发布时间】:2021-04-07 01:53:04
【问题描述】:

我想读取/解析混合二进制/文本的数据文件。此文件不是 utf_8 格式,无法转换。

我的数据文件头的结构是:

#[derive(Debug)]   
Struct DataParse{
       
       file_num : u16{2}, 
       file_name: char{16},
       file_size: u32{4},
       file_off: u32{4},
       file_dum: u8{1}
    
}

我使用 io::Cursor 和内存缓冲区和 crate 字节序对我的文件进行操作:

use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use byteorder::{LittleEndian, ReadBytesExt};
use std::io::Cursor;

    fn read_parse_file(path_of_file: &str) -> io::Result<()> {
    
        let path = Path::new(&path_of_file);
        let display = path.display();
        println!("xxx : {}", &display);
    
        let mut f = File::open(&path)?;  
        let mut buffer = vec![0; 27];
    
        f.read_exact(&mut buffer).unwrap(); 
    
        let mut vec_pointer = Cursor::new(buffer);
    
        let filenum = vec_pointer.read_u16::<LittleEndian>().unwrap();
        let filename = // ?????????
        let filesize = vec_pointer.read_u32::<LittleEndian>().unwrap();
        let fileoff = vec_pointer.read_u32::<LittleEndian>().unwrap();
        let filendum = vec_pointer.read_u8().unwrap();
    
        let dat_binary = DataParse {file_num: filenum, file_name: filename, file_size: filesize, file_off: fileoff,  file_dum: filendum  };

        println!("{:?}", dat_binary);

    
        Ok(())
    
    }

我的问题是,在我的情况下,如何在混合二进制/文本中获取 char 类型的“结构文件名”?

【问题讨论】:

  • 这取决于您希望如何在最终结构中存储已解析的文本。是StringVec&lt;u8&gt;[u8; 16] 还是[char; 16]?回想一下,char 是一个 4 字节的数字,用于保存 Unicode 代码点,因此它可能不是您想要的。
  • @ddulaney :嗯,好的,但在我的最终结构中有一个光标,如果我想将解析的文本存储在字符串中,该怎么办? String::from_utf8().unwrap() 不适用于 std::io::Cursor<:vec::vec>>
  • from_utf8 依赖于您分配一个新的Vec 并预填充它。 vec![0u8; 16]分配一个16字节的vec,然后在光标上read_exact读入它,然后将它传递给String::from_utf8
  • @ddulaney:感谢您的帮助。非常感谢。我有最后一个问题。这里是我的代码的输出控制台:file_num: 2621, filename_of_ressource:"LESSON.BIN\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}", size: 792, off: 65536, dum: 0 这是我一直在寻找的,所以没关系,但每个文件名都有不同的长度。而且我无法提前定义。如何更正这个:LESSON.BIN\u{0}\u{0}\u{0}\u{0}\u{0}\u{0} 到这个:LESSON.BIN
  • 使用String::find 找到第一个空的索引,然后String::truncate 切断那里的字符串。如果字符串中没有\u{0} 字符,find 将返回None

标签: rust


【解决方案1】:

感谢@ddulaney 帮助我。

fn read_parse_file(path_of_file: &str) -> io::Result<()> {

    let path = Path::new(&path_of_file);
    let display = path.display();
    println!("path is : {}", &display);

    let mut f = File::open(&path)?;

    let mut buffer = vec![0; 27];
    let mut string_buffer = vec![0u8; 16];

    f.read_exact(&mut buffer).unwrap(); 
  
    let mut vec_pointer = Cursor::new(buffer);

    let filenum = vec_pointer.read_u16::<LittleEndian>().unwrap();

    vec_pointer.read_exact(&mut string_buffer).unwrap();
    let mut filename = String::from_utf8(string_buffer).unwrap(); 
    match filename.find('\0'){
        None => {},
        Some(v) => { filename.truncate(v) },   
    }
        
    let filesize = vec_pointer.read_u32::<LittleEndian>().unwrap();
    let fileoff = vec_pointer.read_u32::<LittleEndian>().unwrap();
    let filendum = vec_pointer.read_u8().unwrap();

    let dat_binary = DatBinary {file_num : filenum, filename_of_ressource : filename, size : filesize, off : fileoff, dum : filendum}; 

    println!("{:?}", dat_binary);  

    Ok(())

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-14
    • 2013-12-06
    • 1970-01-01
    • 2018-12-11
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多