Question Vérifier l'intégrité d'un fichier CSV

Plus d'informations
il y a 14 ans 2 mois #10858 par arnau
Bonjour à toute la communauté,

Je viens vous demander votre aide car je pêche un peu sur un script que j'essaye de faire, le but : vérifier l'intégrité d'un fichier CSV. C'est à dire, en clair, vérifier que chaque ligne contient bien le même nombre de champs (vide ou non) en jouant sur le délimiteur CSV.

Pour l'instant, j'ai fait ma petite usine à gaz de test qui donne :
[code:1]
$file = Get-Content \"F:\Powershell Scripts\test.txt\"
$global:line_count = 0
$global:nbfield = 0
$global:checksum = 0

foreach ($line in $file)
{
$splited_line = $line.split(';')
$global:nbfield = $splited_line.count

$global:line_count++

$global:checksum = $global:checksum + $global:nbfield

Write-host \"nbfield = $global:nbfield -- Ligne = $global:line_count\"
}
$expected = $global:nbfield*$global:line_count

Write-Host \"Last Line fields = $global:nbfield\"
Write-Host \"Last Line number = $global:line_count\"

Write-Host \"Total Expected = $expected\"
Write-Host \"Total Checksum = $global:checksum\"

if ( $global:checksum -ne $expected)
{
Write-Host \"ERROR Checksum\" -ForegroundColor \"Red\"
}
else
{
Write-Host \"Checksum OK\" -ForegroundColor \"Green\"
}
[/code:1]

Avec un fichier texte en entrée :

1;2;3
4;5;6
7;8;9
10;11;12
3;;
5;;
22;36;

Pour le fichier texte au dessus, cela marche bien, le script annonce :

nbfield = 3 -- Ligne = 1
nbfield = 3 -- Ligne = 2
nbfield = 3 -- Ligne = 3
nbfield = 3 -- Ligne = 4
nbfield = 3 -- Ligne = 5
nbfield = 3 -- Ligne = 6
nbfield = 3 -- Ligne = 7
Last Line fields = 3
Last Line number = 7
Total Expected = 21
Total Checksum = 21
Checksum OK

