2010-07-30 6 views
0

J'ai un fichier texte qui contient une donnée commeLire la chaîne entre guillemets de fichier texte

ID  Name   Path         IsTrue  Period 
1   "1 yr"  "C:\\Program Files\\My File.xyz"  -1   2" 
1   "1 yr"  "C:\\Program Files\\My File.xyz"  -1   2" 

maintenant j'ai le code suivant pour diviser la ligne

string[] ArrSeperators = { " " }; 
ArrSplitStrs = CurrStr.Split(ArrSeperators, 
          StringSplitOptions.RemoveEmptyEntries); 

CurrStr représente chaque ligne du fichier texte.

Le problème est qu'il divise le nom et le chemin en plusieurs chaînes, mais elles doivent être traitées comme une seule chaîne. Je ne peux pas apporter de modifications au fichier car il s'agit d'un fichier standard sur différents produits.

Je ne comprends pas ce que je peux faire.

Répondre

1

utiliser un algorithme comme celui-ci:

Procédé chaque caractère de chaque ligne un à la fois.

comte tous « que vous trouvez.

Si le nombre de « s est impair, vous savez que vous devez continuer à lire le champ actuel jusqu'à ce que vous frappez une autre ».

Si le nombre de » s est pair, vous savez que dès que vous touchez un espace, vous êtes sur le champ suivant.

Quelque chose comme (cela peut avoir des erreurs - je viens de l'écrire sur le dessus de ma tête):

StringBuilder field = new StringBuilder(); 
int quoteCount = 0; 

foreach (char c in line) 
{ 
    if (c == '"') 
    { 
     quotCount++; 
     continue; 
    } 

    if (quoteCount % 2 = 0) 
    { 
     if (c == ' ') 
     { 
      yield return field.ToString(); 
      field.Length = 0; 
     } 
     else 
     { 
      field.Append(c); 
     } 
    } 
    else 
    { 
     field.Append(c); 
    } 
} 

EDIT:

Voici un exemple hacky qui fonctionne pour votre échantillon - La méthode GetFields a besoin d'un refactoring et c'est loin de la qualité de tout ce que je mettrais dans mon code, mais le principe de base est là.

class Program 
{ 
    static void Main(string[] args) 
    { 
     var records = ReadFile(@"D:\x.txt"); 

     foreach (var record in records) 
     { 
      foreach (var field in record) 
      { 
       Console.Write(field + " | "); 
      } 

      Console.WriteLine(); 
     } 

     Console.ReadKey(); 
    } 

    static IEnumerable<IEnumerable<String>> ReadFile(String file) 
    { 
     using (var reader = new StreamReader(file)) 
     { 
      // Ignore column titles line. 
      reader.ReadLine(); 

      while (!reader.EndOfStream) 
      { 
       yield return GetFields(reader.ReadLine()); 
      } 
     } 
    } 

    static IEnumerable<String> GetFields(String line) 
    { 
     Int32 quoteCount = 0; 
     StringBuilder field = new StringBuilder(); 

     foreach (var c in line) 
     { 
      if (c == '"') 
      { 
       quoteCount++; 
       continue; 
      } 

      if (quoteCount % 2 == 0) 
      { 
       if (c == ' ') 
       { 
        if (field.Length > 0) 
        { 
         yield return field.ToString(); 
         field.Length = 0; 
        } 
       } 
       else 
       { 
        field.Append(c); 
       } 
      } 
      else 
      { 
       field.Append(c); 
      } 
     } 

     yield return field.ToString(); 
    } 
} 
+0

Merci, cela fonctionne très bien, j'ai fait GetFields comme une méthode d'extension de sorte que Je peux l'utiliser n'importe où ... Merci encore ... Mais, y aura-t-il des problèmes de performance comme cela fonctionne sur chaque caractère – Mohit

+0

@Mohit: Mesurez les performances pour un fichier de taille de scénario pire et voyez.) ou ToArray() sur le résultat de ReadFile - sinon vous allez juste tester le performance de créer un objet qui va produire vos résultats à un moment donné dans le futur, plutôt que de tester la lecture réelle des résultats! –

+0

J'ai un test avec un fichier vraiment long. Sa performance est acceptable. Merci pour la suggestion (ToArray), je l'ai déjà fait. Merci encore – Mohit

0

Si un séparateur de tabulation est utilisé pour séparer les champs, vous pouvez utiliser '\ t'.

+0

non, ils sont séparés par des espaces et nombre d'espaces entre deux données varie d'une section à – Mohit

+0

Pour capturer les champs à l'intérieur des guillemets simples/doubles, vous pouvez utiliser: Regex regexp = new Regex ("([\" \ ']) (?: \\\\\\ 1 |.) *? \\ 1 "); –

0

Essayez le code suivant. Testée avec l'échantillon fourni en question ...

string CurrStr = "1   \"1 yr\"  \"C:\\Program Files\\My File.xyz\"  -1   2\""; 
string[] ArrSplitStrs = CurrStr.Split('"'); 
int HighestCount = ArrSplitStrs.Count() % 2 == 0 ? ArrSplitStrs.Count() : ArrSplitStrs.Count() - 1; 
for (int Counter = 1; Counter < HighestCount;) 
{ 
    Console.WriteLine(ArrSplitStrs[Counter]); 
    Counter += 2; 
} 
+0

la sortie est ArrSplitStrs [0] = "1" ArrSplitStrs [0] = "1" YR ArrSplitStrs [0] = "" ArrSplitStrs [0] = « C: \\ Program Files \ \ My file.xyz » ArrSplitStrs [0] = "-1 2" ArrSplitStrs [0] = "" au lieu de ArrSplitStrs [0] = "1" ArrSplitStrs [1] = "1 an" ArrSplitStrs [2] = "C: \ Fichiers programme \ Mon fichier.xyz" ArrSplitStrs [3] = "-1" ArrSplitStrs [4] = "2" Je le veux tableau nto comme je dois le traiter davantage – Mohit

+0

Prenez le nouveau tableau et ajoutez les éléments qui sont en cours d'impression. –

Questions connexes