Skip to content

$csv.nextRecord

Description

Retourne l'enregistrement suivant lu du CSV donné en référence.

$csv.parse vs $csv.nextRecord

Les méthodes $csv.parse et $csv.nextRecord permettent toutes les deux de parcourir un CSV et d'effectuer un traitement pour chaque enregistrement. Les deux méthodes varient quant à l'approche pour réaliser le traitement.

Le choix de l'approche appartient donc au développeur, d'autant que les performances des deux méthodes sont sensiblement identiques.

Syntaxe

$csv.nextRecord( referenceCsv )

Paramètres

referenceCsv pojo
Référence de CSV obtenue à l'aide de $csv.load

Retour

Retourne un tableau contenant les valeurs du record, ou null si le parser a atteint la fin du fichier.

Exemple

L'exemple ci-dessous est un code complet effectuant l'importation des données "entrées" du registre fédéral des bâtiments et des logements.

L'idée est de parser le CSV en itérant sur les enregistrements (c.-à-d. les lignes du CSV) et d'envoyer les données dans une table par lots. Pour ce faire, on construit une requête de la forme:

insert into (col1, col2, ...) values('valA1', 'valB1', ...),('valA2', 'valB2', ...)

Le nombre de lignes enregistrées à la fois est déterminé par la constante maxCounter. Cette variable joue un grand rôle sur les performances car elle influe sur le nombre de requêtes envoyées à la base de données. Elle est fixée à 250 dans l'exemple ci-dessous. Lors des tests, cela a permis d'importer un peu plus de 15'000 enregistrement à la seconde. Dans les mêmes conditions, une valeur de 500 permet d'importer environ 18'000 enregistrement par seconde.

La solution proposée ci-dessous n'est toutefois pas optimale. Une importation par batch serait plus adapté à ce type de traitement.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// préparation de la table de destination
$sql.update("create table tmpCsv(EGID varchar(9),
                                 EDID varchar(2),
                                 EGAID varchar(9),
                                 DEINR varchar(12),
                                 ESID varchar(8),
                                 STRNAME varchar(120),
                                 STRNAMK varchar(48),
                                 STRINDX varchar(6),
                                 STRSP varchar(4),
                                 STROFFIZIEL varchar(1),
                                 DPLZ4 varchar(4),
                                 DPLZZ varchar(2),
                                 DPLZNAME varchar(80),
                                 DKODE varchar(11),
                                 DKODN varchar(11),
                                 DOFFADR varchar(1),
                                 DEXPDAT varchar(10))"::T);
$sql.update("delete from tmpCsv");  // note: SQLite ne supporte pas "truncate"

// nombre max de records envoyés en DB à la fois
const maxCounter = 250;

// prototype de requête d'insertion
const sqlProto = "insert into tmpCsv(EGID,EDID,EGAID,DEINR,ESID,STRNAME,STRNAMK,STRINDX,STRSP,STROFFIZIEL,DPLZ4,DPLZZ,DPLZNAME,DKODE,DKODN,DOFFADR,DEXPDAT) values ";

// fonction d'écriture des données en DB
function flushData(data) {
    $sql.insert(sqlProto & data);
}

// chargement du CSV
var src = $file.load("C:/Temp/ch/eingang_entree_entrata.csv");
var csv = $csv.load(src, { format: { format: "tdf", skipHeaderRecord: true } });

try {
    var nrows = 0;
    var counter = maxCounter;
    var sqlData = "";   // lot de valeurs à passer à la requête INSERT

    var beg = $cal.timestamp(); // juste pour calculer le temps de traitement total

    // début des itérations
    while (true) {
        var row = $csv.nextRecord(csv);
        if (row != null) {
            // string qui aura la forme ",('valA1','valB1',...)"
            var values = "";
            for (var col : row) {
                values &= ",'${col::Q}'";
            }

            // on ajoute les valeurs à notre lot de values
            sqlData &= ",(" & $string.substring(values, 1) & ")";

            // on contrôle s'il y a lieu de faire un flush
            if (--counter == 0) {
                flushData($string.substring(sqlData, 1));  // on skip la 1re virgule
                counter = maxCounter;   // reset du compteur
                sqlData = "";           // reset du lot de values
            }

            // comptage de ligne et affichage d'un log tous les 10'000 records
            if (++nrows % 10000 == 0) $logger.info(nrows);
        }
        else {
            // fin de fichier
            break;
        }
    }

    // on flush le solde de data
    if (sqlData != "") {
        flushData($string.substring(sqlData, 1));
    }

    $logger.info("Duration: " & $cal.diff(beg, $cal.timestamp());
}
finally {
    // fermeture du parser
    $csv.close(csv);
}

Voir également l'exemple de la méthode $csv.parse qui réalise le même traitement, mais de façon différente.