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

Langage Java Discussion :

PostGresql, BLOB, Input/OutputStream, setBinaryStream


Sujet :

Langage Java

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Points : 25
    Points
    25
    Par défaut PostGresql, BLOB, Input/OutputStream, setBinaryStream
    Bonjour à tous!

    Dans le cadre d'un projet personnel, je me tape la tête sur un problème
    que je n'arrive pas à résoudre.

    Mon but est d'insérer un .wav dans une colonne bytearea d'une table Postgresql,
    et l'opération inverse, à savoir lire le BLOB et l'exporter dans un second fichier .wav...
    Le problème est que la taille de mon fichier bis est quasiment le double, et j'ai beau chercher, je ne trouve pas pourquoi, j'ai la vague intuition que le problème vient de l'insertion en base...

    le code de l'insertion
    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
     
     statement.execute("TRUNCATE TABLE musique");
     
                //Preparation du champ data
                File fichier = new File("test.wav");
                System.out.println("Taille fichier: " + fichier.length());
                InputStream in = new FileInputStream(fichier);
     
                //Insertion dans la base
                ps = connection.prepareStatement("INSERT INTO musique (title,id_album,tracknumber,id_artist,id_genre,date,data) VALUES (?,?,?,?,?,?,?)");
                ps.setString(1, "Premier titre");   // title
                ps.setInt(2, 1);            // id_album
                ps.setInt(3, 1);            // tracknumber
                ps.setInt(4, 1);            // id_artist
                ps.setInt(5, 1);            // id_genre
                ps.setTimestamp(6, null);   // date            
                //ps.setBlob(7, in, (int) fichier.length());    //marche pas avec jdbc>3.0
                ps.setBinaryStream(7, in, (int) fichier.length());
                ps.execute();
     
                ps.close();
                in.close();
                rs.close();
                statement.close();
                connection.close();
    et celui du Select et export:
    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
     
                String titre = "Premier titre";
                resultset = statement.executeQuery("SELECT title, data FROM musique WHERE title = '" + titre + "' LIMIT 1");
                resultset.next();
    //            System.out.println("Les lignes dans la base: ");
    //            System.out.println("   TITLE = " + resultset.getString("title"));
    //            System.out.println("   DATA = " + new String(resultset.getBytes("data"), 0, 32));
     
     
                InputStream in = resultset.getBinaryStream("data");
                File fichier_sortie = new File("testrecup.wav");
                OutputStream out = new FileOutputStream(fichier_sortie);
     
                //Premier essai
                byte buffer[] = new byte[512 * 1024];
                int nbLecture;
                while ((nbLecture = in.read(buffer)) != -1) {
                    out.write(buffer, 0, nbLecture);
                }
                System.out.println("Taille fichier sortie: " + fichier_sortie.length());
     
                out.flush();
                out.close();
                in.close();
                resultset.close();
                statement.close();
                connection.close();
    et la sortie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    run:
    TEST
    Titre: Premier titre
    Taille fichier: 50168204
    Taille fichier sortie: 100336407
    BUILD SUCCESSFUL (total time: 8 seconds)

    Est-ce quelqu'un voit quelque chose qui cloche?
    D'avance merci

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Points : 25
    Points
    25
    Par défaut
    Je continue mes investigations en testant ce petit bout de code, qui shunte toute la partie Postgresql:
    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
     //Preparation du champ data
                File fichier = new File("test.wav");
                System.out.println("Taille fichier original: " + fichier.length());
                InputStream in = new FileInputStream(fichier);         
     
                //test pour copier dans la foulée le fichier
                File fichier_sortie = new File("testdirectcopie.wav");
                OutputStream out = new FileOutputStream(fichier_sortie);
                byte buffer[] = new byte[512 * 1024];
                int nbLecture;
                while ((nbLecture = in.read(buffer)) != -1) {
                    out.write(buffer, 0, nbLecture);
                }
                System.out.println("Taille fichier copie directe: " + fichier_sortie.length());
                //fin test
    Ce bout de code ne fait finalement que copier le contenu d'un fichier vers un autre. Les deux fichiers sont identiques... me voilà bien avancé, je viens de recoder un copier/coller, formidable non?

    Mes soupçons se tournent maintenant vers les méthodes d'insertion en base:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
         //ps.setBlob(7, in);    //marche pas avec jdbc>3.0
         //ps.setBlob(7, in, (int) fichier.length());    //marche pas avec jdbc>3.0
         //ps.setBinaryStream(7, in, (long) fichier.length());   //marche pas avec jdbc>3.0
         ps.setBinaryStream(7, in, (int) fichier.length());
    que je ne dois pas vraiment maitriser, à moins qu'il n'y ait une histoire de format de données, mais là, je commence à secher

    Allez, j'y retourne, un peu de soutien me ferait du bien quand même

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Points : 25
    Points
    25
    Par défaut
    Bon, pas grand monde pour m'aider sur le coup

    M'enfin,
    J'ai partiellement réussi en suivant la doc de JDBC PostGreSQL concernant les OIDs donc en utilisant un champ OID en lieu et place d'un champ bytea, avec des méthodes et étapes supplémentaires par rapport à celle présentée ci- dessus... donc des performances que j'estime moindre (enfin ca filoche quand même très correctement)
    La chose est qu'un bytea est sensé accepter sans broncher des données jusqu'à
    1Go, que mes données sont loin de dépasser actuellement.

    Donc problème pas vraiment encore résolu...

  4. #4
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 084
    Points
    7 084
    Par défaut
    Je te conseillerai d'appeler l'aide de la communauté PostGres, la gestion des BLOBs est une problèmatique assez générale.

    J'ai eu pas mal de problèmes sous Oracle, as tu essayé avec la méthode java.sql.PreparedStatement.setBytes(int, byte[]) ?

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Points : 25
    Points
    25
    Par défaut
    Merci de ta réponse Nemek

    Après cette judicieuse remarque, je me suis empressé de faire
    le test avec un ps.setBytes... et... idem, la taille de mon fichier de
    sortie est toujours le double (-1 octet en réalité) de mon fichier en
    entrée... je ne vois plus trop le pourquoi et le comment...

    Sans indiscrétion Nemek, quels ont été tes problèmes avec Oracle
    et des BLOBs?

  6. #6
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 084
    Points
    7 084
    Par défaut
    Aucune indiscrétion à parler de mes problèmes d'érec... euh Oracle je veux dire :p

    Pour manipuler une colonne typé BLOB, il faut ne traiter que cette colonne ... Exemple : pour insérer un enregistrement avec un BLOB, il faut d'abord insérer l'enregistrement avec toutes les valeurs sauf le(s) BLOB(s) et ensuite mettre à jour l'enregistrement pour y placer le BLOB.

    J'ai essayé différentes méthodes sur le PreparedStatement et c'est la seule qui a fonctionné. La seule que je n'ai pas testée, c'est instancier un objet spécifique à Oracle et la méthode setObject.

    Est-ce qu'il n'y aurait pas un bug connu avec tes drivers JDBC pour Postgres concerne le traitement des BLOBs ?

    As-tu regarder ce que tu insérais en base de données sans passer par JDBC ?

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Points : 25
    Points
    25
    Par défaut
    Je vais essayer ta solution en deux temps en ce qui concerne l'insertion en base, ça devrait être assez rapide à tester d'ailleurs...

    Sinon, je ne pense pas qu'il y ait un bug avec ma version de jdbc, je me suis servi du lien suivant pour mes tests, j'imagine qui si bug il y avait, ils auraient été les premiers à en parler, non?
    http://jdbc.postgresql.org/documenta...nary-data.html
    Je vais d'ailleurs reprendre à l'identique les deux exemples de cette même page pour me rassurer... et puis je me tournerais vers le forum PostGres

    Sinon qu'entends tu par insérer en base sans passer par jdbc? Via une requête SQL?

  8. #8
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 084
    Points
    7 084
    Par défaut
    Je ne disais pas d'insérer sans passer par JDBC mais de vérifier ce que tu as inséré via un autre logiciel.
    Par exemple:

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Points : 25
    Points
    25
    Par défaut
    Bien sûr j'ai pgAdmin pour regarder tout çà
    Seulement, dans mon champ data, il me met un message
    du genre <données binaires...> et pas moyen de voir la "taille"
    de cette case via pgAdmin (ou pas trouvé en fait)

  10. #10
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 084
    Points
    7 084
    Par défaut
    Tu peux pas télécharger le contenu dans un fichier ?

    Sinon utilise la fonction lo_export(oid, path)

Discussions similaires

  1. Réponses: 4
    Dernier message: 12/01/2012, 16h26
  2. [PHP 5.3] Stream, BLOBs et Postgresql
    Par atsig dans le forum Langage
    Réponses: 1
    Dernier message: 23/06/2011, 14h30
  3. Ecriture d'un blob dans une base postgresql
    Par isoman dans le forum Hibernate
    Réponses: 2
    Dernier message: 06/02/2009, 12h24
  4. Insérer un BLOB avec setBinaryStream()
    Par plutonium719 dans le forum Oracle
    Réponses: 0
    Dernier message: 04/12/2007, 17h35
  5. [Blob] PostGreSQL Beta4 pour Windows
    Par YanK dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 09/10/2003, 11h46

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