Dans nos deux précédents articles, nous avons exploré la puissance des fonctions d'Entrées/Sorties (I/O) à bas niveau pour manipuler des tables SAS (Data Sets) de manière dynamique. Mais qu'en est-il des fichiers textes externes ?
Au quotidien, l'instruction INFILE couplée à INPUT est notre meilleure alliée pour lire des fichiers plats (CSV, TXT). Cependant, face à des fichiers exotiques — des logsFichiers chronologiques enregistrant les événements système, erreurs et activités d'exécution dans SAS Viya, essentiels pour le monitoring, le débogage et l'audit des services et des jobs. d'applications non structurés, des fichiers où le délimiteur change selon la ligne, ou des documents que vous devez parser conditionnellement — INFILE peut vite devenir un casse-tête.
Aujourd'hui, nous allons voir comment les fonctions I/O dédiées aux fichiers externes (la famille des fonctions commençant par F) nous offrent un contrôle chirurgical sur la lecture de textes complexes.
1. Le cycle de vie d'un fichier texte et le concept du "FDB"
Lire un fichier texte avec les fonctions de bas niveau suit une chorégraphie très stricte, similaire à celle des tables SAS, mais avec un acteur central différent : le FDB (File Data Buffer).
Voici le processus étape par étape :
FILENAME: Comme pour unLIBNAME, on associe un chemin physique à un nom logique (fileref).FOPEN: On ouvre le fichier (ce qui nous retourne un identifiant de fichier, ou File ID).FREAD: Cette fonction lit la ligne suivante du fichier physique et la stocke dans le FDB (une zone de mémoireGemini said
Espace de stockage temporaire (RAM) utilisé par le moteur CAS pour charger et traiter les données à haute vitesse, minimisant les accès disque pour optimiser les performances de SAS Viya. tampon). À ce stade, la donnée n'est pas encore dans votre programme !FGET: C'est cette fonction qui vient piocher dans le FDB pour copier le texte dans une variable de votre étape DATA (le PDV).FCLOSE: On ferme le fichier pour libérer la mémoireGemini said
Espace de stockage temporaire (RAM) utilisé par le moteur CAS pour charger et traiter les données à haute vitesse, minimisant les accès disque pour optimiser les performances de SAS Viya..
2. Exemple 1 : Lire un fichier texte ligne par ligne
Commençons par la base : lire un fichier texte (par exemple, un log système) et afficher son contenu brut ligne par ligne. Remarquez comment nous utilisons un fileref dynamique généré par SAS pour éviter tout conflit.
SAS
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
/* 1. Déclaration des variables */
length ligne_texte $ 200
msg_erreur $ 75
mon_fileref $ 8;
/* Initialisation à vide pour que SAS génère un nom de fileref automatique */
mon_fileref = '';
/* 2. Assignation du fichier physique */
rc_file = filename(mon_fileref, 'C:\temp\mon_journal_log.txt');
if rc_file > 0 then goto gestion_erreur;
/* 3. Ouverture du fichier en lecture séquentielle ('S' pour Sequential ou 'I' pour Input) */
id_fichier = fopen(mon_fileref, 'S');
if id_fichier = 0 then goto gestion_erreur;
putlog "--- DÉBUT DE LA LECTURE ---";
/* 4. Boucle de lecture des lignes */
do while (1);
/* FREAD copie la ligne physique vers la mémoire tampon (FDB) */
code_retour = fread(id_fichier);
/* Si code_retour n'est pas 0, c'est la fin du fichier (-1) ou une erreur */
if code_retour ne 0 then leave;
/* FGET extrait le texte du FDB (jusqu'à 200 caractères) vers notre variable */
code_extraction = fget(id_fichier, ligne_texte, 200);
/* Traitement métier : on affiche la ligne */
putlog ligne_texte;
end;
putlog "--- FIN DE LA LECTURE ---";
/* 5. Routines de nettoyage */
fermeture_fichier:
code_fermeture = fclose(id_fichier);
code_liberation = filename(mon_fileref, ''); /* Libère le fileref */
stop;
gestion_erreur:
code_err = sysrc();
msg_erreur = sysmsg();
putlog "ERREUR: Impossible de lire le fichier. Code: " code_err;
if msg_erreur ne '' then putlog msg_erreur;
stop;
run;
Le détail qui change tout :
Si une ligne de votre fichier fait 500 caractères, mais que votre variable ligne_texte est limitée à 200, FGET tronquera silencieusement le texte pour le faire rentrer. Assurez-vous d'avoir une instruction length suffisamment grande !
3. Le parsing chirurgical : Gérer les champs avec FSEP
L'exemple ci-dessus récupère toute la ligne d'un coup. Mais que faire si votre fichier est un fichier délimité (comme un CSV) ou s'il contient des séparateurs spécifiques (comme des tabulations ou des "pipes" |) ?
C'est ici que le FDB montre sa vraie puissance. Voyez la fonction FGET non pas comme un simple copieur, mais comme un curseur intelligent.
- Avec la fonction
FSEP(File Separator), vous pouvez dire à SAS : "Voici le délimiteur de ce fichier". - Ensuite, chaque appel à
FGETne lira plus toute la ligne, mais se déplacera d'un délimiteur à l'autre à l'intérieur du FDB.
4. Exemple 2 : Découper un fichier complexe champ par champ
Imaginons un fichier où chaque ligne contient des informations séparées par un point-virgule (;). Nous allons utiliser FSEP pour configurer le délimiteur, et appeler FGET en boucle pour extraire chaque champ un par un, peu importe combien de champs contient la ligne.
SAS
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
length champ_extrait $ 50
mon_fileref $ 8;
mon_fileref = '';
rc = filename(mon_fileref, 'C:\temp\donnees_complexes.txt');
id_fichier = fopen(mon_fileref, 'S');
if id_fichier = 0 then do;
putlog "Erreur d'ouverture du fichier.";
stop;
end;
/* DÉFINITION DU DÉLIMITEUR : on configure le FDB pour chercher les ';' */
rc_sep = fsep(id_fichier, ';');
/* Boucle principale : lecture ligne par ligne (FREAD) */
do while (fread(id_fichier) = 0);
putlog "-> Nouvelle Ligne détectée :";
compteur_champ = 1;
/* Boucle secondaire : extraction champ par champ (FGET) */
/* FGET renvoie -1 quand il arrive à la fin du buffer de la ligne courante */
do while (fget(id_fichier, champ_extrait) = 0);
putlog " Champ N°" compteur_champ " : " champ_extrait;
compteur_champ + 1;
end;
end;
/* Fermeture propre */
rc = fclose(id_fichier);
rc = filename(mon_fileref, '');
run;
Pourquoi est-ce si puissant ?
- Flexibilité totale : Si la première ligne contient 3 champs et la deuxième en contient 12, ce code fonctionnera parfaitement sans planter (contrairement à un
INPUTstatique). - Délimiteurs dynamiques : Vous pourriez tout à fait écrire une logique qui change le délimiteur via
FSEPen cours de route, en fonction du contenu que vous venez de lire ! (Exemple : si le premier mot de la ligne est "LOG", le délimiteur est un espace. Si c'est "DATA", c'est une virgule).
Conclusion
Les fonctions FOPEN, FREAD, FSEP et FGET transforment SAS en un véritable scalpel pour le traitement de texte. Bien qu'elles demandent d'écrire un peu plus de logique qu'une simple étape INFILE, elles permettent d'absorber n'importe quelle structure de fichier, aussi chaotique soit-elle.
Vous avez maintenant toutes les clés pour lire n'importe quelle donnée, qu'elle provienne d'une table SAS ou d'un fichier texte brut.
Mais comment faire si l'on veut exécuter ces puissantes actions I/O sans même utiliser d'étape DATA, par exemple au beau milieu d'une logique macro ? C'est ce que nous découvrirons dans notre prochain article avec la fonction macro %SYSFUNC !






