العمل مع CSV في C++: من التحليل اليدوي إلى مكتبة libcsv
يظل تنسيق CSV (قيم مفصولة بفواصل) أحد أكثر الطرق شيوعًا لتبادل البيانات الجدولية. لا يحتوي C++ على دعم مدمج لـ CSV، ولكن توجد عدة طرق فعالة: التحليل اليدوي باستخدام الأدوات القياسية والمكتبات المتخصصة مثل libcsv. في هذه المقالة، سنشرح كلا الطريقتين، ومزاياهما وعيوبهما، وسنقدم أمثلة عملية على الكود.
ما هو CSV وخصائصه
CSV هو تنسيق نصي، حيث يتوافق كل سطر مع سجل، ويتم فصل الحقول بفواصل. الصعوبات الرئيسية:
- يمكن أن تحتوي الحقول على فواصل إذا كانت محاطة بعلامات اقتباس (
"Hello, world"); - يتم تخطي علامات الاقتباس داخل الحقل بتكرارها (
""); - يمكن أن يكون الفاصل حرفًا آخر (فاصلة منقوطة، علامة تبويب);
- يمكن أن تحتوي الأسطر على أحرف سطر جديد داخل علامات الاقتباس.
لذلك، غالبًا ما يؤدي التقسيم البسيط للسطر بناءً على الفواصل إلى أخطاء. سننظر في طريقتين موثوقتين.
الطريقة 1: التحليل اليدوي باستخدام std::stringstream
مناسبة لملفات CSV البسيطة بدون علامات اقتباس متداخلة أو فواصل أسطر. يتكون التنفيذ من وظيفتين: قراءة حقل واحد وتحليل السطر بأكمله.
#include <iostream>#include <fstream>#include <sstream>#include <vector>#include <string>
// تقسيم سطر CSV إلى حقول مع مراعاة علامات الاقتباسstd::vector<std::string> parseCSVLine(const std::string& line) { std::vector<std::string> fields; std::string field; bool inQuotes = false;
for (size_t i = 0; i < line.size(); ++i) { char c = line[i]; if (c == '"' && !inQuotes) { inQuotes = true; } else if (c == '"' && inQuotes) { // التحقق من علامات الاقتباس الم escaped if (i + 1 < line.size() && line[i + 1] == '"') { field += '"'; ++i; // تخطي علامة الاقتباس التالية } else { inQuotes = false; } } else if (c == ',' && !inQuotes) { fields.push_back(field); field.clear(); } else { field += c; } } fields.push_back(field); // الحقل الأخير return fields;}
int main() { std::ifstream file("data.csv"); std::string line;
while (std::getline(file, line)) { auto fields = parseCSVLine(line); for (const auto& f : fields) { std::cout << "[" << f << "] "; } std::cout << std::endl; } return 0;}الإيجابيات: لا تبعيات خارجية، تحكم كامل في المنطق.
السلبيات: لا يعالج الحقول متعددة الأسطر (قيمة تحتوي على )، يتطلب معالجة يدوية للأخطاء.
الطريقة 2: مكتبة libcsv
libcsv هي مكتبة C خفيفة الوزن لتحليل CSV، مكتوبة بلغة C ولكنها تعمل بشكل ممتاز من C++. تعالج بشكل صحيح جميع الحالات القياسية: علامات الاقتباس، التخطي، الحقول متعددة الأسطر، الفواصل المخصصة.
التثبيت
قم بتنزيل المصدر من SourceForge أو قم بالتثبيت عبر مدير الحزم:
# Linux (Debian/Ubuntu)sudo apt-get install libcsv-dev
# macOSbrew install libcsvمثال لقراءة CSV باستخدام libcsv
#include <iostream>#include <fstream>#include <vector>#include <string>#include <cstring>#include <csv.h>
// هيكل لتخزين البياناتstruct CSVData { std::vector<std::vector<std::string>> rows; std::vector<std::string> currentRow;};
// Ca