IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

comportement inattendu de la classe BufferedOutputStream


Sujet :

Entrée/Sortie Java

  1. #1
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut comportement inattendu de la classe BufferedOutputStream
    Bonsoir tout le monde,
    je développe une petite application de transfert de fichiers en utilisant TCP.
    voici le code du serveur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    package tcp.ftp;
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
     
    public class FTPServer {
     
        public static void main(String[] args) {
            new FTPServer().go();
        }
     
        void go() {
            try {
                ServerSocket server = new ServerSocket(2015);
                System.out.println("server is running ....!");
                while (true) {
                    Socket socket = server.accept();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String file = reader.readLine();
                    System.out.println("file to be downloaded is : " + file);
                    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                    BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
                    while (true) {
                        int octet = bis.read();
                        if (octet == -1) {
                            break;
                        }
                        bos.write(octet);
     
                    }
                    bos.flush();
                    //bos.close();
     
                }
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
     
    }
    ce code envoie une partie de fichier et non pas le fichier complet au client. noter que j'ai utilisé flush() pour vider le buffer. Mais quand je remplace flush() par close(), ce code envoie le fichier au complet sans aucune perte. ce comportement me parait bizarre n'est ce pas!. une autre remarque: je peux utiliser ce code, sans socket, pour copier un fichier avec succès (sans close() et seulement avec flush() à la fin).

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Hello,

    C'est effectivement surprenant. BufferedOutputStream fait bel et bien son job et transmet bel et bien le fichier entier. De son côté, le OutputStream de la socket a bel et bien reçu l'ordre et délègue comme il peut la demande à l'OS d'envoyer les données.

    Voici ce que je pense qu'il se passe : en fait, le fichier a bel et bien été envoyé en entier, avec ce code. Mais de l'autre côté, il se pourrait bien qu'il ne soit pas reçu en entier, notamment du fait que la socket n'a pas été fermée proprement, et que l'autre côté ne sait pas comment réagir face à ça, et ne termine pas ses propres actions proprement.

    Il est courant (sans surprise) dans les échanges réseau, de s'attendre à ce que la socket soit fermée proprement et de considérer que la communication a été corrompue si ce n'est pas le cas.
    Donc il faut toujouts utiliser close() à la fin. Le flush() n'est utile que si on veut envoyer des informations maintenant mais qu'on voudra aussi en envoyer encore plus tard.


    Citation Envoyé par win_ubuntu Voir le message
    ce code envoie une partie de fichier et non pas le fichier complet au client. noter que j'ai utilisé flush() pour vider le buffer. Mais quand je remplace flush() par close(), ce code envoie le fichier au complet sans aucune perte. ce comportement me parait bizarre n'est ce pas!. une autre remarque: je peux utiliser ce code, sans socket, pour copier un fichier avec succès (sans close() et seulement avec flush() à la fin).
    Ce n'est pas surprenant, du fait de l'usage courant avec les fichiers de chercher à enregistrer sur le disque, maintenant, ce qu'on a transmis au système de fichier, dans le but de ne pas perdre l'information si l'ordinateur plante et que le fichier n'a pas été fermé.
    Il reste que close() n'est pas là pour faire joli et qu'il faut l'appeler. Ne serait-ce que parce que d'habitude on tient à libérer les ressources. Si ton programme est sur le point de se terminer et les ressources ne t'intéressent plus et si cette ressource est un fichier sur lequel tu as fait flush(), la plupart des systèmes vont s'arranger pour que ça marche. Il n'empêche que ça ne sert à rien de savoir ça : il est plus malin d'appeler close(), toujours, sans exception. Là il n'y a pas de si : ça marche et c'est tout.

    Pour garantir l'appel de close(), ceci aurait pu être fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    try(ServerSocket server = new ServerSocket(2015)) {
                System.out.println("server is running ....!");
                while (true) {
                    try(Socket socket = server.accept()) {
                      BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                      String file = reader.readLine();
                      System.out.println("file to be downloaded is : " + file);
     
                      try(
                          InputStream fis = new FileInputStream(file);
                          BufferedInputStream bis = new BufferedInputStream(fis);
                          BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream())
                      ) {
                        while (true) {
                          int octet = bis.read();
                          if (octet == -1) {
                            break;
                          }
                          bos.write(octet);
                        }
                      }
                    }
                }
    }
    Là ce sont les try() qui s'occupent de fermer tout ce qu'il faut, donc tout va bien, ça se fera.


    Remarques annexes :
    - Pour améliorer les performances, ce n'est pas tout d'utiliser "une classe qui buffeurise", il faudrait peut-être traiter les octets par lots au lieu de un par un.
    - Ce code de copie de fichier peut être fait bien plus simplement avec copy() de la classe Files de Java 1.7.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    Merci infiniment pour la réponse,
    j'ai mis de coté l'utilisation de l'instruction try-with-resources pour comprendre les effets de ne pas fermer les flux. pour moi, on doit fermer les flux et les sockets juste pour libérer les ressources. noter bien aussi, qu'il suffit de fermer le flux de BufferedOutputStream (sans fermer la socket) pour que client reçoit au complet le fichier envoyé par le serveur. puisque, l'invocation de la méthode close () de BufferedOutputStream ne ferme pas automatiquement la socket. mais l'inverse est toujours vrai: fermer la socket a pour conséquence la fermeture automatique des flux sous-jacents.

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Euh, si fermer le BufferedOutputStream ne ferme pas la socket, c'est un bug dans ces classes.

    La doc dit clairement :
    - que close() sur n'importe quel OutputStream doit effectuer la clôture et libération des ressources sous-jacentes, donc pour un BufferedOutputStream un appel à close() du OutputStream sous-jacent.
    - que close() sur l'un des streams d'une Socket, ferme les deux streams et la socket. On peut raisonnablement se demander quel autre effet ça pourrait bien avoir sinon.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par win_ubuntu Voir le message
    ce code envoie une partie de fichier et non pas le fichier complet au client. noter que j'ai utilisé flush() pour vider le buffer. Mais quand je remplace flush() par close(), ce code envoie le fichier au complet sans aucune perte. ce comportement me parait bizarre n'est ce pas!. une autre remarque: je peux utiliser ce code, sans socket, pour copier un fichier avec succès (sans close() et seulement avec flush() à la fin).
    Même si java vide ses buffers avec cette commande, ce n'est pas le cas de l'OS. La couche réseau TCP/IP travaille par paquet. Comme les applis écrivent souvent par petit bout dans les flux, pour éviter la surcharge réseau (ça prends la place mine de rien les entête TCP/IP), l'OS regroupe tout ça dans un seul paquet de 1 ou 2k en général. Le flush d'un flux socket n'a aucune influence là dessus (le flush du SocketOutputStream est vide comme tu peux le voir ici).
    Ceci dit, au bout de moins d'une seconde, ce buffer devrait s'être vidé de lui même.

    Par contre, du coté de récepteur du fichier, si tu as mal codé, ça pourrait attendre des plombes.... Je vois par exemple que ton serveur ne précise pas d'avance la taille du fichier au client donc, même avec un flush, comment le client est supposé savoir que le fichier est terminé?

  6. #6
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Même si java vide ses buffers avec cette commande, ce n'est pas le cas de l'OS. La couche réseau TCP/IP travaille par paquet. Comme les applis écrivent souvent par petit bout dans les flux, pour éviter la surcharge réseau (ça prends la place mine de rien les entête TCP/IP), l'OS regroupe tout ça dans un seul paquet de 1 ou 2k en général. Le flush d'un flux socket n'a aucune influence là dessus (le flush du SocketOutputStream est vide comme tu peux le voir ici).
    Ceci dit, au bout de moins d'une seconde, ce buffer devrait s'être vidé de lui même.

    Par contre, du coté de récepteur du fichier, si tu as mal codé, ça pourrait attendre des plombes.... Je vois par exemple que ton serveur ne précise pas d'avance la taille du fichier au client donc, même avec un flush, comment le client est supposé savoir que le fichier est terminé?
    je pense que le serveur n'a pas besoin d'envoyer la taille du fichier au client. le serveur doit seulement fermer les flux. dans mon cas:
    le client doit tester si fin de flux est arrivé (-1) c'est tout.
    voici mon code de client qui télécharge correctement n'importe quel fichier sans besoin de savoir au préalable la taille du fichier (à condition que le serveur ferme le flux (ou la socket) associé à ce client):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    package tcp.ftp;
     
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
     
    /**
     *
     * @author 
     */
    public class FTPClient {
     
        public static void main(String[] args) {
            String file = "JasperReports-Ultimate-Guide-3.pdf";
            try {
                InetAddress address = InetAddress.getLocalHost();
                Socket socket = new Socket(address, 2015);
                System.out.println("connection successfully established ....!");
                PrintWriter pw = new PrintWriter(socket.getOutputStream());
                pw.println(file);
                pw.flush();
                BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy" + file));
                while (true) {
                    int octet = bis.read();
                    if (octet == -1) {
                        break;
                    }
                    bos.write(octet);
                }
                bos.flush();
                System.out.println("file download is complete ...!");
     
            } catch (UnknownHostException ex) {
                System.out.println(ex.getMessage());
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
    }

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par win_ubuntu Voir le message
    je pense que le serveur n'a pas besoin d'envoyer la taille du fichier au client. le serveur doit seulement fermer les flux.
    Ben dans ton premier message tu te plaignais que tu avais besoin de fermer le flux , faut savoir

  8. #8
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Ben dans ton premier message tu te plaignais que tu avais besoin de fermer le flux , faut savoir
    pour moi, j'avais cru que flush() fait l'affaire. c'est à dire envoie les éventuels octets restés dans le buffer dans le flux associé à la socket. parmi eux l'octet qui représente la fin du fichier (-1). Apparemment, la fermeture des flux joue un rôle double:
    • vider le buffer.
    • libérer les ressources.

    donc, dans ce cas, on peut se passer de la méthode flush().

  9. #9
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    y a pas d'octet -1 qui soit jamais envoyé dans le flux. -1 c'est juste un chiffre que te retourne Inputstream pour te dire 'y a plus rien la socket est fermée.

  10. #10
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    y a pas d'octet -1 qui soit jamais envoyé dans le flux. -1 c'est juste un chiffre que te retourne Inputstream pour te dire 'y a plus rien la socket est fermée.
    vous êtes sûr, rien ne dit sur çà dans la doc. et si le flux est associé à fichier, comment peut on savoir que la fin du fichier est arrivé? exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    static void fastCopy(String source, String destination) {
     
            try {
                FileInputStream fis = new FileInputStream(source);
                BufferedInputStream bis = new BufferedInputStream(fis);
                FileOutputStream fos = new FileOutputStream(destination);
                BufferedOutputStream bos = new BufferedOutputStream(fos);
                while (true) {
                    int octet = bis.read();
                    if (octet == -1) {
                        break;
                    }
                    bos.write(octet);
                }
               bos.flush();
     
            } catch (FileNotFoundException ex) {
                System.out.println(ex.getMessage());
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
    pas de fermeture des flux ici. cette méthode copie un fichier correctement, et le programme se termine normalement.

  11. #11
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par win_ubuntu Voir le message
    vous êtes sûr, rien ne dit sur çà dans la doc.
    If no byte is available because the end of the stream has been reached, the value -1 is returned.
    Ca me semble clair non, le -1 c'est quand on est arrivé à la fin du stream. Autrement dit y a plus rien après et y aura jamais rien après. Dans un socket ça ne peut se produire que si on la ferme. Et c'est même pas garanti d'aillerus. Si il y a un problème réseau, le packet RST peut ne jamais arriver et le client poireaute comme une con pendant des heures.

    et si le flux est associé à fichier, comment peut on savoir que la fin du fichier est arrivé?
    Parce que le ficher a une taille précise et que au bout, c'est au bout. Y a pas de "marqueur" à la fin qui serait magique et stocké dans le fichier. Le bout, c'est quand on a atteints la taille du fichier. Du coup FileInputStream te renvoie -1 sur le read pour te faire comprendre que c'est cuit y a plus rien à lire là.
    pas de fermeture des flux ici. cette méthode copie un fichier correctement, et le programme se termine normalement.
    Tu arrive bien au bout de ton Inputstream, ce qui n'est pas le cas avec ta socket puisque tu ne l'a pas fermée.

    Bref le "-1" n'est pas dans le fichier (d'ailleurs ça rentre pas dans une octet), il n'est pas écrit dans la socket et le flush ne marque jamais une fin de flux et n'écrit pas -1 dans le flux.

  12. #12
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    Salut,
    je trouve votre explication est très logique pour moi. néanmoins, je me pose quelques questions.

    If no byte is available because the end of the stream has been reached, the value -1 is returned.
    çà ne garantie pas que la classe utilise la taille du fichier pour détecter "fin du flux" . et on même temps n'exclut pas que la classe utilise un caractère 'EOF'. le comment est imprécise. je ne sais pas est ce que les systèmes d'exploitation utilise un tel caractère pour marquer la fin du fichier.

    (d'ailleurs ça rentre pas dans une octet)
    . que voulez vous dire par çà? on peut pas représenter -1 avec un seul octet?.

  13. #13
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par win_ubuntu Voir le message
    çà ne garantie pas que la classe utilise la taille du fichier pour détecter "fin du flux" .
    Ma foi, je suppose que ça ne garantit pas qu'on fait comme ça, non... Mais on peut raisonnablement se demander par quel autre moyen elle pourrait bien s'y prendre.

    Citation Envoyé par win_ubuntu Voir le message
    et on même temps n'exclut pas que la classe utilise un caractère 'EOF'.
    Ben si. Il se passe quoi si ton fichier contient un caractère EOF ? On s'arrête en plein milieu ? Ça va pas être possible...

    Citation Envoyé par win_ubuntu Voir le message
    je ne sais pas est ce que les systèmes d'exploitation utilise un tel caractère pour marquer la fin du fichier.
    Je suppose que ça a pu exister à une époque, mais de nos jours ça ne va pas le faire, pour la même raison.

    Citation Envoyé par win_ubuntu Voir le message
    . que voulez vous dire par çà? on peut pas représenter -1 avec un seul octet?.
    C'est vrai que je l'aurais pas dit comme ça -_-°.
    read() renvoie les octets sous forme de valeurs de 0 à 255, ce qui nous fait 256 valeurs différentes, autant qu'un octet peut en avoir.
    Et aucune de ces valeurs n'est -1. Donc aucun octet du fichier ne pourrait être envoyé sous forme -1, et il n'y a plus de place dans un octet pour ajouter cette possibilité, les 256 valeurs possibles sont déjà prises.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  14. #14
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par win_ubuntu Voir le message
    . que voulez vous dire par çà? on peut pas représenter -1 avec un seul octet?.
    Je vais me corriger:

    "ca ne rentre pas dans un octet non signé", puisque c'est ce que renvoie read. Et comme les octet non signés ca existe pas en java, ils en ont rajouté une couche en le transformant en int et en utilisant l'espace ainsi gangé pour mettre des caractères spéciaux d'indication qui ne viennent pas du fichier.


    Pour le EOF, même si l'os utilisait ça, l'inputstream ne le verrait pas. Il se content d'utiliser derrière l'api système et d'utiliser les protocoles liés à l'OS pour savoir si la fin du flux est atteinte. Bref, tu n'a pas à savoir comment c'est fait, mais il n'y a en java pas de caractre spécial dans une flux pour marquer sa fin, et le -1 ne viens pas du flux.

  15. #15
    Membre habitué
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2010
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2010
    Messages : 212
    Points : 184
    Points
    184
    Par défaut
    je vous remercie infiniment les gars. les choses sont claires maintenant.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 27/12/2010, 11h27
  2. Comportement général d'une classe
    Par palmier dans le forum ActionScript 1 & ActionScript 2
    Réponses: 6
    Dernier message: 04/02/2008, 11h12
  3. [XSLT]Problème de comportement inattendu
    Par kalimatchoum dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 06/03/2007, 18h33
  4. [PL/SQL][Oracle9] Proc. Stoc. comportement inattendue
    Par Carlito_superheros dans le forum Oracle
    Réponses: 2
    Dernier message: 30/08/2006, 16h13
  5. Comportement inattendu de Firefox
    Par reggae dans le forum Firefox
    Réponses: 3
    Dernier message: 08/05/2006, 21h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo