مكتبة csv للعمل مع ملفات CSV في Rust
CSV (قيم مفصولة بفواصل) هو أحد أكثر التنسيقات شيوعًا لتخزين البيانات الجدولية. في Rust، توجد مكتبة قوية ومرنة وعالية الأداء للعمل مع CSV وهي csv، والتي تشكل جزءًا من النظام البيئي BurntSushi (مؤلف ripgrep و regex). تتيح لك قراءة البيانات وكتابتها وتسلسلها وإلغاء تسلسلها بأقل جهد وبأقصى درجات أمان الأنواع.
التثبيت
أضف التبعية في Cargo.toml:
[dependencies]csv = "1.3"للتسلسل/إلغاء التسلسل للهياكل، ستحتاج أيضًا إلى serde:
[dependencies]csv = "1.3"serde = { version = "1.0", features = ["derive"] }الميزات الرئيسية للمكتبة
- القراءة والكتابة مع فواصل وعلامات اقتباس ورموز هروب قابلة للتخصيص.
- معالجة تلقائية للرؤوس — العمل بأسماء الأعمدة.
- التسلسل/إلغاء التسلسل عبر
serde— تحويل صفوف CSV إلى هياكل Rust ذات أنواع صارمة. - معالجة مرنة للأخطاء — تحديد موقع الأخطاء (رقم الصف، العمود).
- المعالجة التدفقية — العمل مع الملفات الكبيرة دون تحميلها بالكامل في الذاكرة.
- دعم ترميزات غير UTF-8 (عبر الكريتات الخارجية، مثل
encoding).
قراءة ملف CSV
أبسط طريقة لقراءة CSV هي استخدام Reader والمكرر على السجلات.
مثال 1: القراءة بدون رؤوس
use csv::ReaderBuilder;use std::error::Error;
fn read_csv_no_headers() -> Result<(), Box<dyn Error>> { let data = "name,age,cityAlice,30,LondonBob,25,Paris"; let mut reader = ReaderBuilder::new() .has_headers(false) .from_reader(data.as_bytes());
for result in reader.records() { let record = result?; println!("{:?}", record); } Ok(())}مثال 2: القراءة مع الرؤوس
use csv::Reader;use std::error::Error;
fn read_csv_with_headers() -> Result<(), Box<dyn Error>> { let data = "name,age,cityAlice,30,LondonBob,25,Paris"; let mut reader = Reader::from_reader(data.as_bytes());
for result in reader.deserialize() { let record: (String, u32, String) = result?; println!("{} is {} years old from {}", record.0, record.1, record.2); } Ok(())}استخدام Serde للكتابة الصارمة للأنواع
الطريقة الأكثر ملاءمة هي تعريف هيكل مع تعليق #[derive(Deserialize)].
use serde::Deserialize;use csv::Reader;use std::error::Error;
#[derive(Debug, Deserialize)]struct Person { name: String, age: u32, city: String,}
fn read_typed_csv() -> Result<(), Box<dyn Error>> { let data = "name,age,cityAlice,30,LondonBob,25,Paris"; let mut reader = Reader::from_reader(data.as_bytes());
for result in reader.deserialize() { let person: Person = result?; println!("{:?}", person); } Ok(())}يضمن ذلك تحويل البيانات تلقائيًا إلى الأنواع المطلوبة. إذا، على سبيل المثال، احتوى حقل age على السلسلة "abc"، سيعيد البرنامج خطأً مع تحديد الصف والعمود.
كتابة ملف CSV
للكتابة، يُستخدم Writer. يمكن كتابة سلاسل نصية خام أو هياكل مسلسلة.
مثال: الكتابة عبر هيكل
use serde::Serialize;use csv::Writer;use std::error::Error;
#[derive(Debug, Serialize)]struct Person { name: String, age: u32, city: String,}
fn write_csv() -> Result<(), Box<dyn