Delimitarea parserului de șir?

Mă uit la parsarea unui șir delimitat, ceva la ordinul lui

a, b, c

Dar acesta este un exemplu foarte simplu, iar parsarea datelor delimitate poate deveni complexă; de exemplu

1, "Algoritmul dvs. simplu, acesta nu reușește", Adevărat

ar arunca șirul naiv. Completați implementarea la biți. Există ceva ce pot utiliza în mod liber/fura/copia și lipi care oferă o soluție relativ antiglont pentru parsarea textului delimitat? .NET, plox.

Update: I decided to go with the TextFieldParser, which is part of VB.NET's pile of goodies hidden away in Microsoft.VisualBasic.DLL.

0
fr hi bn

9 răspunsuri

Pentru a face un plug nerușinat, am lucrat la o bibliotecă pentru o vreme numită fotelo (Text Formatat Loader) pe care o folosesc pentru a analiza rapid cantități mari de text pe baza delimitatorului, poziției sau regexului. Pentru un șir rapid este depășită, dar dacă lucrați cu jurnale sau cantități mari, poate că este exact ceea ce aveți nevoie. Funcționează cu un model de fișier de control similar cu SQL * Loader (un fel de inspirație din spatele acestuia).

0
adăugat

Nu sunt conștient de nici un cadru, dar o mașină simplă de stat funcționează:

  • State 1: Read every char until you hit a " or a ,
    • In case of a ": Move to State 2
    • In case of a ,: Move to State 3
    • In case of the end of file: Move to state 4
  • State 2: Read every char until you hit a "
    • In case of a ": Move to State 1
    • In case of the end of the file: Either Move to State 4 or signal an error because of an unterminated string
  • State 3: Add the current buffer to the output array, move the cursor forward behind the , and back to State 1.
  • State 4: this is the final state, does nothing except returning the output array.
0
adăugat
Asta e de fapt adevărat, întotdeauna uit de caracterul temut care scarpină majoritatea parserilor CSV. Limpezite.
adăugat autor Michael Stum, sursa
Corzile CSV pot include caractere noi de linii în cadrul citatelor de text, astfel încât să nu puteți semna o eroare în starea 2 dacă se termină linia.
adăugat autor cjk, sursa

There are some good answers here: Split a string ignoring quoted sections

Poate doriți să reformulați întrebarea dvs. cu ceva mai precis (de exemplu, Fragmentul de cod sau biblioteca pe care o pot utiliza pentru a analiza datele CSV în .NET ?).

0
adăugat

Mă gândesc că un cadru generic ar trebui să specifice între două lucruri: 1. Care sunt caracterele delimitante. 2. În ce condiții aceste caractere nu se iau în considerare (cum ar fi atunci când acestea se află între ghilimele).

Cred că ar fi mai bine să scrii logica personalizată de fiecare dată când trebuie să faci ceva de genul asta.

0
adăugat

Cea mai simplă cale este doar să împărțiți șirul într-o matrice de caractere și să căutați determinatorii de șir și caracterele divizate.

Ar trebui să fie relativ ușor de test unitate.

Puteți să-l înfășurați într-o metodă de extensie similară cu metoda de bază .Spilt.

0
adăugat
Un șir este în mod inerent o matrice de caractere, nu trebuie să faceți nici o conversie
adăugat autor cjk, sursa

Folosesc acest lucru pentru a citi dintr-un fișier

string filename = @textBox1.Text;
string[] fields;
string[] delimiter = new string[] {"|"};
using (Microsoft.VisualBasic.FileIO.TextFieldParser parser =
       new Microsoft.VisualBasic.FileIO.TextFieldParser(filename)) {
    parser.Delimiters = delimiter;
    parser.HasFieldsEnclosedInQuotes = false;

    while (!parser.EndOfData) {
        fields = parser.ReadFields();
        //Do what you need
    }
}

Sunt sigur că cineva de aici poate transforma acest lucru pentru a analiza un șir care este în memorie.

0
adăugat
Revenind la acest răspuns, încă mai cred că este cel mai bun. Am incercat pe FileHelpers si am ajuns la concluzia ca ma sperie. Nu am încredere în un cadru care se bazează pe ordinea în care câmpurile sunt definite pe un tip.
adăugat autor Will, sursa

Mai bine târziu decât niciodată (adăugați la caracterul complet al SO):

http://www.codeproject.com/KB/database/CsvReader.aspx

Această regulă este regulată.

GJ

0
adăugat

Precum

var elements = new List();
var current = new StringBuilder();
var p = 0;

while (p < internalLine.Length) {
    if (internalLine[p] == '"') {
        p++;

        while (internalLine[p] != '"') {
            current.Append(internalLine[p]);
            p++;
        }

       //Skip past last ',
        p += 2;
    }
    else {
        while ((p < internalLine.Length) && (internalLine[p] != ',')) {
            current.Append(internalLine[p]);
            p++;
        }

       //Skip past ,
        p++;
    }

    elements.Add(current.ToString());
    current.Length = 0;
}
0
adăugat
@ C1pher vă rugăm să nu faceți modificări stilistice, cum ar fi Java vs C #/Pascal bracketing.
adăugat autor StuartLC, sursa
De acord. Am încercat să resping această editare, dar ea a fost deja aprobată.
adăugat autor Andy West, sursa
La care aș vrea să adaug că nu suntem K & R, nici în dezvoltarea kernel-ului Linux. FFS, băieți.
adăugat autor Stu, sursa

A very complrehesive library can be found here: FileHelpers

0
adăugat
Am incercat pe FileHelpers de cand a intrebat aceasta intrebare si chiar nu imi plac parserii delimitati.
adăugat autor Will, sursa