WOW !! MUCH LOVE ! SO WORLD PEACE !
Fond bitcoin pour l'amélioration du site: 1memzGeKS7CB3ECNkzSn2qHwxU6NZoJ8o
  Dogecoin (tips/pourboires): DCLoo9Dd4qECqpMLurdgGnaoqbftj16Nvp


Home | Publier un mémoire | Une page au hasard

 > 

Badora


par Stéphane Clerc
UPMF - Grenoble - IUT II 2003
  

précédent sommaire suivant

Bitcoin is a swarm of cyber hornets serving the goddess of wisdom, feeding on the fire of truth, exponentially growing ever smarter, faster, and stronger behind a wall of encrypted energy

3.2) Transfert et organisation de la nouvelle base de données :

a) Programme de transfert en C :

Pour pouvoir utiliser la base de données avec le programme qui allait être réalisé en Java, il fallait tout d'abord trouver une nouvelle forme d'organisation de la base et la transférer car la librairie C-Isam qui permettait de la gérer jusqu'à maintenant ne peut être accéder qu'avec le langage C. Afin d'effectuer ce transfert deux solutions ont été examinées et après une étude approfondie c'est la deuxième qui a finalement été choisie ce qui est expliqué ciaprès.

La première solution envisagée fut d'utiliser JNI (Java Native Interface) pour effectuer ce transfert. Le package JNI de Java permet de coupler du code Java et du code C ou C++ en respectant cinq étapes de programmation :

- codage de la partie du programme en Java (classes .java) : déclarations des méthodes natives et compilation avec l'exécutable "javac".

- génération d'un fichier *.h grâce à l'exécutable "javah" qui crée l'en-tête du fichier C de manière automatique.

- codage de la partie C : implémentation des méthodes natives

- génération d'une librairie (*.so sous un environnement UNIX et *.dll sous Windows) qui contient les fichiers *.h et *.c

- exécution du programme avec la commande "java"

Ainsi il était possible de réutiliser les fonctions déjà écrites en C pour consulter la base et récupérer les données avec un programme Java qui se chargerait de les organiser d'une nouvelle façon. Puis après étude de cette solution et quelques essais, il s'est avéré que les possibilités de ce système étaient assez restreintes et qu'il était difficile de la mettre en place.

C'est pourquoi une deuxième solution pour transférer la base de données a été envisagée : le plus simple était de passer par un fichier intermédiaire entre un programme C et un programme Java. Ainsi un premier programme en C a été réalisé pour lire l'ensemble des données stockées dans la base et les écrire dans un fichier texte qui pourrait donc être relu de

n'importe quelle manière. Quatre fichiers textes ont donc été construits par ce programme et représentent les 4 années de données. Ces fichiers étaient seulement destinés à être relus une fois par un autre programme en Java qui lui se chargerait de les organiser autrement.

Le programme de transfert en Java lit donc chaque fichier texte de façon séquentielle et ordonne les données dans un fichier binaire. On aurait pu conserver les fichiers textes obtenus à la suite de l'exécution du programme de transfert en C, cependant ces fichiers sont très volumineux puisqu'ils font chacun entre 200 et 300 Mo. Cela rendrait les recherches très longues puisque l'accès à un fichier texte ne peut se faire que de manière séquentielle. Il fallait alors trouver une autre façon de stocker les données qui seraient exploitées par le programme de visualisation en Java. Examiné

Après le transfert des données dans un fichier texte intermédiaire, il a fallu trouver un moyen de stocker et de structurer ces données qui seront utilisées par le programme en Java.

b) Nouvelle organisation de la base :

Afin d'organiser la nouvelle base de données plusieurs méthodes ont été considérées. La première qui est présentée ici est la sérialisation. Après quelques tests cette solution n'a finalement pas été retenue au profit de la deuxième méthode examinée détaillée ensuite.


· Etude d'une méthode : la sérialisation :

Etant donné que Java est un langage orienté objet et permet donc d'exploiter pleinement les avantages d'une structure avec des classes et des objets, le plus simple était de relire chaque fichier texte et de construire des objets à partir de ces données. Les objets seraient ensuite enregistrés dans un fichier et pourraient être réutilisés ultérieurement.

Pour réaliser ceci Java propose la sérialisation d'objets. L'interface "Serializable" permet de stocker des objets dans un fichier qui sont accédés séquentiellement. Quand on sérialise un objet dans un fichier, toutes ses dépendances et les objets avec lesquels il a des liens sont également sérialisés. C'est pourquoi il était intéressant de créer une classe "Base" qui regrouperait l'ensemble des objets de la base de données et cet objet "Base" serait seul sérialisé dans un fichier. Alors tous les autres objets seraient également enregistrés dans le fichier et pourraient être retrouvés par la suite.

Tableau de comparaison avantages / inconvénients pour la sérialisation :

Avantages

Inconvénients

Permet la persistance des objets et des liens entre objets de manière très simple.

Très long si l'on a beaucoup d'objets ou des objets de grande taille.

Format indépendant du système d'exploitation, donc possibilité d'utiliser les objets avec d'autres systèmes par la suite.

 

Système applicable à tous les objets.

 

Enregistre tous les objets référencés par l'objet sérialisé.

 
 

Cependant il existe un énorme inconvénient à cette méthode : puisque la base de données est d'une taille très importante, l'objet "Base" aurait fait plusieurs centaines de Mo également et il fallait plusieurs heures pour le sérialiser ou le désérialiser, car en effet on est obligé de lire (désérialiser) l'objet en une seule fois et avec tous les objets qui en dépendent. La sérialisation est donc très utile et très pratique dans certains cas, en particulier quand on ne possède pas d'importants objets à mémoriser mais pour ce projet elle n'était pas du tout envisageable.


· Choix d'une autre méthode :

Les autres méthodes pour stocker des données dans des fichiers en Java sont les fichiers textes et les fichiers binaires à accès séquentiel, ce qui aurait été beaucoup trop long ici. Il restait donc une solution qui est l'utilisation de fichiers binaires à accès direct ("RandomAccessFile" pour Java). La classe RandomAccessFile permet de créer et de lire des fichiers binaires à accès direct grâce à la fonction "seek" qui place le "pointeur du fichier" où l'on veut dans le fichier.

Cependant il faut indiquer à cette fonction à quel octet on veut aller dans le fichier et non pas en lui indiquant une clé comme dans les fichiers indexés. Cela implique de connaître l'endroit exact où est stockée une donnée si on veut la retrouver. Le programme Java servant au transfert de la base construit un fichier binaire pour les données de chaque année (donc 4 saisons) et organise les données de manière ordonnée. Ainsi il relit les données dans le fichier texte de manière chronologique et les retranscrit dans le fichier binaire de la façon suivante (Figure 6) :

Enregistrements

Champs

Total

Evénement1

jd md ad hd mind sd jf mf af hf minf sf nbim

15 octets

Image1

j m a h min s seco site reso nbrad ppirhi

19 octets

Radiale1 1

azi site p1 p2 p3 p4 ... p512

520 octets

Radiale12

azi site p1 p2 p3 p4 ... p512

520 octets

...

...

...

Radiale1Max

azi site p1 p2 p3 p4 ... p512

520 octets

Image2

j m a h min s seco site reso nbrad ppirhi

19 octets

Radiale21

azi site p1 p2 p3 p4 ... p512

520 octets

...

...

...

Evénement2

jd md ad hd mind sd jf mf af hf minf sf nbim

15 octets

...

...

...

 

Figure 6 : Structure du fichier binaire

Les enregistrements et les champs sont les suivants : Evénement :

Champs :

- jd : jour de la date de début de l'événement (byte : 1 octet)

- md : mois de début (byte : 1 octet)

- ad : année de début (short : 2 octets) - hd : heure de début (byte : 1 octet) - mind : minute de début (1 octet) - sd : seconde de début (1 octet)

- jf : jour de la date de fin de l'événement (byte : 1 octet)

- mf : mois de fin (1 octet)

- af : année de fin (short : 2 octets) - hf : heure de fin (byte : 1 octet)

- minf : minute de fin (byte : 1 octet) - sf : seconde de fin (byte : 1 octet)

- nbim : nombre d'images composant l'événement (byte : 1 octet) -

Taille totale : 15 octets

Image :

Champs .
·

- j : jour de la date de l'image (byte : 1 octet)

- m : mois (byte : 1 octet)

- a : année (short : 2 octets) - h : heure (byte : 1 octet)

- min : minute (byte : 1 octet) - s : seconde (byte : 1 octet)

- seco : secteur couvert (2) (float : 4 octets)

- site : site (1) (float : 4 octets)

- reso : résolution de l'image (byte : 1 octet)

- nbrad : nombre de radiales composant l'image (short : 2 octets)

- ppirhi : indique si l'image est PPI ou RHI (1) (byte : 1 octet)

Taille totale : 19 octets

Radiale :

Champs .
·

- azi : azimut (1) de la radiale (float : 4 octets)

- site : site (float : 4 octets)

- p1, p2... p512 : portes composant la radiale (512 portes par radiale) : valeur en DBz (1) (byte : 1 octet)

Taille totale : 520 octets

(1) Cf. définition dans le Glossaire page 33