(Et si on supprime un \";\" n'importe où dans le fichier texte, on est en checksum error...si si ça marche je vous jure :))

Maintenant, compter le nombre de champs par ligne c'est facile. Vérifier qu'on à bien le nombre de champ voulu aussi. Mais ce que j'aimerais contrôler maintenant, c'est qu'on a bien le même nombre de champ par ligne (dans l'exemple \"3\")pour avoir un \"checkline\" en plus du \"checksum\".

Je pensais jouer sur une comparaison avec le nombre de champs de la ligne n-1 avec la ligne en cours n...le soucis c'est qu'au premier passage dans la boucle, vu que le script ne saura pas combien doit valoir n-1 il va hurler pour ce premier passage mais par contre sera content pour la suite.

J'avais une autre idée aussi, mais j'ai oublié et de toute manière ça coinçait aussi pour un petit détail.

Voilà, si vous avez des idées je suis preneur, j'espère avoir été clair sinon je me ferais une joie d'expliquer plus en détails et illustré.

Merci beaucoup, et joyeuses fêtes de fins d'années à tous :)

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 14 ans 2 mois #10861 par Laurent Dardenne
Salut,
que donne tes tests en utilisant directement le cmdlet Import-csv ?

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 14 ans 2 mois #10864 par arnau
Laurent Dardenne écrit:

Salut,
que donne tes tests en utilisant directement le cmdlet Import-csv ?


J'avais pas penser à ça...

En tout cas ça me donne ça (première execution avec le csv fidèle à mon post précédent, et pour la deuxieme execution j'ai fait sauté le deuxième \";\" de la première ligne):

[code:1]
PS F:\Powershell Scripts> Import-Csv -Path \"F:\Powershell Scripts\test.txt\" -Delimiter \";\"

1 2 3
- - -
4 5 6
7 8 9
10 11 12
3
5
22 36


PS F:\Powershell Scripts> Import-Csv -Path \"F:\Powershell Scripts\test.txt\" -Delimiter \";\"

1 23
- --
4 5
7 8
10 11
3
5
22 36
[/code:1]

Alors je sais pas si c'est \"l'effet en-tête\" mais du coup il à importé que les deux premières colonnes du coup...alors que les suivantes en comportait 3.

J'ai du mal à voir où tu veux en venir Laurent (Faut dire je suis parti de loin, j'étais même en train d'éplucher ton pdf sur les tableaux :woohoo: )

Merci de ton aide :)

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 14 ans 2 mois #10865 par Arthur
Salut,

Si j'ai bien compris, tu cherches à valider un fichier CSV en fonction du nombre de champs.

[code:1]$file = @()
$file = gc .\test.txt
$nbfields = ($file[0].split(\";\"«»)).count
$IsCSV = 1
for($i=0;$i -lt $file.count;$i++)
{
$new_nbfields = ($file[$i].split(\";\"«»)).count;
if ($new_nbfields -ne $nbfields)
{
$IsCSV = 0
break
}
$nbfields = $new_nbfields ;
}

if($IsCSV -eq 0)
{
Write-Host \"invalid CSV\"
}
else
{
Write-Host \"valid CSV\"
}[/code:1]

C'est pas super propre, on peux surement faire plus efficace mais ça à l'air de marcher.<br><br>Message édité par: bilbao, à: 28/12/11 10:15

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 14 ans 2 mois #10866 par arnau
bilbao écrit:

Salut,

Si j'ai bien compris, tu cherches à valider un fichier CSV en fonction du nombre de champs.

[code:1]$file = @()
$file = gc .\test.txt
$nbfields = ($file[0].split(\&quot;;\&quot;«»)).count
$IsCSV = 1
for($i=0;$i -lt $file.count;$i++)
{
$new_nbfields = ($file[$i].split(\&quot;;\&quot;«»)).count;
if ($new_nbfields -ne $nbfields)
{
$IsCSV = 0
break
}
$nbfields = $new_nbfields ;
}

if($IsCSV -eq 0)
{
Write-Host \&quot;invalid CSV\&quot;
}
else
{
Write-Host \&quot;valid CSV\&quot;
}[/code:1]

C'est pas super propre, on peux surement faire plus efficace mais ça à l'air de marcher.&lt;br&gt;&lt;br&gt;Message édité par: bilbao, à: 28/12/11 10:15


Salut Bilbao,

Ne t'en fais pas, je ne suis pas du tout développeur à la base : je ne cherche donc pas un code \&quot;propre\&quot; mais \&quot;fonctionnel\&quot; pour commencer. C'est plus facile d'optimiser un code qui marche plutôt que d'aller chercher l'optimisation dès le départ :)

Alors, j'ai pas testé ton code pour l'instant, mais je l'ai bien étudié. Au premier coup d’œil je comprenais pas pourquoi cela commençait par \&quot;une double\&quot; initialisation de $file. J'ai ensuite compris que tu mettais le contenu du csv dans le tableau afin de pouvoir accéder tout de suite à la première ligne et compter son nombre de champ. Du coup maintenant on a une bonne référence pour la comparaison avant de passer dans la boucle :)

C'est l'idée que je cherchais, il faut que je le bricole à ma sauce pour mon script mais je peux résoudre mon problème grâce à toi :woohoo:

En fait je fais cette opération pour contrôler le fichier avant de pusher dans une BDD, et le vrai fichier csv fait entre 7000 et 8000 lignes (donc contrôler à la main quand il y a une erreur... c'est long, surtout que l'erreur qui arrive le plus souvent c'est le caractère \&quot;entrée\&quot; glissé au milieu d'une ligne qui créé un gros décalage et fait partir le push en cacahuète )


Merci en tout cas pour votre aide,

Bon réveillon du nouvel an à tous :)

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 14 ans 2 mois #10868 par Arthur
Il semble que tu as tout compris, si tes fichiers sont lourds je te conseil de remplacer:

[code:1]for($i=0;$i -lt $file.count;$i++) [/code:1]

par:

[code:1]$array_length = $file.count
for($i=0;$i -lt $array_length ;$i++)[/code:1]

C'est plus efficace.

Pour info on est obligé de passer par une boucle \&quot;For\&quot;, le \&quot;break\&quot; sur les boucles \&quot;Foreach\&quot; arrête le script. (et non juste la boucle)

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.111 secondes
Propulsé par Kunena