31 votes

TStringList divisant les bogues

Récemment, j'ai été informé par un de bonne réputation AFIN que l'utilisateur, qui TStringList a fractionnement des bugs qui serait la cause de l'échec d'analyse des données au format CSV. Je n'ai pas été informé de la nature de ces bugs, et une recherche sur internet, y compris la Qualité de Centrale n'a pas produit tous les résultats, donc je vous demande. Quelles sont TStringList fractionnement des bugs?

Veuillez noter, je ne suis pas intéressé à infondées avis en fonction des réponses.


Ce que je sais:

Pas grand-chose... On est qui, ces bugs se manifestent rarement avec des données de test, mais pas si rarement dans le monde réel.

L'autre est, comme indiqué, ils empêchent une analyse correcte de CSV. Pensant qu'il est difficile de reproduire les bugs avec les données de test, je suis (probablement) la recherche de l'aide de qui ont essayé d'utiliser une chaîne de la liste au format CSV analyseur dans le code de production.

Pertinence des problèmes:

J'ai obtenu de l'information sur un "Delphi XE' tagged question, donc, à défaut de l'analyse en raison du "caractère d'espace étant considéré comme un"séparateur de fonctionnalité ne s'applique pas. Parce que l'introduction de l' StrictDelimiter de la propriété avec Delphi 2006, a décidé que. Je suis moi-même à l'aide de Delphi 2007.

