[csv] एक सीएसवी फ़ाइल में अल्पविराम से निपटना



Answers

2017 के लिए, सीएसवी पूरी तरह से निर्दिष्ट है - आरएफसी 4180।

यह एक बहुत ही सामान्य विनिर्देश है, और पूरी तरह से कई पुस्तकालयों ( github.com/Flinesoft/CSVImporter ) द्वारा कवर किया गया है।

बस किसी भी आसानी से उपलब्ध सीएसवी लाइब्रेरी का उपयोग करें - जो आरएफसी 4180 कहना है।

वास्तव में सीएसवी प्रारूप और कॉमा को संभालने के लिए एक कल्पना है:

लाइन ब्रेक (सीआरएलएफ), डबल कोट्स और कॉमा युक्त फ़ील्ड डबल-कोट्स में संलग्न किए जाने चाहिए।

http://tools.ietf.org/html/rfc4180

तो, मूल्य foo और bar,baz , आप यह करते हैं:

foo,"bar,baz"

विचार करने के लिए एक और महत्वपूर्ण आवश्यकता (spec से भी):

यदि फ़ील्ड को घेरने के लिए डबल-कोट्स का उपयोग किया जाता है, तो किसी फ़ील्ड के अंदर दिखाई देने वाला डबल-कोट एक और डबल कोट के साथ इसे से बचकर अवगत होना चाहिए। उदाहरण के लिए:

"aaa","b""bb","ccc"
Question

मैं एक सीएसवी फ़ाइल को कैसे संभालना है, उसके बारे में सुझावों की तलाश कर रहा हूं, फिर हमारे ग्राहकों द्वारा अपलोड किया गया है, और उसमें कंपनी के नाम की तरह मूल्य में कॉमा हो सकता है।

हम जिन विचारों को देख रहे हैं उनमें से कुछ हैं: उद्धृत पहचानकर्ता (मूल्य "," मान "," आदि) या एक का उपयोग कर | एक अल्पविराम के बजाय। सबसे बड़ी समस्या यह है कि हमें इसे आसान बनाना है, या ग्राहक इसे नहीं करेगा।




मुझे लगता है कि इस समस्या का सबसे आसान समाधान ग्राहक को एक्सेल में सीएसवी खोलने के लिए है, और फिर ctrl + r को सभी अल्पविरामों को बदलने के लिए जो भी पहचानकर्ता आप चाहते हैं। यह ग्राहक के लिए बहुत आसान है और आपकी पसंद के डिलीमीटर को पढ़ने के लिए आपके कोड में केवल एक ही बदलाव की आवश्यकता है।




यदि आप एक * निक्स-सिस्टम पर हैं , तो sed तक पहुंच है और केवल आपके सीएसवी के एक विशिष्ट क्षेत्र में एक या अधिक अवांछित कॉमा हो सकते हैं, आप निम्न एक-लाइनर का उपयोग इन्हें " आरएफसी 4180 धारा 2 प्रस्ताव करता है:

sed -r 's/([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*)/\1"\2"\3/' inputfile

किन क्षेत्र पर अवांछित कॉमा (ओं) हो सकता है, इस पर निर्भर करता है कि आपको रेगेक्स (और प्रतिस्थापन) के कैप्चरिंग समूहों को बदलना / विस्तार करना है।
उपरोक्त उदाहरण उद्धरण चिह्नों में चौथे क्षेत्र (छः में से) को घेर लेगा।

इन --in-place-option साथ संयोजन में आप इन परिवर्तनों को सीधे फ़ाइल पर लागू कर सकते हैं।

सही रेगेक्स को "निर्माण" करने के लिए, अनुसरण करने के लिए एक सरल सिद्धांत है:

  1. आपके सीएसवी के हर क्षेत्र के लिए जो अनचाहे कॉमा के साथ मैदान से पहले आता है, आप एक [^,]*, लिखते हैं [^,]*, और उन्हें एक कैप्चरिंग समूह में एक साथ रख देते हैं।
  2. उस फ़ील्ड के लिए जिसमें अवांछित कॉमा (नों) लिखते हैं (.*)
  3. अनचाहे कॉमा (ओं) के साथ मैदान के बाद हर क्षेत्र के लिए आप एक लिखते हैं ,.* और उन्हें एक कैप्चरिंग समूह में एक साथ रख दें।

विशिष्ट फ़ील्ड के आधार पर विभिन्न संभावित रेगेक्स / प्रतिस्थापन का संक्षिप्त अवलोकन यहां दिया गया है। यदि नहीं दिया गया है, प्रतिस्थापन \1"\2"\3

([^,]*)(,.*)                     #first field, regex
"\1"\2                           #first field, substitution

