CSV फ़ाइल में अल्पविराम से निपटना


472

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

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


ग्राहक इसे लिख रहा है और इसे अपलोड कर रहा है
बॉब द जेनिटर

1
यहाँ csv फ़ाइल में कमोस के अंदर प्रबंधन का समाधान है। visit stackoverflow.com/questions/9889225/…
हसन अबरार

iOS पर, अनिवार्य रूप से आपको github.com/Flinesoft/CSVImporter
Fattie

3
ध्यान दें कि यह QA पुराना है। आजकल csv का अर्थ है RFC 4180 और वह है।
फेटी

मेरे पास एक ही मुद्दा है, एक csv फ़ाइल में एक कॉलम को कुल करने की कोशिश कर रहा है जो अल्पविराम से अलग है। एक awk कमांड के साथ कोई समस्या नहीं है। दुर्भाग्य से कुछ कोशिकाओं में अल्पविराम (उदाहरण के लिए एक पते में) हो सकता है, अन्य कोशिकाएं नहीं होंगी। लिनक्स संगत समाधान की तलाश है लेकिन यह सुनिश्चित नहीं है कि कहां से शुरू करें।
हरियाली

जवाबों:


223

जैसा कि दूसरों ने कहा है, आपको उन मूल्यों से बचना होगा जिनमें उद्धरण शामिल हैं। यहाँ C♯ में थोड़ा CSV रीडर है जो एम्बेडेड कोट्स और कैरिज रिटर्न सहित उद्धृत मूल्यों का समर्थन करता है।

वैसे, यह इकाई-परीक्षण कोड है। मैं इसे अभी पोस्ट कर रहा हूं क्योंकि यह प्रश्न बहुत अधिक लग रहा है और अन्य लोग पूरी लाइब्रेरी नहीं चाहते हैं जब सरल सीएसवी समर्थन करेगा।

आप इसका उपयोग इस प्रकार कर सकते हैं:

using System;
public class test
{
    public static void Main()
    {
        using ( CsvReader reader = new CsvReader( "data.csv" ) )
        {
            foreach( string[] values in reader.RowEnumerator )
            {
                Console.WriteLine( "Row {0} has {1} values.", reader.RowIndex, values.Length );
            }
        }
        Console.ReadLine();
    }
}

यहाँ कक्षाएं हैं। ध्यान दें कि आप Csv.Escapeफ़ंक्शन का उपयोग मान्य CSV लिखने के लिए भी कर सकते हैं ।

using System.IO;
using System.Text.RegularExpressions;

public sealed class CsvReader : System.IDisposable
{
    public CsvReader( string fileName ) : this( new FileStream( fileName, FileMode.Open, FileAccess.Read ) )
    {
    }

    public CsvReader( Stream stream )
    {
        __reader = new StreamReader( stream );
    }

    public System.Collections.IEnumerable RowEnumerator
    {
        get {
            if ( null == __reader )
                throw new System.ApplicationException( "I can't start reading without CSV input." );

            __rowno = 0;
            string sLine;
            string sNextLine;

            while ( null != ( sLine = __reader.ReadLine() ) )
            {
                while ( rexRunOnLine.IsMatch( sLine ) && null != ( sNextLine = __reader.ReadLine() ) )
                    sLine += "\n" + sNextLine;

                __rowno++;
                string[] values = rexCsvSplitter.Split( sLine );

                for ( int i = 0; i < values.Length; i++ )
                    values[i] = Csv.Unescape( values[i] );

                yield return values;
            }

            __reader.Close();
        }
    }

    public long RowIndex { get { return __rowno; } }

    public void Dispose()
    {
        if ( null != __reader ) __reader.Dispose();
    }

    //============================================


    private long __rowno = 0;
    private TextReader __reader;
    private static Regex rexCsvSplitter = new Regex( @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))" );
    private static Regex rexRunOnLine = new Regex( @"^[^""]*(?:""[^""]*""[^""]*)*""[^""]*$" );
}

public static class Csv
{
    public static string Escape( string s )
    {
        if ( s.Contains( QUOTE ) )
            s = s.Replace( QUOTE, ESCAPED_QUOTE );

        if ( s.IndexOfAny( CHARACTERS_THAT_MUST_BE_QUOTED ) > -1 )
            s = QUOTE + s + QUOTE;

        return s;
    }

