Я пытаюсь эффективно разобрать CSV-файлы по строкам без лишнего выделения памяти.Как назначить кусочки при переходе через Vec в ржавчине без копирования?
Поскольку мы не можем индексировать в строки в Русте, моя идея состояла в том, чтобы создать-структуру для каждой строки, которая имеет в собственности Vec<char>
из строки символов и несколько &[char]
срезов, представляющих места в этом Vec
полей, которые требуют дальнейшая обработка.
Я поддерживаю только английский язык, поэтому нет необходимости в графах Unicode.
Я хватаю каждую строку из BufReader
, собрать его в мою Vec<char>
, а затем перебирать символы заметить правильные смещения для каждого поля среза:
let mut r_line: String;
let mut char_count: usize;
let mut comma_count: usize;
let mut payload_start: usize;
for stored in &ms7_files {
let reader = BufReader::new(File::open(&stored.as_path()).unwrap());
for line in reader.lines() {
r_line = line.unwrap().to_string();
let r_chars: Vec<char> = r_line.chars().collect();
char_count = 0;
comma_count = 0;
payload_start = 0;
for chara in r_chars {
char_count += 1;
if chara == ',' {
comma_count += 1;
if comma_count == 1 {
let r_itemid = &r_chars[0..char_count - 1];
payload_start = char_count + 1;
} else if comma_count == 2 {
let r_date = &r_chars[payload_start..char_count - 1];
let r_payload = & r_chars[payload_start..r_line.len() - 1];
}
}
}
// Code omitted here to initialize a struct described in my
// text above and add it to a Vec for later processing
}
}
Все идет гладко до тех пор, код внутри if
испытаний на comma_count
, где я пытаюсь создать ломтики char в Vec
. Когда я пытаюсь скомпилировать, я получаю ужас:
proc_sales.rs:87:23: 87:30 error: use of moved value: `r_chars` [E0382]
proc_sales.rs:87 let r_itemid = &r_chars[0..char_count - 1];
^~~~~~
proc_sales.rs:87:23: 87:30 help: run `rustc --explain E0382` to see a detailed explanation
proc_sales.rs:82:17: 82:24 note: `r_chars` moved here because it has type `collections::vec::Vec<char>`, which is non-copyable
proc_sales.rs:82 for chara in r_chars {
^~~~~~~
для каждой попытки создания среза. Я могу понять, почему компилятор жалуется. То, что я пытаюсь понять, - это лучшая стратегия сбора и обработки этих данных, не прибегая к большому количеству копий и клонирования. Черт, если бы я мог оставить оригинал String
(для каждой файловой строки), принадлежащий BufReader
, и просто держись за кусочки в это, я бы!
Не стесняйтесь прокомментировать исправление вышеуказанного кода, а также предложения по альтернативным подходам к этой проблеме, которые ограничивают ненужное копирование.
Я не могу проверить, потому что я нахожусь в поезде .. но я готов поспорить, потому что ваш цикл for - это, по сути, синтаксический сахар для 'r_chars.into_iter()' .., который будет владеть. Если вместо этого явно использовать 'для chara в r_chars.iter()' .., то он вернет ссылки. –
** Определенно ** используйте [csv crate] (https://github.com/BurntSushi/rust-csv). «На самом низком уровне анализатор может декодировать CSV со скоростью около 200 МБ/с». И это влечет за собой нулевые распределения. – Shepmaster
* Так как мы не можем индексировать строки в Rust, * - уверен, что вы можете. Вам просто нужно использовать байтовые смещения, которые лежат на границах символов UTF-8. Существуют даже итераторы, такие как ['char_indices'] (http://doc.rust-lang.org/std/primitive.str.html#method.char_indices). – Shepmaster