En outre, depuis la liste des chaînes ne peuvent détenir que des chaînes, il est seulement chargé de la séparation des champs. Toute conversion les difficultés rencontrées par les valeurs de champ (f.j'. date, les nombres à virgule flottante..) découlant de paramètres régionaux différences etc. ne sont pas dans le champ d'application.

Règles de base:

Il n'y a pas de spécification standard pour CSV. Mais il y a des règles de base déduit à partir de diverses spécifications.

Ci-dessous est une démonstration de la façon dont TStringList gère ces. La règle et l'exemple des chaînes sont de Wikipédia. Crochets ([ ]) sont superposées autour de chaînes de caractères pour être en mesure de voir ou les espaces de fin (le cas échéant) par le code de test.


Les espaces sont considérés comme faisant partie d'un domaine et ne doit pas être ignoré.

Chaîne de Test: [1997, Ford E350]
Articles: [1997] [ Ford ] [ E350]


Les champs avec des virgules incorporées doit être entourée de guillemets doubles.

Chaîne de Test: [1997,Ford E350,"Super, luxe camion"]
Articles: [1997] [Ford] [E350] [Super, luxe camion]


Domaines intégré dans le double-guillemets doit être entourée de guillemets doubles, et chacun de l'embarqué, les guillemets doubles doit être représenté par une paire de guillemets doubles.

Chaîne de Test: [1997,Ford E350,"Super", "luxe"" camion"]
Articles: [1997] [Ford] [E350] [Super, "de luxe" camion]


Les champs insérés les sauts de ligne doit être entourée de guillemets doubles.

Chaîne de Test: [1997,Ford E350,"Aller en obtenir un maintenant
ils vont vite"]
Articles: [1997] [Ford] [E350] [Aller à en obtenir un maintenant
ils vont vite]


En CSV implémentations de garniture de pointe ou les espaces, les champs avec ces espaces doivent être placés à l'intérieur de guillemets doubles.

Chaîne de Test: [1997,Ford E350," Super luxe camion "]
Articles: [1997] [Ford] [E350] [ Super luxueux camion ]


Les champs peuvent toujours être entourée de guillemets doubles, si nécessaire ou pas.

Chaîne de Test: ["1997","Ford","E350"]
Articles: [1997] [Ford] [E350]



Test de code:

var
  SL: TStringList;
  rule: string;

  function GetItemsText: string;
  var
    i: Integer;
  begin
    for i := 0 to SL.Count - 1 do
      Result := Result + '[' + SL[i] + '] ';
  end;

  procedure Test(TestStr: string);
  begin
    SL.DelimitedText := TestStr;
    Writeln(rule + sLineBreak, 'Test string: [', TestStr + ']' + sLineBreak,
            'Items: ' + GetItemsText + sLineBreak);
  end;

begin
  SL := TStringList.Create;
  SL.Delimiter := ',';        // default, but ";" is used with some locales
  SL.QuoteChar := '"';        // default
  SL.StrictDelimiter := True; // required: strings are separated *only* by Delimiter

  rule := 'Spaces are considered part of a field and should not be ignored.';
  Test('1997, Ford , E350');

  rule := 'Fields with embedded commas must be enclosed within double-quote characters.';
  Test('1997,Ford,E350,"Super, luxurious truck"');

  rule := 'Fields with embedded double-quote characters must be enclosed within double-quote characters, and each of the embedded double-quote characters must be represented by a pair of double-quote characters.';
  Test('1997,Ford,E350,"Super, ""luxurious"" truck"');

  rule := 'Fields with embedded line breaks must be enclosed within double-quote characters.';
  Test('1997,Ford,E350,"Go get one now'#10#13'they are going fast"');

  rule := 'In CSV implementations that trim leading or trailing spaces, fields with such spaces must be enclosed within double-quote characters.';
  Test('1997,Ford,E350," Super luxurious truck "');

  rule := 'Fields may always be enclosed within double-quote characters, whether necessary or not.';
  Test('"1997","Ford","E350"');

  SL.Free;
end;



Si vous avez tout lu, la question était :), quelles sont les "TStringList fractionnement des bugs?"

13voto

Cosmin Prund Points 21063

Pas grand-chose... On est qui, ces bugs se manifestent rarement avec des données de test, mais pas si rarement dans le monde réel.

Il suffit d'un cas. Des données de Test n'est pas aléatoire de données, un utilisateur avec un cas d'échec devrait soumettre les données et voilà, nous avons un cas de test. Si personne ne peut fournir des données de test, peut-être il n'y a pas de bug ou d'échec?

Il n'y a pas de spécification standard pour CSV.

Que l'on aide bien sûr à la confusion. Sans spécification de la norme, comment voulez-vous prouver que quelque chose est mal? Si cela est laissé à sa propre intuition, vous pouvez lancer dans toutes sortes d'ennuis. Voici certains de mes propres heureux interaction avec émise par le gouvernement du logiciel; Ma demande a été censé pour exporter des données au format CSV, et le gouvernement demande a été censé pour l'importer. Voici ce que nous a mis dans un beaucoup de difficulté à plusieurs années dans une rangée:

  • Comment représenter des données vides? Car il n'y a pas de CSV standard, d'un an mon amitié gov décidé à tout va, y compris à rien (deux fois de suite des virgules). Ensuite, ils ont décidé seulement consécutive, les virgules sont OK, c'est, Field,"",Field n'est pas valide, doit être Field,,Field. Eu beaucoup de plaisir à expliquer à mes clients que le gouv app changé les règles de validation à partir d'une semaine à l'autre...
  • Avez-vous d'exportation ZÉRO de données entier? C'est probablement un plus grand abus, mais mon "gov app" a décidé de valider aussi. En même temps, il était nécessaire que l' 0, alors il est obligatoire de ne PAS inclure l' 0. C'est, à un moment Field,0,Field est valide, suivant Field,,Field a été la seule méthode valide...

Et voici un autre test cas où (mon) l'intuition a échoué:

1997, Ford E350, "Super, luxe camion"

Veuillez noter que l'espace entre , et "Super, et le bien de la chance virgule qui suit "Super. L'analyseur employé par TStrings ne voit que la citation de char si il immédiatement suit le délimiteur. Cette chaîne est analysée comme:

[1997]
[ Ford]
[ E350]
[ "Super]
[ luxurious truck"]

Intuitivement, je m'attends à:

[1997]
[ Ford]
[ E350]
[Super luxurious truck]

Mais devinez quoi, Excel est-il de la même façon Delphi t-il...

Conclusion

  • TStrings.CommaText est d'assez bonne qualité et bien mis en œuvre, au moins en Delphi version 2010, j'ai regardé est assez efficace (évite plusieurs allocations de chaîne, utilise un PChar "marche" de la chaîne à analyser) et travaille sur la même chose que d'Excel analyseur ne.
  • Dans le monde réel, vous aurez besoin d'échanger des données avec d'autres logiciels, écrite à l'aide d'autres bibliothèques (ou pas bibliothèques), où les gens ont peut-être manquez-interprétation de certaines (disparu?) les règles de CSV. Vous devrez vous adapter, et ce n'est probablement pas une affaire de droite ou de mal, mais d'un cas de "mes clients ont besoin d'importer cette merde". Si cela se produit, vous devrez écrire votre propre analyseur, celui qui s'adapte aux exigences de la 3ème partie de l'app, vous seriez confronté à. En attendant, vous pouvez utiliser en toute sécurité TStrings. Et quand ça arrive, il pourrait ne pas être TStrings'faute!

4voto

afrazier Points 2290

Je vais aller sur une branche et dire que la panne la plus fréquente est le cas de la embarqués saut de ligne. Je sais que la plupart des CSV analyse je n'ignore que. Je vais utiliser 2 TStringLists, 1 pour le fichier, je suis d'analyse, l'autre pour la ligne en cours. Donc je vais finir avec un code semblable au suivant:

procedure Foo;
var
    CSVFile, ALine: TStringList;
    s: string;

begin
    CSVFile := TStringList.Create;
    ALine := TStringList.Create;
    ALine.StrictDelimiter := True;
    CSVFile.LoadFromFile('C:\Path\To\File.csv');
    for s in CSVFile do begin
        ALine.CommaText := s;
        DoSomethingInteresting(ALine);
    end;
end;

Bien sûr, puisque je ne suis pas en prenant soin de faire en sorte que chaque ligne est "complète", je peux potentiellement exécuter dans les cas où l'entrée contient une cité saut de ligne dans un champ, et je m'ennuie.

Jusqu'à ce que je tombe sur les données du monde réel où c'est une question, je ne vais pas la peine de le réparer. :-P

0voto

Un autre exemple ... ce bogue TStringList.CommaText existe dans Delphi 2009.

 procedure TForm1.Button1Click(Sender: TObject);
var
  list : TStringList;
begin
  list := TStringList.Create();
  try
    list.CommaText := '"a""';
    Assert(list.Count = 1);
    Assert(list[0] = 'a');
    Assert(list.CommaText = 'a'); // FAILS -- actual value is "a""
  finally
    FreeAndNil(list);
  end;
end;
 

Le setter TStringList.CommaText et les méthodes associées corrompent la mémoire de la chaîne qui contient l'élément a (son caractère de terminaison nul est remplacé par un " ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X