    public static string Unescape( string s )
    {
        if ( s.StartsWith( QUOTE ) && s.EndsWith( QUOTE ) )
        {
            s = s.Substring( 1, s.Length - 2 );

            if ( s.Contains( ESCAPED_QUOTE ) )
                s = s.Replace( ESCAPED_QUOTE, QUOTE );
        }

        return s;
    }


    private const string QUOTE = "\"";
    private const string ESCAPED_QUOTE = "\"\"";
    private static char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
}

2
आपको अपने अनुप्रयोग के आधार पर, विंडोज़ अनुपालन के लिए \ n \ n का अनुवाद करने की आवश्यकता हो सकती है।
विषैला पौधा

3
@NNNaeem, विस्तृत करने के लिए देखभाल?
हार्प जूल

यह एक सीएसवी फ़ाइल पंक्ति में आइटमों को सही ढंग से नहीं गिन रहा है, यह खेतों और साहस रिटर्न और टैप में अल्पविराम के साथ अच्छी तरह से काम नहीं कर रहा है
नाडा एन। हंतौली

-1 ओपी उस भाषा को निर्दिष्ट नहीं करता है जो फ़ाइल बना रही है। यदि कोई अन्य प्रोग्रामर किसी भी भाषा में समाधान की तलाश में यहां आता है, लेकिन C #, तो उन्हें कोई समाधान नहीं मिलेगा जिसका वे इस उत्तर में उपयोग कर सकते हैं।
बेन लेगिएरो

8
@ BenC.R.Leggiero, तो मुझे लगता है कि आपको अपने प्रश्न को कम करना चाहिए, क्योंकि यह आपके मानक के लिए अचूक है। जैसा कि यह है, एक साधारण कल्पना के औपचारिक कार्यान्वयन के लिए कोड की मात्रा होती है, और आसानी से किसी भी सामान्य भाषा में इसका अनुवाद किया जा सकता है।
harpo

395

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

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

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


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

पंक्ति विराम (CRLF), दोहरे उद्धरण और अल्पविराम वाले फ़ील्ड को दोहरे उद्धरणों में संलग्न किया जाना चाहिए।

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

इसलिए, मानों के लिए fooऔर bar,baz, आप ऐसा करते हैं:

foo,"bar,baz"

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

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

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

120
"लाइन ब्रेक (CRLF), दोहरे उद्धरण और अल्पविराम वाले फ़ील्ड को दोहरे उद्धरणों में संलग्न किया जाना चाहिए।"
एली

42
"यदि डबल-कोट्स का उपयोग खेतों को घेरने के लिए किया जाता है, तो एक मैदान के अंदर दिखाई देने वाले दोहरे-उद्धरण को दूसरे दोहरे उद्धरण से पहले ही भाग जाने से बचना चाहिए।"
सी। ड्रैगन 76

11
वास्तव में एक युक्ति नहीं है, लेकिन फिर भी शायद काम है। यह कहता है ... "अस्तित्व में कोई औपचारिक विनिर्देश नहीं है, जो सीएसवी फ़ाइलों की विस्तृत विविधता की अनुमति देता है। यह खंड उस प्रारूप का दस्तावेजीकरण करता है जो सबसे अधिक कार्यान्वयन के बाद लगता है।"
जस्टिन क्लार्क

5
इसके अलावा, यह मत भूलो कि इसके नाम के बावजूद, पंक्ति में CSV मान केवल अल्पविराम से ही नहीं - कम से कम विंडोज प्लेटफार्मों पर अलग हो सकते हैं। यह वर्तमान क्षेत्रीय सेटिंग्स (कमांड लाइन में intl.cpl, "उन्नत सेटिंग्स") पर निर्भर करता है, विशेष रूप से, सूची विभाजक System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator:।
lxa

4
कृपया इस उत्तर में प्रासंगिक जानकारी डालें, लिंक के अलावा, ए) उपरोक्त टिप्पणियों (और मेरा) में से अधिकांश को हटा दें, बी) उत्तरदाता की तुलना में इतने अधिक लोगों को बचाने के लिए समय अभी तक एक और पृष्ठ पर जाएं और प्रासंगिक ढूंढें डेटा, सी) लिंक रोट रोकें।
user66001

