【问题标题】:Rust - open dynamic number of writersRust - 开放的动态作者数量
【发布时间】:2021-01-15 17:57:00
【问题描述】:

假设我有来自文件(条形码)的动态数量的输入字符串。 我想根据与输入字符串的匹配来拆分一个巨大的 111GB 文本文件,并将这些命中写入文件。

我不知道会有多少输入。

我已经完成了所有的文件输入和字符串匹配,但是卡在了输出步骤。

理想情况下,我会为输入矢量条形码中的每个输入打开一个文件,只包含字符串。有什么方法可以打开动态数量的输出文件?

一种次优方法是搜索条形码字符串作为输入 arg,但这意味着我必须重复读取大文件。

条形码输入向量只包含字符串,例如 “塔格塔特”, “标签标签”,

理想情况下,如果输入前两个字符串,则输出应如下所示

file1 -> TAGAGTAT.txt
file2 -> TAGAGTAG.txt

感谢您的帮助。

extern crate needletail;
use needletail::{parse_fastx_file, Sequence, FastxReader};
use std::str;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

fn read_barcodes () -> Vec<String> {
    
    // TODO - can replace this with file reading code (OR move to an arguments based model, parse and demultiplex only one oligomer at a time..... )

    // The `vec!` macro can be used to initialize a vector or strings
    let barcodes = vec![
        "TCTCAAAG".to_string(),
        "AACTCCGC".into(),
        "TAAACGCG".into()
        ];
        println!("Initial vector: {:?}", barcodes);
        return barcodes
} 

fn main() {
    //let filename = "test5m.fastq";

    let filename = "Undetermined_S0_R1.fastq";

    println!("Fastq filename: {} ", filename);
    //println!("Barcodes filename: {} ", barcodes_filename);

    let barcodes_vector: Vec<String> = read_barcodes();
    let mut counts_vector: [i32; 30] = [0; 30];

    let mut n_bases = 0;
    let mut n_valid_kmers = 0;
    let mut reader = parse_fastx_file(&filename).expect("Not a valid path/file");
    while let Some(record) = reader.next() {
        let seqrec = record.expect("invalid record");

        // get sequence
        let sequenceBytes = seqrec.normalize(false);
        
        let sequenceText = str::from_utf8(&sequenceBytes).unwrap();
        //println!("Seq: {} ", &sequenceText);

        // get first 8 chars (8chars x 2 bytes)
        let sequenceOligo = &sequenceText[0..8]; 
        //println!("barcode vector {}, seqOligo {} ", &barcodes_vector[0], sequenceOligo);
        if sequenceOligo == barcodes_vector[0]{
            //println!("Hit ! Barcode vector {}, seqOligo {} ", &barcodes_vector[0], sequenceOligo);
            counts_vector[0] =  counts_vector[0] + 1;

        }  

【问题讨论】:

  • “有什么方法可以打开动态数量的输出文件” - Vec&lt;File&gt;?我不清楚你希望你的输出是什么样子。另外,你说你已经完成了字符串匹配部分,但你似乎也不确定如何划分工作(?),你究竟需要什么帮助?
  • Vec 听起来很有用。我只需要一个示例 a)如何正确实例化以相关字符串命名的文件向量 b)正确设置输出文件对象 c)写入这些文件(尽管解析器应该提供一个方法)

标签: file rust bioinformatics


【解决方案1】:

您可能想要HashMap&lt;String, File&gt;。您可以像这样从条形码矢量构建它:

use std::collections::HashMap;
use std::fs::File;
use std::path::Path;

fn build_file_map(barcodes: &[String]) -> HashMap<String, File> {
    let mut files = HashMap::new();

    for barcode in barcodes {
        let filename = Path::new(barcode).with_extension("txt");
        let file = File::create(filename).expect("failed to create output file");
        files.insert(barcode.clone(), file);
    }

    files
}

你可以这样称呼它:

let barcodes = vec!["TCTCAAAG".to_string(), "AACTCCGC".into(), "TAAACGCG".into()];
let file_map = build_file_map(&barcodes);

你会得到一个像这样写入的文件:

let barcode = barcodes[0];
let file = file_map.get(&barcode).expect("barcode not in file map");
// write to file

【讨论】:

  • 谢谢,这是一个很好的答案。我看到了我现在在概念上缺少的东西。我将尝试实现这一点。 -> 完成,文件已根据需要创建。谢谢!
【解决方案2】:

我只需要一个示例 a) 如何正确实例化以相关字符串命名的文件向量 b) 正确设置输出文件对象 c) 写入这些文件。

这是一个注释示例:

use std::io::Write;
use std::fs::File;
use std::io;

fn read_barcodes() -> Vec<String> {
    // read barcodes here
    todo!()
}

fn process_barcode(barcode: &str) -> String {
    // process barcodes here
    todo!()
}

fn main() -> io::Result<()> {
    let barcodes = read_barcodes();
    
    for barcode in barcodes {
        // process barcode to get output
        let output = process_barcode(&barcode);
        
        // create file for barcode with {barcode}.txt name
        let mut file = File::create(format!("{}.txt", barcode))?;
        
        // write output to created file
        file.write_all(output.as_bytes());
    }
    
    Ok(())
}

【讨论】:

  • 谢谢,它的结构非常清晰且有用。最后的 Ok(()) 是否返回单元类型 / 0 / void 如此处所述 stackoverflow.com/questions/24842271/… ,还是我弄错了?
  • @colindaven 是一样的,我将返回类型 io::Result&lt;()&gt; 添加到 main 所以我可以在 File::create 函数调用上使用 ? 运算符,但结果我也有如果一切顺利,以Ok(()) 结束main
猜你喜欢
  • 1970-01-01
  • 2017-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 1970-01-01
  • 2018-12-24
  • 2021-05-29
相关资源
最近更新 更多