Pour réduire le plus possible la taille des fichiers binaires il fallait bien choisir les types de chaque donnée pour que de la place ne soit pas gaspillée. Les différents types primitifs proposés par Java sont les suivants (Figure 7) :

Primitive

Signification

Taille

Valeurs acceptées

char

Caractère

2 octets

Valeur du jeu de caractères Unicode (65 000 caractères possibles).

byte

Entier très court

1 octet

-128 à 127

short

Entier court

2 octets

-32768 à 32767

int

Entier

4 octets

-2 147 483 648 à 2 147 483 647

long

Entier long

8 octets

-9223372036854775808 à 9223372036854775807

float

Flottant (réel)

4 octets

-1.4* 1 0-45 à 3.4* 1038

double

Flottant double

8 octets

4.9* 10-324 à 1.7* 1 0308

boolean

Booléen

1 octet

0 ou 1 (en réalité, toute autre valeur que 0 est considérée égale à 1)

 

Figure 7 : Types primitifs en Java

Etant donné que la plupart des valeurs des données que l'on a à stocker sont inférieures à 256 du fait de la conversion des données depuis le système SANAGA (où elles étaient sur 8 bits), il était préférable de privilégier l'utilisation du type byte pour réduire la taille du fichier. Ainsi toutes les petites valeurs ne dépassant pas 127 ont été enregistrées comme des bytes. Le problème était que la plupart des valeurs stockées dans la base et qui occupent la majeure partie des fichiers sont les valeurs des portes de chaque radiale.

Or la valeur d'une porte peut varier entre 0 et 255, il n'est donc pas possible de la coder sur un byte. Cependant toutes les valeurs négatives n'étaient pas utilisées car une porte ne peut pas avoir une réflectivité négative. C'est pourquoi le système adopté pour coder les valeurs des portes a été d'utiliser des bytes de la manière suivante :

- pour les portes de valeur comprise entre 0 et 127 : codage normal sur un byte.

- pour les portes de valeur comprise entre 128 et 255 : on soustrait 256 à la valeur initiale de façon à obtenir un nombre négatif compris entre -128 et -1. Lors de la relecture du fichier il faut donc rajouter 256 pour avoir la bonne valeur. Ce système permet de gagner de la place en codant toutes les portes sur un byte, la taille des fichiers est alors pratiquement divisée par 2, ce qui était nécessaire pour qu'ils tiennent tous un CD-Rom.

Grâce à cette organisation on connaît la taille de chaque donnée ce qui permet de calculer le nombre d'octets que l'on veut sauter pour accéder à un certain champ. Par exemple, si l'on recherche un événement dans la base pour une date donnée, il faut consulter la date du 1 er événement puis si ce n'est pas celui qu'on recherche, on peut se placer directement au début de l'événement suivant.

Ainsi si l'on recherche un événement pour une date donnée il faut faire la boucle

suivante (1) :

- ouverture du fichier et placement du pointeur en début de fichier (position 0).

(1) Cf. Annexe 3 page 47 pour le détail du code

- lecture du 1er champ du 1er événement (c'est-à-dire le jour).

Si le jour est identique à celui de la date recherchée on lit les autres champs pour voir si c'est le bon événement, si c'est effectivement le bon on récupère les autres données relatives à l'événement, sinon on reprend la boucle de recherche.

- Si le jour est différent on doit se placer au début du prochain événement. Pour cela il faut connaître le nombre d'octets (et donc d'images enregistrées) à sauter. Le champ "nbim" de l'événement nous indique le nombre d'images qui sont enregistrées pour celui-ci (et pour chaque image le champ "nbrad" indique le nombre de radiales enregistré).

- Il faut donc pour accéder à l'événement suivant se placer à l'octet de rang égal à : octet n° = 15 + 19*nbim + 520*nbrad*nbim (sachant que le nombre de radiales nbrad est différent pour chaque image).

L'accès n'est donc pas tout fait direct puisqu'il faut faire un parcours séquentiel pour trouver l'événement recherché. Cependant cet accès est très rapide puisqu'il ne faut consulter qu'un seul champ de l'événement pour savoir si c'est le bon, c'est-à-dire si la date correspond. Il en est exactement de même si l'on recherche une image pour une date donnée.

Maintenant que la banque de données est organisée dans de nouveaux fichiers lisibles par le programme en Java, la suite de la programmation est la réalisation de l'interface graphique du programme.

3.3) Interface graphique : architecture et fonctionnalité

précédent sommaire suivant






Bitcoin is a swarm of cyber hornets serving the goddess of wisdom, feeding on the fire of truth, exponentially growing ever smarter, faster, and stronger behind a wall of encrypted energy








"Il existe une chose plus puissante que toutes les armées du monde, c'est une idée dont l'heure est venue"   Victor Hugo