8
votes

Envoi d'une capture d'écran (bufferedimage) sur une prise en Java

J'envoie une bufferedimage sur une prise et j'utilise l'exemple trouvé dans Ceci post:

expéditeur p> xxx pré>

récepteur p> xxx pré>

Ça fonctionne - si, et seulement si, et seulement si, et seulement si, et seulement si, Je ferme la sortie de l'expéditeur après cette ligne: p>

    InputStream in = clientSocket.getInputStream();
    long startTime = System.currentTimeMillis();

    byte[] b = new byte[30];
    int len = in.read(b);

    int filesize = Integer.parseInt(new String(b).substring(0, len));

    if (filesize > 0)
    {
        byte[] imgBytes = readExactly(in, filesize);
        FileOutputStream f = new FileOutputStream("C:\\Users\\Dan\\Desktop\\Pic\\1.jpg");
        f.write(imgBytes);
        f.close();

        System.out.println("done");


0 commentaires

3 Réponses :


8
votes

Une option serait d'écrire l'image sur un byteArrayOutPutStream afin que vous puissiez déterminer la longueur, puis écrivez en premier au flux de sortie en premier.

puis sur l'extrémité de réception, vous pouvez lire La longueur, puis lisez que beaucoup d'octets dans une matrice d'octet, puis créez un byteArrayInputStream pour envelopper la matrice et transmet que à imageo.read () .

Je ne suis pas entièrement surpris que cela ne fonctionne pas tant que la prise de sortie ne fonctionne pas normalement - après tout, un fichier contenant un fichier PNG valide et ensuite quelque chose d'autre N'est-ce pas un fichier PNG valide en soi, n'est-ce pas? Donc, le lecteur doit lire à la fin du flux avant de pouvoir terminer - et la "extrémité" d'un flux de réseau ne vient que lorsque la connexion est fermée.

Edit: Voici une méthode pour lire les données nombre d'octets dans un nouveau réseau d'octets. Il est pratique d'avoir une méthode distincte "utilitaire". xxx


14 commentaires

@David: C'est un code très convoluté - en particulier, vous ne devriez jamais attraper ArrayIndexoutofboundSException. Pourquoi n'utilisez-vous pas simplement out.write (imgbyte) ? Et sur le côté de la réception, vous utilisez client.getInputStream (). Lisez (tampon); qui est Ignorant complètement la valeur de retour de Lecture . Pas une bonne idée. Call getinputtream () une fois , puis appelle lire plusieurs fois, notant combien de données ont été lues sur chaque appel. Ne supposez pas que ce sera toujours la même que la taille de la réception.


Oui j'ai oublié de mentionner. Out.Write (imgbyte) oblige instantanément à la prise de courant et déconnecte le client. Je ne peux pas comprendre pourquoi cela se passe, mais je pensais qu'il doit y avoir une limite à la quantité de données que vous pouvez écrire à une fois, alors j'ai essayé de la scinder et de l'envoyer.


@David: Non, il devrait être absolument bien d'écrire des données sur une prise. Êtes-vous sûr que ce n'était pas le côté recevant qui a fermé la prise?


@David: Vous ignorez toujours la valeur de retour de entrée.Read () . Vous Ne devez pas faire ça. Vous devez faire boucle, entraînant de la quantité de données dont vous avez encore besoin de lire et de lire un morceau à la fois. Sur une connexion réseau, vous ne sera pas tout faire en une seule fois.


Cela a juste fait cette tentative modifiée 4. La réception ne donne aucune erreur. L'expéditeur, cependant, déconnecte simplement et dit "raccordement réinitialisé par pair" lorsque j'essaie d'écrire plus de 200 Ko à l'une à l'une d'abord sur le flux de sortie. Des idées?


@David: Eh bien, vous êtes maintenant écrasement les données à chaque fois - vous devez lire d'où vous êtes arrivé à dans le reste du tampon. Je suppose que vous avez réellement réussi à terminer la réception de toutes les données (par conséquent, vous fermez la prise), mais comme vous avez écrasé les données existantes sur chaque lecture, vous devez alors décoder l'image.


Et que suggérez-vous d'utiliser pour copier ce que j'avais eu du tampon dans Imgbyte? Système.arraycopy? Si c'est le cas, veuillez regarder la tentative n ° 3 et dites-moi pourquoi cela échoue.


@David: Vous pouvez lire directement dans imgbyte . Je vais ajouter un extrait de code rapide ... Notez que cela n'a rien à voir avec Image IMAGE.


Si vous êtes intéressé, jetez un coup d'œil à ce qui s'est passé. Si vous êtes fatigué de cela, je peux comprendre;)


@David: Oui, c'est exactement ce que je m'attendais - vous ne lisez jamais des données dans le début de la mémoire tampon. La plupart de votre fichier est donc vide. Avez-vous essayé l'extrait que j'ai fourni?


Cela utilise l'extrait que vous avez fourni. Remarquez l'octet de ligne [] imgbytes = readexactly (dans, platesize); Notez que je parle de tentative 5, recevez.


@David: J'ai maintenant remarqué comment vous écrivez la longueur dans le fichier. Ne fais pas ça! Vous lisez une quantité aléatoire de données jusqu'à 30 octets - rien ne garantit que ce que vous lisez sera une chaîne valide du tout. Ecrivez-le à l'aide de quelque chose comme dataOutputtream.writeint et lisez-le avec DataGuTstream.readint . Vous devriez vérifier que vous transmettez correctement la taille la taille avant de partir ...


J'avais l'habitude d'avoir un système.Out.println (FileSize), mais je l'ai supprimé. C'était valable en premier lieu. (Bien que je suis d'accord c'est une mauvaise pratique). J'ai utilisé Evirsint maintenant et j'ai toujours exactement le même problème. Vous pouvez l'exécuter et voir si vous voulez.


@David: exactement le même problème? Les fichiers sont-ils de la même taille que l'autre maintenant? Est-ce qu'ils commencent avec les mêmes données? Je ne peux pas vraiment exécuter le code facilement sans dépenser de la quantité de temps à la fois définir tout le reste. Si vous pouviez modifier votre message sur juste une paire de clients / serveur courts mais complets à l'aide du dernier code, je verrai si je peux trouver le temps de diagnostiquer plus bien ce soir.



2
votes

Pour les autres utilisateurs de Stackoverflow comme moi.

dans la réponse "Jon Skeet". Modifier la ligne de méthode suivante de la méthode ReadExacTly. xxx

pour obtenir les données d'image complètes.


0 commentaires

0
votes
public static void main(String[] args) {
    Socket socket = null;
    try {
        DataInputStream dis;
        socket = new Socket("192.168.1.48",8000);
        while (true) {
            dis = new DataInputStream(socket.getInputStream());
            int len = dis.readInt();
            byte[] buffer = new byte[len];
            dis.readFully(buffer, 0, len);
            BufferedImage im = ImageIO.read(new ByteArrayInputStream(buffer));
            jlb.setIcon(new ImageIcon(im));
            jfr.add(jlb);
            jfr.pack();
            jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jfr.setVisible(true);
            System.gc();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } 
    finally {
        try {
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
In 192.168.1.48:8000 machine python server running and i got stream in java code

0 commentaires