2012-07-06 16 views
7

ho dati che assomiglia a questo ...dividere una stringa in stringhe sub da larghezza fissa

1 TESTAAA  SERNUM A DESCRIPTION 
    2 TESTBBB  ANOTHR ANOTHER DESCRIPTION 
    3 TESTXXX  BLAHBL 

La mia domanda è, qual è il modo più efficace per suddividere questi dati in è sottostringhe più piccoli, come ci saranno centinaia di linee. Inoltre, alcune linee mancheranno l'ultima colonna. Ho provato a fare regex ma non ha avuto successo con il pattern che ho usato per le larghezze. I dati sopra riportati dovrebbero abbattere in questi campi (lunghezza di ogni colonna elencati di seguito)

{id} {firsttext} {serialhere} {description} 
4 22   6   30+ 

Chiunque può dare una mano o di suggerire un buon modello di espressione regolare corrispondenza per estrarre le informazioni?

Grazie, Simon

risposta

7

provare la seguente espressione regolare:

(.{4})(.{22})(.{6})(.+)? 

Se i valori sono sempre non vuota e separati con spazi (vale a dire, don' Entrare l'uno nell'altro), quindi provare qualcosa di più semplice come

line.Split(" ") 
6

vorrei davvero consigliare a scrivere un metodo per fare questo via String.Substring direttamente. Questo sarà probabilmente più efficiente nel darti le esatte larghezze richieste.

Ciò probabilmente funzionerà (anche se è non testato, e volutamente non elimina l'imbottitura stringa):

public static string[] SplitFixedWidth(string original, bool spaceBetweenItems, params int[] widths) 
{ 
    string[] results = new string[widths.Length]; 
    int current = 0; 

    for (int i = 0; i < widths.Length; ++i) 
    { 
     if (current < original.Length) 
     { 
      int len = Math.Min(original.Length - current, widths[i]); 
      results[i] = original.Substring(current, len); 
      current += widths[i] + (spaceBetweenItems ? 1 : 0); 
     } 
     else results[i] = string.Empty; 
    } 

    return results; 
} 

Detto questo, se stai leggendo questo da un file di Stream o di testo direttamente, utilizzando TextFieldParser ti consentirà di leggere i dati direttamente come dati a larghezza fissa.

+0

TextFieldParse può leggere da qualsiasi Stream o TextReader, s o non deve andare in un file fisico. –

+0

@SteveDog Sì - i dati devono essere in un flusso. Questo è raramente un problema, però, ma non lo inserirò necessariamente se già (per qualche motivo) avessi un array di stringhe che stavi elaborando, o qualcosa del genere. Detto questo, ho modificato per includere quell'informazione –

+0

No, sto dicendo che prenderà anche un TextReader, quindi puoi semplicemente istanziarlo come 'new TextFieldParser (new StringReader (" the data "))'. Nessun flusso necessario. –

5

controlla questo link sul MSDN:

http://msdn.microsoft.com/en-us/library/zezabash.aspx

In sostanza, la classe TextFieldParser fa esattamente questo genere di cose. È anche un ottimo modo per leggere i dati delimitati, come i file CSV. Per qualsiasi motivo, Microsoft ha scelto di metterlo sotto lo spazio dei nomi Microsoft.VisualBasic.FileIO, il che è fastidioso perché non ha nulla a che fare con VB.

Ad esempio, è possibile utilizzare in questo modo:

TextFieldParser parser = new TextFieldParser(new StringReader(fixedWidthData)); 
parser.TextFieldType = FieldType.FixedWidth; 
parser.SetFieldWidths(4, 22, 6, -1); 
while (!parser.EndOfData) 
{ 
    string[] row = parser.ReadFields(); 
} 
Problemi correlati