Demande d'aide avec la lecture de fichier JSON

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Demande d'aide avec la lecture de fichier JSON

Message par boddhi »

Autres remarques :
• tu ouvres et fermes ta BDD par deux fois. pourquoi ne pas faire en sorte qu'elle ne le soit qu'une seule fois ?
• l'instruction SQL "PRAGMA auto_vacuum = FULL" n'est à utiliser qu'une seule fois, au moment de la création de la BDD. Chaque BDD possède dans sa structure des paramètres qui lui sont propres. Celui-ci en est un et, une fois défini, il devient persistant tant qu'il n'est pas modifié...
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: Demande d'aide avec la lecture de fichier JSON

Message par cage »

Deux remarques :
1) Il y a un travail d'optimisation à faire : En effet, des portions de code sont redondantes
2) Le recours à une GUI détaillant le déroulement des processus (avec leurs résultats - réussite ou échec) serait un plus :wink: surtout si tu veux en faire un exécutable (lequel accélérerait également l'exécution du code)
Je suis tout a fait d'accord avec toi, mais ce code n'a pour but que de vérifier la faisabilité de
a) création d'une ou plusieurs BD, je n'ai pas encore fait le choix
b) faire de multiples accès en lecture de la BD
c) éventuellement, enregistrer une donnée ou l'effacer
d) actualiser la base avec des données fraiches. Effacer les anciennes et écrire les nouvelles.
e) lire des données diverses sous forme de JSON pour soit les afficher, soit les enregistrer pour usage différé

Mon application "my player iptv" gére une vingtaine de playlists dont certaines contiennent 300.000 entrées
A ce jour, voici comment je procéde
a) je télécharge sur disque une fois par jour la playlist qui m'intéresse
b) je traite la playlist a l'aide de Map/List/Structure pour pouvoir utiliser la playlist a ma convenance, regarder une chaine, un film ou une série
c) je ferme l'application
d) je ré-ouvre l'application et je reprend le processus a la phase b)
C'est lourd et ça prend du temps, que se soit pour la lecture de la playlist et son traitement ou que se soit pour la création des menus
Mon souhait était de transposer tout cela dans une BD
Une fois le premier traitement terminé, la BD n'est pas modifiée, sinon lors d'une mise à jour de la playlist.
Donc gain de temps.
A ce jour, les playlists sont enregistrées dans des dossiers qui sont dédiés a cette playlist
Par exemple, pour la playlist Freebox, le dossier est ".\m3u\Freebox\playlist.m3u" relatif au dossier de l'application.
Maintenant, je pense télécharger en mémoire la playlist, la traiter en BD et l'enregistrer en playlist.db
Mon idée est de faire ça pour toutes les playlists, soit au total environ 20 BD playlist.db
Ceci afin de ne pas être obligé de travailler en multi-tables dans une BD unique.
Pour la partie JSON, ça ne concerne que la playlist Freebox.
Son but premier est de me donner une correspondance Nom de chaine/uuid afin de pouvoir accéder au guide TV de la chaine.
Dans l'interface de "my player iptv", un clic droit sur une chaine amène un menu contextuel avec 2 choix:
1) ajouter aux favoris ou retirer des favoris
2) afficher le guide TV de la chaine

Je sais maintenant grâce a toi que c'est possible, même si je n'en ai jamais douté.
Ton aide et tes conseils avisés sont les bienvenus, ainsi que toute suggestion d'améliorations du processus.
Je prends bien note de toute tes remarques et je modifie mon code en rapport.

J'ai du pain sur la planche avant que mon application iptv soit satisfaisante, du moins a mes yeux.
cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: Demande d'aide avec la lecture de fichier JSON

Message par cage »

Autres remarques :
• tu ouvres et fermes ta BDD par deux fois. pourquoi ne pas faire en sorte qu'elle ne le soit qu'une seule fois ?
• l'instruction SQL "PRAGMA auto_vacuum = FULL" n'est à utiliser qu'une seule fois, au moment de la création de la BDD. Chaque BDD possède dans sa structure des paramètres qui lui sont propres. Celui-ci en est un et, une fois défini, il devient persistant tant qu'il n'est pas modifié...
J'ouvre par deux fois la BD pour simuler 2 actions différentes, mais effectivement, j'aurais pu le faire en une seule fois.
Je prend note pour "PRAGMA auto_vacuum = FULL"
A passer une seule fois au moment de la création de la BD (avant ou après création de la table. ?)
Une fois cette commande passée et inscrite dans les paramètres de la BD, suis-je obligé d'utiliser la commande "VACUUM" ou alors cette commande est automatique.
Si je dois la passer, quel est le moment le plus judicieux. ?
cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Demande d'aide avec la lecture de fichier JSON

Message par boddhi »

Je t'avouerai ne pas avoir tout bien compris le cheminement de ce que tu souhaites faire et la chaleur n'aide pas non plus ! :lol:
cage a écrit : a) création d'une ou plusieurs BD, je n'ai pas encore fait le choix
Pour quelle raison/à quelles fins envisages-tu éventuellement la création de plusieurs BDD ?
cage a écrit : d) je ré-ouvre l'application et je reprend le processus a la phase b)
Là, je comprends pas ! Pourquoi ré-ouvrir ? C'est la même playlist ? Si oui ou si non, en quoi est-elle différente ?