76

CSV प्रारूप कॉमा का उपयोग अलग-अलग मानों के लिए करता है, वे मान जिनमें कैरेज़ रिटर्न, लाइनफ़ीड, अल्पविराम या डबल कोट्स दोहरे-कोट्स से घिरे होते हैं। वे मान जिनमें दोहरे उद्धरण शामिल हैं, और प्रत्येक शाब्दिक उद्धरण तुरंत पूर्ववर्ती उद्धरण से बच जाता है: उदाहरण के लिए, 3 शब्द संकेत:

test
list, of, items
"go" he said

निम्नानुसार एन्कोड किया जाएगा:

test
"list, of, items"
"""go"" he said"

किसी भी क्षेत्र को उद्धृत किया जा सकता है, लेकिन केवल ऐसे फ़ील्ड जिनमें अल्पविराम, सीआर / एनएल, या उद्धरण उद्धृत होने चाहिए

CSV प्रारूप के लिए कोई वास्तविक मानक नहीं है , लेकिन लगभग सभी अनुप्रयोग यहां दिए गए सम्मेलनों का पालन करते हैं । जिस RFC का उल्लेख अन्यत्र किया गया था, वह CSV के लिए एक मानक नहीं है, यह MIME के ​​भीतर CSV का उपयोग करने के लिए RFC है और इसमें कुछ अपरंपरागत और अनावश्यक सीमाएँ शामिल हैं, जो इसे MIME के ​​बाहर बेकार बनाती हैं।

एक गेटा जो मैंने देखा है कि कई CSV मॉड्यूल इस तथ्य को समायोजित नहीं करते हैं कि एक ही क्षेत्र में कई लाइनों को एन्कोड किया जा सकता है, जिसका अर्थ है कि आप यह नहीं मान सकते हैं कि प्रत्येक पंक्ति एक अलग रिकॉर्ड है, आपको या तो अपने में newlines की अनुमति नहीं देने की आवश्यकता है डेटा या इसे संभालने के लिए तैयार रहें।


40

स्ट्रिंग के चारों ओर दोहरे उद्धरण लगाएं। आम तौर पर एक्सेल क्या करता है

अला एली,

आप दो दोहरे उद्धरणों के रूप में एक दोहरे उद्धरण से बचते हैं। जैसे "टेस्ट 1", "फू" "बार", "टेस्ट 2"


मूल रूप से एक उद्धृत आइडेंटिफ़ायर के रूप में एक ही अवधारणा
बॉब द जेनिटर

1
आप दो दोहरे उद्धरणों के रूप में एक दोहरे उद्धरण से बचते हैं। जैसे "टेस्ट 1", "फू" "बार", "टेस्ट 2"
एली

जब एक "अल्पविराम द्वारा तुरंत पीछा किया जाता है, तो बस स्ट्रिंग के चारों ओर दोहरे उद्धरण डालने से काम नहीं
चलता

9

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

डेटा, अधिक डेटा, अधिक डेटा \, यहां तक ​​कि अभी भी अधिक

आपको उद्धरणों का मिलान करने का प्रयास करने की आवश्यकता नहीं है, और आपके पास पार्स करने के लिए कुछ अपवाद नहीं हैं। यह आपके कोड को भी सरल करता है।


3
त्वरित और गंदे लेकिन काम नहीं करता है यदि आपके पास वास्तव में एक प्रविष्टि है जिसमें "\",
सर्प काया

1
सर्प, यही कारण है कि एक डबल \\ एक बचा हुआ बैकस्लैश है, क्योंकि वह अब एक और विशेष चरित्र बन गया है।
ग्रुंगोंडोला

1
यह काम करता है, लेकिन CSV नहीं है। यह एक डीएसवी है
TRIG

8

वहाँ बहुत अच्छी तरह से गठित CSV (.net) - CsvHel से निपटने के लिए नगेट के माध्यम से एक पुस्तकालय उपलब्ध है।

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

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

अधिक प्रलेखन


3
यह बेहतर होगा यदि आपने CsvHelperओपी की समस्या को हल करने के लिए पुस्तकालय का उपयोग करने का एक उदाहरण शामिल किया ।
जॉर्ज स्टॉकर

क्यों लगभग .Net में सब कुछ एक "हेल्पर" हो गया है ... शब्द व्यर्थ के पास है ... जैसे "प्रबंधक"।
बजे

5

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

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

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

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

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

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

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

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

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

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;
}

आप हैडर रो को कैसे हैंडल करेंगे? मैं सी # वस्तुओं के लिए सीएसवी को मैप करने की कोशिश कर रहा हूं जो सभी प्रकार के हैं, लेकिन हेडर पंक्ति इसे तोड़ देती है क्योंकि इसके सभी तार ...
tcoe

के [^""]रूप में ही नहीं है [^"]? एक चरित्र वर्ग विनिर्देश के अंदर एक चरित्र का दोहराव निरर्थक है, है ना?
मिन्ह

4

Microsoft.VisualBasic का संदर्भ जोड़ें (हाँ, यह VisualBasic कहता है, लेकिन यह C # में भी काम करता है - याद रखें कि अंत में यह सिर्फ IL है)।

Microsoft.VisualBasic.FileIO.TextFieldParserCSV फ़ाइल पार्स करने के लिए कक्षा का उपयोग करें यहाँ नमूना कोड है:

 Dim parser As TextFieldParser = New TextFieldParser("C:\mar0112.csv")
 parser.TextFieldType = FieldType.Delimited
 parser.SetDelimiters(",")      

   While Not parser.EndOfData         
      'Processing row             
      Dim fields() As String = parser.ReadFields         
      For Each field As String In fields             
         'TODO: Process field                   

      Next      
      parser.Close()
   End While 

हाँ, यह कुछ हद तक दुर्भाग्यपूर्ण नामस्थान में एक बहुत ही उपयोगी वर्ग है ;-)। हालांकि, मूल प्रश्न को संबोधित करने के लिए, आपको सेटिंग भी करनी चाहिए parser.HasFieldsEnclosedInQuotes = true;और इनपुट फ़ाइल को उन फ़ील्ड्स को घेरना होगा जिनमें CSV युक्ति के अनुसार उद्धरण में अल्पविराम होते हैं - एक्सेल पहले से ही ऐसा करता है।
क्रिस्टोफर किंग

4

आप वैकल्पिक "सीमांकक" का उपयोग कर सकते हैं ";" या "|" लेकिन सबसे सरल सिर्फ वह उद्धरण हो सकता है जो सबसे (सभ्य) CSV पुस्तकालयों और सबसे सभ्य स्प्रेडशीट द्वारा समर्थित है।

CSV के बारे में अधिक जानने के लिए और एक मानक प्रारूप के लिए एक युक्ति का वर्णन करने के लिए और इस वेबपेज को देखने के लिए उद्धृत करें


4

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

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

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

यहाँ छवि विवरण दर्ज करें

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

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

  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उद्धरण चिह्नों के साथ संलग्न करने के बजाय अवांछित कॉमा (ओं) को हटाना चाहते हैं, तो इस उत्तर को देखें ।


3

यदि आप पहिया को फिर से संगठित करने की तरह महसूस करते हैं, तो निम्न आपके लिए काम कर सकते हैं:

public static IEnumerable<string> SplitCSV(string line)
{
    var s = new StringBuilder();
    bool escaped = false, inQuotes = false;
    foreach (char c in line)
    {
        if (c == ',' && !inQuotes)
        {
            yield return s.ToString();
            s.Clear();
        }
        else if (c == '\\' && !escaped)
        {
            escaped = true;
        }
        else if (c == '"' && !escaped)
        {
            inQuotes = !inQuotes;
        }
        else
        {
            escaped = false;
            s.Append(c);
        }
    }
    yield return s.ToString();
}

3

यूरोप में इस समस्या से पहले हमें यह समस्या है। यूरोप में हम दशमलव बिंदु के लिए सभी अल्पविराम का उपयोग करते हैं। इस संख्या को नीचे देखें:

| American      | Europe        |
| ------------- | ------------- |
| 0.5           | 0,5           |
| 3.14159265359 | 3,14159265359 |
| 17.54         | 17,54         |
| 175,186.15    | 175.186,15    |

इसलिए CSV फ़ाइलों के लिए अल्पविराम विभाजक का उपयोग करना संभव नहीं है। उस कारण से, यूरोप में CSV फ़ाइलों को एक अर्धविराम ( ;) द्वारा अलग किया जाता है ।

माइक्रोसॉफ्ट एक्सेल जैसे कार्यक्रम अर्धविराम के साथ फाइल पढ़ सकते हैं और विभाजक से स्विच करना संभव है। आप \tविभाजक के रूप में एक टैब ( ) का भी उपयोग कर सकते हैं । सपर यूजर का यह उत्तर देखें ।


2

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

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


1

यहाँ एक छोटा सा समाधान है:

आप इसके बजाय एक ग्रीक लोअर न्यूमेरल साइन (U + 0375) का उपयोग कर सकते हैं

ऐसा लगता है ͵

इस विधि का उपयोग करने से आपके पास बहुत सारे संसाधन बच जाते हैं ...


1

बस NuGet पर SoftCircuits.CsvParser का उपयोग करें । यह आपके लिए उन सभी विवरणों को संभाल लेगा और कुशलतापूर्वक बहुत बड़ी फ़ाइलों को संभालता है। और, यदि आवश्यक हो, तो यह ऑब्जेक्ट्स की संपत्तियों को मैप करके वस्तुओं को आयात / निर्यात भी कर सकता है। इसके अलावा, मेरे परीक्षण ने इसे लोकप्रिय CsvHelper की तुलना में लगभग 4 गुना तेज दिखाया।


0

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

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

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

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

2 को सही ठहराने के लिए) लगभग सभी भाषा के लिए चारों ओर सीएसवी पार्सर्स है, इसलिए घोल को बहुत सरल बनाने की आवश्यकता नहीं है, भले ही समाधान बहुत आसान लग रहा हो।

कुछ नाम रखने के लिए:

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

  • पर्ल चेक सीपीएन और पाठ :: सीएसवी के लिए

  • fgetcsv / fputcsv फ़ंक्शन में php उपयोग बिल्ड के लिए

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

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


12
XML हमेशा जवाब नहीं है। CSV नौकरी के लिए सही प्रारूप है जब आपके पास बहुत अधिक घना, सारणीबद्ध डेटा (यानी एक स्प्रेडशीट) होता है। वे टैग बहुत अधिक ओवरहेड का परिचय देते हैं, और यदि प्रत्येक और हर पंक्ति का एक समान प्रारूप है, तो प्रत्येक और हर मूल्य का प्रतिनिधित्व करने वाले के बारे में स्पष्ट होने की आवश्यकता नहीं है। जब आप जटिल पदानुक्रमित डेटा, या वैकल्पिक फ़ील्ड्स के साथ रिकॉर्ड करते हैं, तो XML बढ़िया है। यह हमेशा मामला नहीं है।
एडम जास्किविकेज़

सिद्धांत रूप में "टैग" ओवरहेड का एक सा परिचय देते हैं, लेकिन मैं किसी भी वास्तविक जीवन के अनुप्रयोग के बारे में नहीं सोच सकता हूं जहां यह एक समस्या है। क्या आपके पास कोई व्यावहारिक उदाहरण है? डेटा पर काम करने के लिए सीएसवी के बजाय एक डेटाबेस का उपयोग करना चाहिए। यदि हम डेटा क्रमांकन (बैकअप, डेटा इंटरचेंज) के बारे में बात करते हैं, तो क्या 5 दिनों के बजाय एक सप्ताह का समय लगेगा?
पायोत्र कोजापला

2
मूल रूप से, किसी भी स्थिति जिसमें आपके पास डेटा है जो एक तालिका द्वारा सबसे अच्छा प्रतिनिधित्व किया जाता है। मान लें कि आपके पास एक दर्जन अलग-अलग सेंसर से डेटा है जो आप हर बार नमूना लेते हैं, और आप उस समय टाइमस्टैम्प और प्रत्येक सेंसर का मूल्य रिकॉर्ड करते हैं। प्रत्येक रिकॉर्ड समान है: टाइमस्टैम्प, सेंसर 0, सेंसर 1, ... सेंसर 11। XML जटिल, अनियमित डेटा का प्रतिनिधित्व करने के लिए बहुत अच्छा है, लेकिन यह एक अधिक भारी प्रारूप है जो हर एक स्थिति में फिट नहीं होता है। KISS
एडम Jaskiewicz

10
कुछ लोग एक समस्या देखते हैं, और वे कहते हैं "मुझे पता है, मैं XML का उपयोग करूंगा!" अब उन्हें दो समस्याएं हैं।
एडम जास्कविज़

मैं पूरी तरह से सहमत हूं कि xml सब कुछ के लिए एक जवाब नहीं है। विशेष रूप से यह न तो डेटाबेस प्रतिस्थापन के रूप में और न ही कॉन्फ़िगरेशन फ़ाइलों के लिए अनुकूल है। लेकिन यहां सवाल डेटा इंटरचेंज के बारे में था जिसके लिए XML डिजाइन किया गया था।
पायोत्र कोजापला

0

आप csv फाइल को इस तरह से पढ़ सकते हैं।

यह विभाजन का उपयोग करता है और रिक्त स्थान की देखभाल करता है।

ArrayList List = new ArrayList();
static ServerSocket Server;
static Socket socket;
static ArrayList<Object> list = new ArrayList<Object>();


public static void ReadFromXcel() throws FileNotFoundException
{   
    File f = new File("Book.csv");
    Scanner in = new Scanner(f);
    int count  =0;
    String[] date;
    String[] name;
    String[] Temp = new String[10];
    String[] Temp2 = new String[10];
    String[] numbers;
    ArrayList<String[]> List = new ArrayList<String[]>();
    HashMap m = new HashMap();

         in.nextLine();
         date = in.nextLine().split(",");
         name = in.nextLine().split(",");
         numbers = in.nextLine().split(",");
         while(in.hasNext())
         {
             String[] one = in.nextLine().split(",");
             List.add(one);
         }
         int xount = 0;
         //Making sure the lines don't start with a blank
         for(int y = 0; y<= date.length-1; y++)
         {
             if(!date[y].equals(""))
             {   
                 Temp[xount] = date[y];
                 Temp2[xount] = name[y];
                 xount++;
             }
         }

         date = Temp;
         name =Temp2;
         int counter = 0;
         while(counter < List.size())
         {
             String[] list = List.get(counter);
             String sNo = list[0];
             String Surname = list[1];
             String Name = list[2];
             for(int x = 3; x < list.length; x++)
             {           
                 m.put(numbers[x], list[x]);
             }
            Object newOne = new newOne(sNo, Name, Surname, m, false);
             StudentList.add(s);
             System.out.println(s.sNo);
             counter++;
         }

0

सबसे पहले, अपने आप से पूछें, "हमें CSV फ़ाइलों के लिए अलग से कॉमा को संभालने की आवश्यकता क्यों महसूस होती है?"

मेरे लिए, इसका उत्तर है, "क्योंकि जब मैं CSV फ़ाइल में डेटा निर्यात करता हूं, तो फ़ील्ड में कॉमा गायब हो जाते हैं और मेरा फ़ील्ड कई फ़ील्ड्स में अलग हो जाता है जहां कॉमा मूल डेटा में दिखाई देते हैं।" (ऐसा इसलिए है क्योंकि अल्पविराम CSV क्षेत्र विभाजक चरित्र है।)

आपकी स्थिति के आधार पर, सेमी कॉलन को सीएसवी क्षेत्र विभाजक के रूप में भी इस्तेमाल किया जा सकता है।

मेरी आवश्यकताओं को देखते हुए, मैं एक चरित्र का उपयोग कर सकता हूं, उदाहरण के लिए, एकल कम-९ उद्धरण चिह्न, जो अल्पविराम जैसा दिखता है।

तो, यहाँ आप इसे गो में कैसे कर सकते हैं:

// Replace special CSV characters with single low-9 quotation mark
func Scrub(a interface{}) string {
    s := fmt.Sprint(a)
    s = strings.Replace(s, ",", "‚", -1)
    s = strings.Replace(s, ";", "‚", -1)
    return s
}

बदलें समारोह में दूसरा अल्पविराम दिखने वाला वर्ण दशमलव 8218 है।

ध्यान रखें कि यदि आपके पास ऐसे ग्राहक हैं, जिनके पास असीसी-केवल पाठ पाठक हो सकते हैं, तो यह दशमलव 8218 वर्ण अल्पविराम जैसा नहीं लगेगा। यदि यह आपका मामला है, तो मैं आरएफसी 4128 प्रति डबल कोट्स के साथ अल्पविराम (या अर्धविराम) के साथ मैदान के आसपास की सिफारिश करूंगा: https://tools.ietf.org/html/rfc4180


0

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

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

हर भाषा में यूआरएल-एनकोड और स्ट्रिंग्स को डिकोड करने के तरीके होने चाहिए।

जैसे, जावा में

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

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


0

मैं आमतौर पर मेरी CSV फ़ाइलों को पार्सिंग रूटीन में करता हूं। मान लें कि 'लाइन' वेरिएबल CSV फ़ाइल के भीतर एक लाइन है और कॉलम के सभी मान डबल कोट्स में संलग्न हैं। नीचे दी गई दो पंक्तियों के निष्पादन के बाद, आपको 'मान' संग्रह में CSV कॉलम मिलेंगे।

// The below two lines will split the columns as well as trim the DBOULE QUOTES around values but NOT within them
    string trimmedLine = line.Trim(new char[] { '\"' });
    List<string> values = trimmedLine.Split(new string[] { "\",\"" }, StringSplitOptions.None).ToList();

1
मेरा कोड StackOverflow पर कई रंगों में क्यों प्रदर्शित नहीं होता है? मैं चार जगहों से इंडेंट करता हूं।
user1451111


0

सबसे सरल समाधान जो मैंने पाया है वह एक लिबर ऑफिस उपयोग है:

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

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

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

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

"hello",world"

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


1
मानक नियमों के अनुसार, किसी भी क्षेत्र में विभाजित चरित्र या उद्धरण से घिरा हुआ है, और उसके अंदर कोई भी उद्धरण दोगुना है, इसलिए कोई समस्या नहीं है। आपके hello",worldक्षेत्र को बस के रूप में सहेजने की आवश्यकता होगी "hello"",world", जिसे 100% सही ढंग से पार्स किया जा सकता है।
Nyerguds

0
    public static IEnumerable<string> LineSplitter(this string line, char 
         separator, char skip = '"')
    {
        var fieldStart = 0;
        for (var i = 0; i < line.Length; i++)
        {
            if (line[i] == separator)
            {
                yield return line.Substring(fieldStart, i - fieldStart);
                fieldStart = i + 1;
            }
            else if (i == line.Length - 1)
            {
                yield return line.Substring(fieldStart, i - fieldStart + 1);
                fieldStart = i + 1;
            }

            if (line[i] == '"')
                for (i++; i < line.Length && line[i] != skip; i++) { }
        }

        if (line[line.Length - 1] == separator)
        {
            yield return string.Empty;
        }
    }

0

मैंने Csvreader लाइब्रेरी का उपयोग किया, लेकिन कॉलम मूल्य में अल्पविराम (?) से विस्फोट करके मुझे डेटा मिला।

इसलिए यदि आप अधिकांश कॉलम मानों में CSV फ़ाइल डेटा सम्मिलित करना चाहते हैं जिसमें अल्पविराम (,) है, तो आप नीचे दिए गए फ़ंक्शन का उपयोग कर सकते हैं। लेखक लिंक => https://gist.github.com/jaywilliams/385876

function csv_to_array($filename='', $delimiter=',')
{
    if(!file_exists($filename) || !is_readable($filename))
        return FALSE;

    $header = NULL;
    $data = array();
    if (($handle = fopen($filename, 'r')) !== FALSE)
    {
        while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE)
        {
            if(!$header)
                $header = $row;
            else
                $data[] = array_combine($header, $row);
        }
        fclose($handle);
    }
    return $data;
}

0

मैंने CSV फ़ाइल को पार्स करने के लिए papaParse लाइब्रेरी का उपयोग किया और कुंजी-मूल्य जोड़े (CSV फ़ाइल-मान की कुंजी / शीर्ष लेख / पहली पंक्ति) का उपयोग किया।

यहाँ उदाहरण है कि मैं उपयोग करता हूँ:

https://codesandbox.io/embed/llqmrp96pm

इसमें CSV पार्सिंग डेमो करने के लिए dummy.csv फ़ाइल है।

मैंने इसे reactJS के भीतर उपयोग किया है, हालांकि यह किसी भी भाषा के साथ लिखे गए ऐप में दोहराने के लिए आसान और सरल है।


0

एक उदाहरण दिखाने के लिए मदद कर सकता है कि कैसे कॉम को .csv फ़ाइल में प्रदर्शित किया जा सकता है। निम्नानुसार एक साधारण पाठ फ़ाइल बनाएँ:

इस टेक्स्ट फ़ाइल को ".csv" प्रत्यय वाली टेक्स्ट फ़ाइल के रूप में सहेजें और इसे विंडोज 10 से एक्सेल 2000 के साथ खोलें।

स्प्रेडशीट प्रस्तुति में आ, bb, cc, d; d "नीचे की पंक्ति को ऊपर की रेखा की तरह दिखना चाहिए, सिवाय इसके कि नीचे डी के बीच एक अर्धविराम के बजाय एक प्रदर्शित अल्पविराम दिखाया गया है।" आ, बी बी सी, "डी, डी", यह एक्सेल में भी काम करता है

आ, bb, cc, "d, d", यह एक्सेल 2000 में भी काम करता है। आब, बब, cc, "d, d", यह एक्सेल 2000 में भी काम करता है। आब, बब, cc, "d, d", यह काम करता है। यहां तक ​​कि एक्सेल 2000 में भी

आ, bb, cc, "d, d", यह एक्सेल 2000 में विफल रहता है, क्योंकि स्पेस बेलोर 1 1st उद्धरण आ गया है, bb, cc, "d, d", यह एक्सेल 2000 में फेल होने के कारण स्पेस को 1st उद्धरण देता है। आ, bb, cc, "d, d", यह एक्सेल 2000 में फेल होने की वजह से स्पेसल 1st बोली है

आ, bb, cc, "d, d", यह Excel 2000 में भी 2 के उद्धरण से पहले और बाद के रिक्त स्थान के साथ भी काम करता है। आ, bb, cc, "d, d", यह Excel 2000 में भी 2 के उद्धरण से पहले और बाद के रिक्त स्थान के साथ भी काम करता है। आ, bb, cc, "d, d", यह Excel 2000 में भी 2 के उद्धरण से पहले और बाद के रिक्त स्थान के साथ भी काम करता है।

नियम: यदि आप .csv फ़ाइल के एक सेल (फ़ील्ड) में अल्पविराम दिखाना चाहते हैं: "फ़ील्ड को दोहरे उद्धरणों के साथ प्रारंभ और समाप्त करें, लेकिन 1 उद्धरण से पहले सफेद स्थान से बचें"


-1

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


कौन कहता है कि उनके पास एक्सेल है? वास्तव में कौन कहता है कि यह भी एक इंसान है जो अपलोडिंग कर रहा है? ...
बट्टेव

-3

खेतों को अलग करने के लिए एक टैब वर्ण (\ t) का उपयोग करें।


4
-1 महान जब तक कोई अपने मूल्य में एक टैब का उपयोग करता है तब तक समस्या पूछने वाले व्यक्ति को आपका अधिकार वापस मिल जाता है। समस्या को हल करने के लिए जा रहा एक और isnt के लिए एक सीमांकक चार्ट स्वैप करना।
बट्टेव

बकवास। लोग अपने डेटा इनपुट में टैब दर्ज नहीं कर सकते हैं। अधिकांश रूपों में, जो डेटा प्रविष्टि बिंदु को अगले फ़ील्ड पर ले जाता है।
पियरे

6
"लोग अपने डेटा इनपुट में टैब दर्ज नहीं कर सकते" .... क्या आप गंभीर हैं ?? ए) बेशक एक व्यक्ति एक इनपुट क्षेत्र बी में एक टैब डाल सकता है) जो कहता है कि यह एक जीयूआई है जो डेटा से आता है? ग) कौन कहता है कि इसका मानव भी डेटा में प्रवेश कर रहा है?
bytedev
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.