(.*,)([^,]*)                     #last field, regex
\1"\2"                           #last field, substitution


([^,]*,)(.*)(,.*,.*,.*)          #second field (out of five fields)
([^,]*,[^,]*,)(.*)(,.*)          #third field (out of four fields)
([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*) #fourth field (out of six fields)

यदि आप अवांछित कॉमा को उद्धरण चिह्नों के साथ संलग्न करने के बजाय sed साथ हटाना चाहते हैं तो इस उत्तर का संदर्भ लें।




किसी भी अच्छी तरह से बनाए गए सीएसवी (.net) - CsvHelper निपटने के लिए न्यूजेट के माध्यम से एक लाइब्रेरी उपलब्ध है

कक्षा में मानचित्र करने के लिए उदाहरण:

var csv = new CsvReader( textReader );
var records = csv.GetRecords<MyClass>();

व्यक्तिगत फ़ील्ड पढ़ने के लिए उदाहरण:

var csv = new CsvReader( textReader );
while( csv.Read() )
{
    var intField = csv.GetField<int>( 0 );
    var stringField = csv.GetField<string>( 1 );
    var boolField = csv.GetField<bool>( "HeaderName" );
}

क्लाइंट को फ़ाइल प्रारूप को चलाने दें:
, मानक फ़ील्ड डेलीमीटर है, " मानक मान है जो फ़ील्ड से बचने के लिए उपयोग किया जाता है जिसमें एक डिलीमीटर, उद्धरण या रेखा समाप्त होती है।

खेतों के लिए (उदाहरण के लिए) # उपयोग करने के लिए और ' भागने के लिए:

var csv = new CsvReader( textReader );
csv.Configuration.Delimiter = "#";
csv.Configuration.Quote = ''';
// read the file however meets your needs

अधिक दस्तावेज़ीकरण




मैं आमतौर पर उन क्षेत्रों को यूआरएल-एन्कोड करता हूं जिनमें कोई कॉमा या कोई विशेष वर्ण हो सकता है। और तब इसे किसी भी दृश्य माध्यम में उपयोग / प्रदर्शित होने पर डीकोड करें।

(अल्पविराम% 2 सी बन जाता है)

प्रत्येक भाषा में URL-encode और स्ट्रिंग को डीकोड करने के तरीके हो सकते हैं।

उदाहरण के लिए, जावा में

URLEncoder.encode(myString,"UTF-8"); //to encode
URLDecoder.decode(myEncodedstring, "UTF-8"); //to decode

मुझे पता है कि यह एक बहुत ही सामान्य समाधान है और यह स्थिति के लिए आदर्श नहीं हो सकता है जहां उपयोगकर्ता मैन्युअल रूप से सीएसवी फ़ाइल की सामग्री देखना चाहता है।




मुझे मिला सबसे सरल समाधान एक लिबर ऑफिस का उपयोग करता है:

  1. सभी शाब्दिक " द्वारा बदलें
  2. अपनी स्ट्रिंग के चारों ओर डबल उद्धरण रखें

आप एक्सेल का उपयोग करने वाले व्यक्ति का भी उपयोग कर सकते हैं:

  1. सभी शाब्दिक " द्वारा "" बदलें
  2. अपनी स्ट्रिंग के चारों ओर डबल उद्धरण रखें

अन्य लोगों को ध्यान दें कि उपरोक्त केवल चरण 2 करने की अनुशंसा की जाती है, लेकिन यह उन लाइनों के साथ काम नहीं करती है जहां " एक के बाद होता है, जैसे सीएसवी में जहां आप स्ट्रिंग hello",world साथ एक कॉलम रखना चाहते हैं hello",world , जैसा कि सीएसवी पढ़ेगा:

"hello",world"

जिसे दो स्तंभों के साथ पंक्ति के रूप में व्याख्या किया जाता है: hello और world"




यदि आप सामान्य रूप से फ़ाइलों को पार्स करने के लिए एक और शैक्षिक अभ्यास में रूचि रखते हैं (उदाहरण के रूप में सीएसवी का उपयोग करके), तो आप जूलियन बकनॉल द्वारा इस आलेख को देख सकते हैं। मुझे लेख पसंद है क्योंकि यह चीजों को बहुत छोटी समस्याओं में तोड़ देता है जो बहुत कम दुर्बल हैं। आप पहले व्याकरण बनाते हैं, और एक बार आपके पास एक अच्छा व्याकरण होता है, यह व्याकरण को कोड में बदलने के लिए अपेक्षाकृत आसान और विधिवत प्रक्रिया है।

आलेख सी # का उपयोग करता है और कोड डाउनलोड करने के लिए नीचे एक लिंक है।




तारों के चारों ओर डबल कोट्स रखो। आमतौर पर here

आला एली,

आप दो डबल कोट्स के रूप में एक डबल कोट से बचें। जैसे "test1", "foo" "bar", "test2"




जैसा कि हार्पो के उत्तर में मेरी टिप्पणी में बताया गया है, उनका समाधान अच्छा है और ज्यादातर मामलों में काम करता है, हालांकि कुछ परिदृश्यों में जब कॉमा एक-दूसरे के निकट सीधे होते हैं तो यह अल्पविरामों पर विभाजित होने में विफल रहता है।

यह रेगेक्स स्ट्रिंग के कारण अप्रत्याशित रूप से वर्टैबिम स्ट्रिंग के रूप में व्यवहार कर रहा है। इस व्यवहार को सही करने के लिए, रेगेक्स स्ट्रिंग में सभी "वर्णों को वर्टबैम से बचने के बिना मैन्युअल रूप से बचने की आवश्यकता है।

अर्थात। Regex मैन्युअल escapes का उपयोग कर यह होना चाहिए:

",(?=(?:[^\"\"]*\"\"[^\"\"]*\"\")*(?![^\"\"]*\"\"))"

जो अनुवाद करता है ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"

एक वर्टैबिम स्ट्रिंग का उपयोग करते समय @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))" यह व्यवहार करता है जैसा कि आप देख सकते हैं कि क्या आप रेगेक्स डीबग करते हैं:

",(?=(?:[^"]*"[^"]*")*(?![^"]*"))"

तो संक्षेप में, मैं हैरपो के समाधान की सलाह देता हूं, लेकिन इस छोटे गोचा के लिए बाहर देखो!

यदि यह त्रुटि होती है (यदि आपके पास कॉलम की पूर्व-ज्ञात संख्या है) तो मैंने आपको सूचित करने के लिए सीएसवी रीडर में एक छोटा वैकल्पिक असफलता शामिल किया है:

if (_expectedDataLength > 0 && values.Length != _expectedDataLength) 
throw new DataLengthException(string.Format("Expected {0} columns when splitting csv, got {1}", _expectedDataLength, values.Length));

इसे कन्स्ट्रक्टर के माध्यम से इंजेक्शन दिया जा सकता है:

public CsvReader(string fileName, int expectedDataLength = 0) : this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
    _expectedDataLength = expectedDataLength;
}



चूंकि यह सामान्य प्रथाओं के बारे में है, हम अंगूठे के नियमों से शुरू करते हैं:

  1. CSV का उपयोग न करें, इसके बजाय xml फ़ाइल को पढ़ने और लिखने के लिए लाइब्रेरी के साथ एक्सएमएल का उपयोग करें।

  2. यदि आपको सीएसवी का उपयोग करना चाहिए। इसे ठीक से करें और CSV फ़ाइलों को पार्स और स्टोर करने के लिए एक मुफ्त लाइब्रेरी का उपयोग करें।

औचित्य साबित करने के लिए 1), अधिकांश सीएसवी पार्सर एन्कोडिंग एन्कोडिंग नहीं कर रहे हैं, इसलिए यदि आप यूएस-एएससीआईआई से निपट नहीं रहे हैं तो आप परेशानियों के लिए पूछ रहे हैं। उदाहरण के लिए एक्सेलिंग के बारे में किसी भी नोट के बिना एक्सेल 2002 स्थानीय एन्कोडिंग में सीएसवी संग्रहीत कर रहा है। सीएसवी मानक व्यापक रूप से अपनाया नहीं जाता है :( दूसरी तरफ एक्सएमएल मानक अच्छी तरह से अपनाया जाता है और यह एन्कोडिंग को अच्छी तरह से संभालता है।

औचित्य साबित करने के लिए 2), लगभग सभी भाषाओं के लिए सीएसवी पार्सर्स के आस-पास बहुत सारे हैं इसलिए समाधान को बहुत सरल दिखने के बावजूद पहिया को फिर से शुरू करने की कोई आवश्यकता नहीं है।

कुछ नाम देने के लिए:

  • पाइथन उपयोग के लिए csv मॉड्यूल में निर्माण

  • पर्ल चेक सीपीएएन और Text::CSV

  • PHP उपयोग के लिए fgetcsv / fputcsv कार्यों में निर्माण के लिए

  • जावा चेक SuperCVS पुस्तकालय के लिए

वास्तव में इसे हाथ से लागू करने की कोई आवश्यकता नहीं है यदि आप इसे एम्बेडेड डिवाइस पर पार्स नहीं कर रहे हैं।




Related



Tags

csv