Et quand tu parles de 'traitement', c'est le processus complet ? une partie du processus ?
cage a écrit : Mon idée est de faire ça pour toutes les playlists, soit au total environ 20 BD playlist.db
Ceci afin de ne pas être obligé de travailler en multi-tables dans une BD unique.
Pourquoi ne pas envisager un champ supplémentaire dans ta table qui te permettrait de distinguer chacune des playlists ?
Tu pourrais ensuite t'appuyer sur ce champ pour faire toutes sortes d'opérations (SELECT, UPDATE, DELETE, ...)
cage a écrit : Je prend note pour "PRAGMA auto_vacuum = FULL"
A passer une seule fois au moment de la création de la BD (avant ou après création de la table. ?)
Peu importe, l'idéal étant que cela soit fait avant toute opération de suppression ou de MàJ.
Après, dans ma logique "à moi", je crée la BDD, je mets à jour ses paramètres et ensuite, seulement, je crée les tables.
cage a écrit : Une fois cette commande passée et inscrite dans les paramètres de la BD, suis-je obligé d'utiliser la commande "VACUUM" ou alors cette commande est automatique.
Oui et non !
Le paramètre 'auto_vaccum=full' fera décroître automatiquement la taille en octets de ta BDD en libérant l'espace inutilisé à la suite de suppressions ou MàJ mais ne la défragmentera pas.
La commande 'vacuum' fera les deux, libération d'espace et défragmentation. L'intérêt de la défragmentation, tout comme pour un disque dur, est de rendre plus rapide l'accès aux données.
'vacuum' peut être lancée à n'importe quel moment. Toutefois, le moment idéal étant juste avant la fermeture BDD. Mais, tu peux aussi l'exécuter après de très grosses opérations de suppressions ou de MàJ de données. Cela rendra le 'vacuum' final moins long en temps d'exécution.
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Demande d'aide avec la lecture de fichier JSON

Message par boddhi »

Notes sur ton code :

Code : Tout sélectionner

CheckDatabaseUpdate(OUT, #QUERY_DELETE_TABLE)
CheckDatabaseUpdate(OUT, #QUERY_CREATE_TABLE)
peut être remplacé par

Code : Tout sélectionner

CheckDatabaseUpdate(OUT, "DELETE * FROM Database")
  
 

Code : Tout sélectionner

CheckDatabaseQuery(DB, #QUERY_SELECT_TABLE+"'%TF1%'")
Là aussi tu peux te servir de SetDatabaseXxxx()

Code : Tout sélectionner

#QUERY_SELECT_TABLE="SELECT UUID,NAME FROM DATABASE WHERE NAME LIKE ?" ; (ou %?% si vraiment nécessaire)
[...]
SetDatabaseString(DB,0,"TF1")
CheckDatabaseUpdate(DB,#QUERY_SELECT_TABLE)
Note : Pour information, toutes les valeurs définies par des SetDatabaseXxxx() sont remises à 0 dès la première utilisation d'un DatabaseQuery ou DatabaseUpdate. Ainsi :

Code : Tout sélectionner

SetDatabaseString(DB,0,"TF1")
CheckDatabaseQuery(DB,"SELECT * FROM Database WHERE Name=?") ; Récupérera tous les enregistrements où Name=TF1
FinishDatabaseQuery(DB)
CheckDatabaseQuery(DB,"SELECT * FROM Database WHERE Name=?") ; Récupérera tous les enregistrements où Name est un champ vide puisqu'il n'y pas eu de SetDataseString entre les deux 'SELECT'
 
 

Code : Tout sélectionner

  *TamponJSON = ReceiveHTTPMemory(url$)
  If *TamponJSON
    JSON = CatchJSON(#PB_Any, *TamponJSON, MemorySize(*TamponJSON))
    If JSON
      ChaineJSON$ = ComposeJSON(JSON)
      ; ------- !!!! IMPORTANT !!!! ----------
      ; Remplacer les valeurs true et false pour qu'elles puissent être récupérées via la structure DATAS_GUIDE
      ChaineJSON$=ReplaceAllString(ChaineJSON$,": true," ,":1,",#PB_String_NoCase)
      ChaineJSON$=ReplaceAllString(ChaineJSON$,":true,"  ,":1,",#PB_String_NoCase)
      ChaineJSON$=ReplaceAllString(ChaineJSON$,": false,",":0,",#PB_String_NoCase)
      ChaineJSON$=ReplaceAllString(ChaineJSON$,":false," ,":0,",#PB_String_NoCase)
      ; --------------------------------------
      JSON = ParseJSON(#PB_Any, ChaineJSON$, #PB_JSON_NoCase)
    Else
      Debug "Echec lors de l'analyse des données JSON"
    EndIf
  FreeMemory(*TamponJSON)
  Else
    Debug "Echec de la réception en mémoire du fichier JSON"
  EndIf
Toutes les portions de code de ce type peuvent placées à l'intérieur d'une procédure.
Il te suffit ensuite de retourner la valeur JSON pour savoir si tu peux continuer à travailler avec l'arbre JSON ou non.
Dernière modification par boddhi le jeu. 24/août/2023 21:58, modifié 2 fois.
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: Demande d'aide avec la lecture de fichier JSON

Message par cage »

Là, je comprends pas ! Pourquoi ré-ouvrir ? C'est la même playlist ? Si oui ou si non, en quoi est-elle différente ?
Oui, c'est la même playlist, donc la seule différence, c'est que j'ai fermé l'application.
Comme la liste de toute les chaines est chargée dans une ListIconGadget(), il faut bien que je relise la playlist pour alimenter la ListIconGadget()
Une fois cette playlist (fichier playlist.m3u) transposé en DB, a chaque démarrage de mon application, lecture de la BD et insertion dans la ListIconGadget()
Ce sera beaucoup plus rapide.
Pour quelle raison/à quelles fins envisages-tu éventuellement la création de plusieurs BDD ?
Question de facilité, il y a beaucoup de disparité dans les playlists et j'ai du m'adapter a chacune.
Je peux passer de fichier a BD chaque playlist en prenant mon temps pour le faire.
Et au final, peut-être tout mettre dans la même BD.
Déjà, chaque table porte le nom de la playlist en fonction du fournisseur (AUMALE,FREEBOX,JOURNALSAT,PLEX,PLUTO,RADIOS,RAKUTEN,SAMSUNG,TVCLUB) et bien d'autres.
Je n'aurais aucun mal donc a toutes les enregistrer dans la même BD.
Et quand tu parles de 'traitement', c'est le processus complet ? une partie du processus ?
Le traitement de la playlist, hors le fait de la télécharger pour avoir les dernières mis à jour, c'est
a) la lire ligne a ligne pour en retirer les informations telles que "NomDeChaine" ou "NomDeFilm" ou "NomDeSérie" et les liens externes associés et mettre tout ça en forme dans des List/MAp a l'aide de structures
b) créer tout les menus qui donnent accès a ces chaines/films/séries
c) afficher dans la ListIconGadget() la liste Live (Chaines en live)
Ensuite, on a le choix d'afficher les films ou les séries ou les chaines.
Un clic sur le titre d'une colonne de la ListIconGadget() permet de trier en ascendant/descendant
Tout cela grâce au List/MAp crées précédemment.
C'est pour cela que je veux tout passer en BD, car 1 requête SQL bien ficelée, et le tour est joué.
Me reste aussi a voir comment je gère les chaines mises en favoris lors d'une mise à jour de la playlist.
Aujourd'hui, c'est géré dans un fichier favoris.txt dans chaque dossier des playlists

Autrement, Ok pour la commande "VACUUM"
cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Demande d'aide avec la lecture de fichier JSON

Message par boddhi »

cage a écrit : Oui, c'est la même playlist, donc la seule différence, c'est que j'ai fermé l'application.
Comme la liste de toute les chaines est chargée dans une ListIconGadget(), il faut bien que je relise la playlist pour alimenter la ListIconGadget()
Une fois cette playlist (fichier playlist.m3u) transposé en DB, a chaque démarrage de mon application, lecture de la BD et insertion dans la ListIconGadget()
J'ai peut-être (même probablement) sauté un wagon... mais pourquoi ne pas alimenter la BDD et la ListIconGadget en même temps que l'analyse de l'arbre JSON ?
Genre :

Code : Tout sélectionner

If ExamineJSONMembers(jsonObjectValue) ; si il contient des membres
  While NextJSONMember(jsonObjectValue)
    AddElement(CHAINES())
    With CHAINES()
      \NomCanal=JSONMemberKey(jsonObjectValue)
      ExtractJSONStructure(JSONMemberValue(jsonObjectValue),\DonneesChaine,DATAS_CHAINE)
      ; /////////////////////////////////////
      ; Ici
      CheckDatabaseUpdate(DB,...........)
      AddGadgetItem(ListIcon,...........)
      ; /////////////////////////////////////
    EndWith
  Wend
EndIf
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: Demande d'aide avec la lecture de fichier JSON

Message par cage »

J'ai peut-être (même probablement) sauté un wagon... mais pourquoi ne pas alimenter la BDD et la ListIconGadget en même temps que l'analyse de l'arbre JSON ?
Lest playlists sont au format m3u sous cette forme (ce n'est pas du JSON)
Je prends l'exemple de la Freebox qui est très simple par rapport a d'autres playlists

Code : Tout sélectionner

#EXTM3U
#EXTINF:0,1 - TF1 (TNT)
rtsp://mafreebox.freebox.fr/fbxdvb/stream?tsid=6&nid=8442&sid=1537&frontend=1
#EXTINF:0,2 - France 2 (bas débit)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=201&flavour=ld
#EXTINF:0,2 - France 2 (auto)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=201
#EXTINF:0,2 - France 2 (HD)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=201&flavour=hd
#EXTINF:0,2 - France 2 (standard)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=201&flavour=sd
#EXTINF:0,2 - France 2 (TNT)
rtsp://mafreebox.freebox.fr/fbxdvb/stream?tsid=1&nid=8442&sid=257&frontend=1
#EXTINF:0,3 - France 3 (auto)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=202
#EXTINF:0,3 - France 3 (HD)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=202&flavour=hd
#EXTINF:0,3 - France 3 (standard)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=202&flavour=sd
#EXTINF:0,3 - France 3 (bas débit)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=202&flavour=ld
#EXTINF:0,3 - F3 Paris Ile-de-France (TNT)
rtsp://mafreebox.freebox.fr/fbxdvb/stream?tsid=1&nid=8442&sid=273&frontend=1
#EXTINF:0,4 - CANAL+ (TNT)
rtsp://mafreebox.freebox.fr/fbxdvb/stream?tsid=3&nid=8442&sid=769&frontend=1
#EXTINF:0,4 - CANAL+ (TNT)
rtsp://mafreebox.freebox.fr/fbxdvb/stream?tsid=3&nid=8442&sid=778&frontend=1
#EXTINF:0,5 - France 5 (auto)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=203
#EXTINF:0,5 - France 5 (HD)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=203&flavour=hd
#EXTINF:0,5 - France 5 (standard)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=203&flavour=sd
#EXTINF:0,5 - France 5 (TNT)
rtsp://mafreebox.freebox.fr/fbxdvb/stream?tsid=4&nid=8442&sid=1045&frontend=1
#EXTINF:0,6 - M6 (TNT)
rtsp://mafreebox.freebox.fr/fbxdvb/stream?tsid=4&nid=8442&sid=1025&frontend=1
#EXTINF:0,7 - Arte (HD)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=204&flavour=hd
#EXTINF:0,7 - Arte (standard)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=204&flavour=sd
#EXTINF:0,7 - Arte (bas débit)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=204&flavour=ld
#EXTINF:0,7 - Arte (auto)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=204
#EXTINF:0,7 - Arte (TNT)
rtsp://mafreebox.freebox.fr/fbxdvb/stream?tsid=4&nid=8442&sid=1031&frontend=1
#EXTINF:0,8 - C8 (standard)
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=372&flavour=sd
Cette liste est simple, car elle ne fait pas référence aux catégories Live, Movie, Serie ou autres.
La lecture se fait en séquentiel, Nom de la chaine, URL de la chaine puis Nom de la chaine, URL de la chaine et ainsi de suite.
Donc il faut associer chaque chaine a son URL plus un index d'ordre pour pouvoir faire un tri sur chaque titre de colonne.
Le JSON est particulier a la Freebox et donne uniquement des infos sur les chaines et ne sert que pour le guide TV
Quand on clique sur le nom d'une chaine, elle s'ouvre dans le player de son choix (vlc par exemple)

La BD n'est créé qu'une fois par jour, mais pour Freebox, une fois par semaine suffit largement, la liste change rarement.
Donc, si tous les jours je lance l'application, il faut bien que je remplisse la ListIconGadget() avec les infos des chaines.
D’où, je suis obligé de relire la playlist sauf si je la transpose en BD. Dans ce cas, une seule requête SQL suffit pour documenter la ListIconGadget()
Rapidité et simplicité.
Pour la BD de la Freebox, 2 tables sont nécessaires, une que je nomme CHAINES pour enregistrer les infos JSON et l'autre FREEBOX pour enregistrer toutes les informations de la playlist.
cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: Demande d'aide avec la lecture de fichier JSON

Message par cage »

Un exemple un peu plus compliqué d'une playlist au format m3u

Code : Tout sélectionner

#EXTM3U
#EXTINF:-1 tvg-id="TF1.fr" tvg-name="FR - TF 1" tvg-logo="http://logo.protv.cc/picons-dino/logos/tf1hd.png" group-title="|EU| FRANCE GENERAL",FR - TF 1
http://line.premium-dino.com:80/Username/Password/543147
#EXTINF:-1 tvg-id="M6.fr" tvg-name="FR - M6" tvg-logo="http://logo.protv.cc/picons-dino/logos/m6hd.png" group-title="|EU| FRANCE GENERAL",FR - M6
http://line.premium-dino.com:80/Username/Password/543159
#EXTINF:-1 tvg-id="France2.fr" tvg-name="FR - FRANCE 2" tvg-logo="http://logo.protv.cc/picons-dino/logos/france2hd.png" group-title="|EU| FRANCE GENERAL",FR - FRANCE 2
http://line.premium-dino.com:80/Username/Password/543149
#EXTINF:-1 tvg-id="France3.fr" tvg-name="FR - FRANCE 3" tvg-logo="http://logo.protv.cc/picons-dino/logos/france3hd.png" group-title="|EU| FRANCE GENERAL",FR - FRANCE 3
http://line.premium-dino.com:80/Username/Password/543151
#EXTINF:-1 tvg-id="France4.fr" tvg-name="FR - FRANCE 4" tvg-logo="http://logo.protv.cc/picons-dino/logos/france4.png" group-title="|EU| FRANCE GENERAL",FR - FRANCE 4
http://line.premium-dino.com:80/Username/Password/543153
Il y a plus de travail pour parser cette playlist qui est complétement différente de celle de la Freebox.
cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Demande d'aide avec la lecture de fichier JSON

Message par boddhi »

cage a écrit : Un exemple un peu plus compliqué d'une playlist au format m3u
Avec des StringField(), c'est un jeu d'enfant ! :wink: :D
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: Demande d'aide avec la lecture de fichier JSON

Message par cage »

Procédure simplifiée pour lire une playlist genre playlist Freebox

Code : Tout sélectionner

Structure CHAINES
  INDEX.s
  GENRE.s
  MEDIA.s
  TITRE.s
  GROUP.s
  SERIE.s
  PAYS.s
  REFID.s
EndStructure

Global NewList LISTE.CHAINES()

Procedure lecture_playlist()
  IN = ReadFile(#PB_Any, PLAYLIST.s)
  If IN
    ;;; === LECTURE PLAYLIST ===
    While Eof(IN) = 0
      entry$ = Trim(ReadString(IN))
      If entry$ = #Null$
        Continue
      EndIf
      begin$ = UCase(Left(entry$,7))
      Select begin$
        Case "#EXTINF"
          I+1
          VRAI_CHANNEL+1
          title$ = #Null$
          If FindString(entry$,"--") Or
             FindString(entry$,"**") Or
             FindString(entry$,"==") Or
             FindString(entry$,"++") Or
             FindString(entry$,"##") Or
             FindString(entry$,"- -")
            VRAI_CHANNEL-1
            FAUX_CHANNEL+1
            Continue
          EndIf
          title$ = StringField(entry$,2,",")
          title$ = Trim(title$)
          title$ = UCase(title$)
          title$ = replaceAllString(title$,Space(2),Space(1))
          fra$ = "FR:"
          foo$ = "FR:"
          pay$ = #Empty$
          If Left(title$, 3) = foo$
            pay$ = fra$
            title$ = Trim(StringField(title$, 2, foo$))
            title$ = fra$ + " " + title$
          EndIf
          foo$ = "|FR|"
          If Left(title$, 4) = foo$
            pay$ = fra$
            title$ = Trim(StringField(title$, 2, foo$))
            title$ = fra$ + " " + title$
          EndIf
          foo$ = "[FR]"
          If Left(title$, 4) = foo$
            pay$ = fra$
            title$ = Trim(StringField(title$, 2, foo$))
            title$ = fra$ + " " + title$
          EndIf
          foo$ = "FR -"
          If Left(title$, 4) = foo$
            pay$ = fra$
            title$ = Trim(StringField(title$, 2, foo$))
            title$ = fra$ + " " + title$
          EndIf
          If FindString(title$, "_")
            title$ = ReplaceString(title$, "_", " ")
          EndIf
          title$ = replaceAllString(title$,Space(2),Space(1))
        Case "HTTP://", "HTTPS:/", "RTSP://"
          LAST_CHANNEL+1
          If title$ = #Null$
            Continue
          EndIf
          LIVE+1
          N = CountString(entry$, "/")
          refid$  = Str(LAST_CHANNEL)
          lastid$ = StringField(entry$, N+1, "/")
          N = 6
          Select fournisseur$
            Case #FREEBOX    : refid$ = RSet(refid$ ,3,"0") : N=3
            Case #TVCLUB     : refid$ = lastid$             : N=2
            Default          : refid$ = RSet(refid$ ,6,"0")
          EndSelect
          ;;; ====== LISTE() ======
          AddElement(LISTE())
          LISTE()\INDEX = RSet(Str(I),N,"0")
          LISTE()\GENRE = #live
          LISTE()\MEDIA = entry$
          LISTE()\TITRE = title$
          LISTE()\REFID = refid$
      EndSelect
      ;;; === FIN LECTURE PLAYLIST ===
    Wend
    CloseFile(IN)
  EndIf ; If IN
EndProcedure
cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Demande d'aide avec la lecture de fichier JSON

Message par boddhi »

cage a écrit : Procédure simplifiée pour lire une playlist genre playlist Freebox
Comme tous les chemins mènent à Rome et pour le fun, voici ma proposition d'analyse de ton fichier Freebox avec utilisation des StringField()

Code : Tout sélectionner

EnableExplicit

Structure INFOSCHAINE
  Nom.s
  Groupe.s
  Langue.s
  UrlChaine.s
  UrlLogo.s
  UrlVideo.s
EndStructure
;
NewList Chaines.INFOSCHAINE()
Define.s ChaineM3U,LigneFichier
Define.a LigneDonneeOk,FichierValide
Define.l NoLigneFichier,NbLignesDonnees
;
#Fichier=""
CompilerIf #Fichier=""
  MessageRequester("Erreur","La constante 'Fichier' n'a pas reçu de nom de fichier !",#PB_MessageRequester_Error)
  End
CompilerEndIf
If ReadFile(0,#Fichier,#PB_UTF8)
  While Not Eof(0)
    LigneFichier=Trim(ReadString(0))
    NoLigneFichier+1
    If LigneFichier
      If UCase(LigneFichier)="#EXTM3U" And NbLignesDonnees=0
        FichierValide=#True
      Else
        If Not FichierValide
          Debug "Fichier non valide"
          Break
        EndIf
        Select UCase(StringField(LigneFichier,1,":"))
          Case "#EXTINF"
            If Not LigneDonneeOk
              NbLignesDonnees+1
              AddElement(Chaines())
              With Chaines()
                \UrlChaine=StringField(StringField(LigneFichier,2,"tvg-id="+Chr(34)),1,Chr(34))
                LigneDonneeOk=Bool(\UrlChaine<>"")
                If LigneDonneeOk
                  \UrlLogo=StringField(StringField(LigneFichier,2,"tvg-logo="+Chr(34)),1,Chr(34))
                  \Groupe=StringField(StringField(LigneFichier,2,"group-title="+Chr(34)),1,Chr(34))
                  \Nom=StringField(StringField(LigneFichier,2,","),1,Chr(34))
                  \Langue=StringField(\Nom,1," - ")
                  \Nom=StringField(\Nom,2," - ")
                EndIf
              EndWith
            EndIf
            If Not LigneDonneeOk
              Debug "Ligne n° "+NoLigneFichier+" : Mauvais format de ligne, Url vidéo attendue !"
            EndIf
          Case "HTTP","HTTPS","RSTP"
            If LigneDonneeOk
              With Chaines()
                \UrlVideo=LigneFichier
                Debug "Nom chaîne : "+\Nom+#LF$+"Groupe : "+\Groupe+#LF$+"Langue : "+\Langue+#LF$+"Url chaîne : "+\UrlChaine+#LF$+"Url logo : "+\UrlLogo+#LF$+"Url vidéo : "+\UrlVideo
                Debug "*********************************************************"
              EndWith
              LigneDonneeOk=#False
            Else
              Debug "Ligne n° "+NoLigneFichier+" : Mauvais format de ligne, #EXTINF attendu !"
            EndIf
        EndSelect
      EndIf
    EndIf
  Wend
  CloseFile(0)
  Debug ""+NbLignesDonnees+" ligne(s) de données de chaînes traitée(s)"
Else
  Debug "Erreur système : "+GetLastError_()
EndIf
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: Demande d'aide avec la lecture de fichier JSON

Message par cage »

Bonjour,

Je suis entrain de travailler sur ton code pour améliorer ma lecture des playlist.m3U qui date de plusieurs années maintenant.
J'ai mis sur mon site 3 fichiers playlist.m3u différents pour tester le code.
Télécharger playlist-dino.7z
Télécharger playlist-freebox.7z
Télécharger playlist-maroc.7z
Ces playlists sont modifiées et ne sont pas donc pas utilisables en l'état.
Seule la playlist Freebox est vraie mais non utilisable si on est pas chez Free.
Je posterais ici mon code fait a partir du tien dès qu'il sera assez avancé.
Je trouve vraiment très plaisant et très instructif notre échange.
Comme quoi le JSON ouvre des portes.
cage

Comme promis, voici le code

Code : Tout sélectionner

EnableExplicit

SetCurrentDirectory(GetPathPart(ProgramFilename()))

#films   = "Films"
#live    = "Live"
#series  = "Séries"
#inconnu = "Inconnu"

Structure INFOSCHAINE
  Index.l     ; index de la vidéo dans l'ordre d'apparition dans la playlist
  Nom.s       ; nom de la vidéo a afficher (nom du live, film ou série)
  Genre.s     ; live, film ou série
  Serie.s     ; titre de la série
  Groupe.s    ; group-title, nom du groupe d'appartenance de la vidéo
  Langue.s    ; 
  URLVideo.s  ; contenu de la ligne commençant par http:,https:,rtsp:
  ;ces données concernent le guide des programmes et peuvent êtres absentes
  TVGId.s     ; tvg-id
  TVGLogo.s   ; tvg-logo
  TVGName.s   ; tvg-name
EndStructure
;
NewList Chaines.INFOSCHAINE()
Define.s LigneFichier,Genre, Serie, NomVideo
Define.a LigneDonneeOk,FichierValide
Define   NoLigneFichier,NbLignesDonnees,NbCommas,Index
Define   IN
;
Global LIVE, FILMS, SERIES
Global LAST_CHANNEL=0
Global VRAI_CHANNEL=0
Global FAUX_CHANNEL=0
;
Global regex_nulle,regex_genre, regex_serie
;
; Sélectionner une playist pour commencer
;#PLAYLIST$ = "playlist-dino.m3u"
;#PLAYLIST$ = "playlist-freebox.m3u"
;#PLAYLIST$ = "playlist-maroc.m3u"

CompilerIf Not Defined(PLAYLIST$, #PB_Constant)
  #PLAYLIST$=#Empty$
  MessageRequester("Erreur","La constante 'PLAYLIST' n'a pas reçu de nom de fichier !",#PB_MessageRequester_Error)
  End
CompilerEndIf

IN=ReadFile(#PB_Any,#PLAYLIST$,#PB_UTF8)
If IN
  Define HeureDebut=Date()
  Index=0
  LigneDonneeOk=#False
  ClearList(Chaines())
  ; commenter la ligne suivante pour garder toutes les vidéos
  regex_nulle=CreateRegularExpression(#PB_Any, "([*]{3}|[#]{3}|[=]{3}|[-]{3}|[+]{3}|- -)")
  ; permet d'extraire le genre des vidéos (live, films ou séries)
  regex_genre=CreateRegularExpression(#PB_Any, "(?i)(/live/|/movie/|/series/)")
  ; permet d'extraire les numéros saison/épisode d'une série
  regex_serie=CreateRegularExpression(#PB_Any, " S.. E..")
  While Not Eof(IN)
    LigneFichier=Trim(ReadString(IN))
    NoLigneFichier+1
    ;If NoLigneFichier > 20 : Break : EndIf
    If LigneFichier
      Select UCase(StringField(LigneFichier,1,":"))
        Case "#EXTINF"
          LAST_CHANNEL+1
          If regex_nulle
            NbCommas=CountString(LigneFichier,",")
            NomVideo=StringField(LigneFichier,NbCommas+1,",")
            If ExamineRegularExpression(regex_nulle, NomVideo)
              If NextRegularExpressionMatch(regex_nulle)
                Debug NomVideo
                FAUX_CHANNEL+1
                NoLigneFichier+1
                LigneDonneeOk=#False
                ; on ne tiendra pas compte de la ligne qui suit
                ReadString(IN)
                Continue
              EndIf
            EndIf
          EndIf ; If regex_nulle
          If Not LigneDonneeOk
            Index+1
            NbLignesDonnees+1
            VRAI_CHANNEL+1
           ;La première ligne commence par #EXTINF: (durée) [attributs], (titre).
           ;Les paramètres requis sont : durée et titre.
           ;Dans le cas d’une chaine TV, la durée doit toujours être à 0 ou -1.
           ;Les attributs ne sont pas obligatoires, voici la liste des attributs pris en charge:
           ;tvg-shift    - décalage horaire du guide TV
           ;tvg-id       - ?
           ;tvg-name     - identifiant du guide TV
           ;tvg-logo     - logo de la chaîne (url)
           ;audio-track  - piste audio de la chaîne, si supportée.
           ;             - Saisir le code langue au format ISO 639-2,
           ;               vous pouvez utiliser plusieurs codes séparés par une virgule (ex:"eng, rus, fre").
           ;             - Le premier élément de la liste sera la langue définie par défaut.
           ;aspect-ratio - définit le ratio d’image (peut ne pas être disponible pour certains modèles TV).
           ;             - Valeurs disponibles: 16:9, 3:2, 4:3, 1,85:1, 2,39:1
           ;Exemples:
           ;#EXTINF:0,1 - TF1 (TNT)
           ;#EXTINF:-1,FR: TF1 FHD
           ;#EXTINF:-1 tvg-id="CLUB1." tvg-name="Club 1"    tvg-logo="1.png"     group-title="tvclub" ,Club 1
           ;#EXTINF:-1 tvg-id="TF1.fr" tvg-name="|FR| TF1"  tvg-logo="TF1.png"   group-title="FRANCE TNT",|FR| TF1
           ;#EXTINF:-1 tvg-id="TF1.fr" tvg-name="FR - TF 1" tvg-logo="tf1hd.png" group-title="|EU| FRANCE GENERAL",FR - TF 1
            AddElement(Chaines())
            With Chaines()
              \Nom = NomVideo
              If \Nom = #Empty$ : \Nom = #inconnu : EndIf
              LigneDonneeOk=Bool(\Nom<>"")
              If LigneDonneeOk
                \Index  = index
                \TVGId  =StringField(StringField(LigneFichier,2,"tvg-id="     +#DQUOTE$),1,#DQUOTE$)
               ;\TVGLogo=StringField(StringField(LigneFichier,2,"tvg-logo="   +#DQUOTE$),1,#DQUOTE$)
                \TVGName=StringField(StringField(LigneFichier,2,"tvg-name="   +#DQUOTE$),1,#DQUOTE$)
                \Groupe =StringField(StringField(LigneFichier,2,"group-title="+#DQUOTE$),1,#DQUOTE$)
                ;il n'est pas évident d'extraire la langue car il n'y a pas de format normalisé
                \Langue =StringField(\TVGName,1," - ") ; a traiter différemment ???
              EndIf
            EndWith
          EndIf
          If Not LigneDonneeOk
            Debug "Ligne n° "+NoLigneFichier+" : Mauvais format de ligne, Nom vidéo attendue !"
            Debug LigneFichier
            Debug "\Nom="+Chaines()\Nom
          EndIf
        Case "HTTP","HTTPS","RTSP"
          If LigneDonneeOk
            Chaines()\Genre=#Empty$
            If regex_genre
              If ExamineRegularExpression(regex_genre, LigneFichier)
                If NextRegularExpressionMatch(regex_genre)
                  Select RegularExpressionMatchString(regex_genre)
                    Case "/live/"   : Chaines()\Genre = #live   : LIVE+1
                    Case "/movie/"  : Chaines()\Genre = #films  : FILMS+1
                    Case "/series/" : Chaines()\Genre = #series : SERIES+1
                      If regex_serie
                        If ExamineRegularExpression(regex_serie, Chaines()\Nom)
                          If NextRegularExpressionMatch(regex_serie)
                            Serie = ReplaceString(Chaines()\Nom, RegularExpressionMatchString(regex_serie), #Null$)
                            Serie = Trim(Serie)
                            Chaines()\Serie=Serie
                          EndIf
                        EndIf
                      EndIf
                    Default : Chaines()\Genre = #live : LIVE+1
                  EndSelect
                EndIf
              EndIf
            EndIf
            If Chaines()\Genre = #Empty$
              Chaines()\Genre  = #live : LIVE+1
            EndIf
            With Chaines()
              \UrlVideo=LigneFichier
              If \Nom = #inconnu
                \Nom = \Genre+"::"+RSet(Str(NoLigneFichier),6,"0")
                Debug \Nom
                Debug \URLVideo
              EndIf
            EndWith
            With Chaines()
              \UrlVideo=LigneFichier
              ; Positionner afficher=#True uniquement sur des petites playlists
              Define afficher=#False
              If afficher
                Debug RSet("",80,"-")+#CRLF$
                Debug "Index : "     +\Index+#CRLF$+
                      "Nom : "       +\Nom+#CRLF$+
                      "Genre : "     +\Genre+#CRLF$+
                      "Série : "     +\Serie+#CRLF$+
                      "Groupe : "    +\Groupe+#CRLF$+
                      "Langue : "    +\Langue+#CRLF$+
                      "TVGId : "     +\TVGId+#CRLF$+
                      "TVGName : "   +\TVGName+#CRLF$+
                      "TVGLogo : "   +\TVGLogo+#CRLF$+
                      "Url vidéo : " +\UrlVideo+#CRLF$
              EndIf
            EndWith
            LigneDonneeOk=#False
          Else
            Debug "Ligne n° "+NoLigneFichier+" : Mauvais format de ligne, #EXTINF attendu !"
            Debug LigneFichier
          EndIf
      EndSelect
    EndIf
  Wend
  Debug VRAI_CHANNEL
  ClearList(Chaines())
  If IsRegularExpression(regex_nulle)
    FreeRegularExpression(regex_nulle)
  EndIf
  If IsRegularExpression(regex_genre)
    FreeRegularExpression(regex_genre)
  EndIf
  If IsRegularExpression(regex_serie)
    FreeRegularExpression(regex_serie)
  EndIf
  CloseFile(IN)
  Define HeureFin=Date()
  Define text$,W=60
  text$=RSet("",W,"-")+#CRLF$
  text$+"Nombre de lignes du fichier de chaînes traitées : "+Str(NoLigneFichier)+#CRLF$
  text$+"Nombre de lignes du fichier de données traitées : "+Str(NbLignesDonnees)+#CRLF$
  text$+RSet("",W,"-")+#CRLF$
  text$+"Tous les liens      : "+LAST_CHANNEL+#CRLF$
  text$+"Liens valides       : "+VRAI_CHANNEL+#CRLF$
  text$+"Liens non valides   : "+FAUX_CHANNEL+#CRLF$
  text$+RSet("",W,"-")+#CRLF$
  text$+"Nombre de live      : "+LIVE+#CRLF$
  text$+"Nombre de films     : "+FILMS+#CRLF$
  text$+"Nombre de séries    : "+SERIES+#CRLF$
  text$+"Nombre total l+f+s  : "+Str(LIVE+FILMS+SERIES)+#CRLF$
  text$+RSet("",W,"-")+#CRLF$
  text$+"Durée de traitement : "+Str((HeureFin-HeureDebut))+" secondes"+#CRLF$
  text$+RSet("",W,"-")+#CRLF$
  text$+"Terminé. Appuyez sur [Entrée]"
Else
  Debug "Erreur système : "+GetLastError_()
EndIf
OpenConsole()
PrintN(text$)
Input()
CloseConsole()
End
; Ressources
;https://fr.wikipedia.org/wiki/M3U
;https://docs.fileformat.com/fr/audio/m3u/
;https://ss-iptv.com/fr/users/documents/m3u
Reste encore a l'améliorer et certainement a l'optimiser.
Des idées ?
cage
Dernière modification par cage le dim. 27/août/2023 1:03, modifié 2 fois.
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

Re: Demande d'aide avec la lecture de fichier JSON

Message par cage »

Bonjour,

Je viens de mettre mon code dans le post précédent.
cage
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
boddhi
Messages : 604
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Demande d'aide avec la lecture de fichier JSON

Message par boddhi »

Salut,

Le code de ton projet avance bien :wink:
Pertinent le recours aux expressions régulières pour gérer les types de données selon les fichiers.

Peut-être l'as-tu déjà fait et en rapport avec nos précédents échanges, il te reste maintenant à implémenter l'alimentation de ta BDD dans ta boucle de lecture des données.
Répondre