Je suis en train d'envoyer un BufferedImage sur un socket et j'utilise l'exemple trouvé dans ce post :
Expéditeur
BufferedImage image = ....;
ImageIO.write(image, "PNG", socket.getOutputStream());
Récepteur
BufferedImage image = ImageIO.read(socket.getInputStream());
Cela fonctionne - SI, et SEULEMENT SI, je ferme le flux de sortie de l'expéditeur après cette ligne :
ImageIO.write(image, "PNG", socket.getOutputStream());
Y a-t-il quelque chose que je peux faire à part fermer le flux de sortie ?
De plus, y a-t-il quelque chose d'autre que je peux faire pour éviter d'utiliser complètement ImageIO ? Il semble mettre une éternité pour faire quoi que ce soit. Notez également que la lecture ou l'écriture sur le disque dur doit être évitée à tout prix en raison de problèmes de performance. J'ai besoin de rendre ce transfert aussi rapide que possible (j'expérimente et essaie de créer un client similaire à VNC et enregistrer chaque capture d'écran sur le disque dur ralentirait considérablement tout). . .
@Jon Skeet
Éditer 3 :
Expéditeur : (Notez que j'envoie une image JPG et non une PNG).
int filesize;
OutputStream out = c.getClientSocket().getOutputStream();
ByteArrayOutputStream bScrn = new ByteArrayOutputStream();
ImageIO.write(screenshot, "JPG", bScrn);
byte[] imgByte = bScrn.toByteArray();
bScrn.flush();
bScrn.close();
filesize = bScrn.size();
out.write(new String("#FS " + filesize).getBytes()); //Envoyer la taille du fichier
out.write(new String("# \n").getBytes()); //Notifier le début de l'image
out.write(imgByte); //Ecrire le fichier
System.out.println("Terminé");
Récepteur : (où input
est le flux d'entrée du socket)
Tentative #1 :
String str = input.toString();
imageBytes = str.getBytes();
InputStream in = new ByteArrayInputStream(imageBytes);
BufferedImage image = ImageIO.read(in);
in.close();
System.out.println("largeur=" + image.getWidth());
(échec : exception Nullpointer sur la ligne de getWidth()) Je comprends cette erreur comme un "image corrompue" parce qu'elle n'a pas pu l'initialiser. Correct ?
Tentative #2 :
byte[] imageBytes = new byte[filesize];
for (int j = 0; i < filesize; i++)
{
imageBytes[j] = (byte) input.read();
}
InputStream in = new ByteArrayInputStream(imageBytes);
BufferedImage image = ImageIO.read(in);
in.close();
System.out.println("largeur=" + image.getWidth());
(échec : exception Nullpointer sur la ligne de getWidth())
Tentative #3 :
if (filesize > 0)
{
int writtenBytes = 0;
int bufferSize = client.getReceiveBufferSize();
imageBytes = new byte[filesize]; //Créer un tableau de bytes aussi grand que l'image
byte[] buffer = new byte[bufferSize]; //Créer un tampon
do {
writtenBytes += input.read(buffer); //Remplir le tampon
System.out.println(writtenBytes + "/" + filesize); //Montrer le progrès
//Copier le tampon dans le tableau de bytes qui contiendra l'image complète
System.arraycopy(buffer, 0, imageBytes, writtenBytes, client.getReceiveBufferSize());
writtenBytes+=bufferSize;
} while ((writtenBytes + bufferSize) < filesize);
// Lire les bytes restants
System.arraycopy(buffer, 0, imageBytes, writtenBytes-1, filesize-writtenBytes);
writtenBytes += filesize-writtenBytes;
System.out.println("Lecture terminée ! Lecture totale : " + writtenBytes + "/" + filesize);
}
InputStream in = new ByteArrayInputStream(imageBytes);
BufferedImage image = ImageIO.read(in);
in.close();
(échec : Le récepteur donne : exception Null pointer)
Tentative 4 :
int readBytes = 0;
imageBytes = new byte[filesize]; //Créer un tableau de bytes aussi grand que l'image
while (readBytes < filesize)
{
readBytes += input.read(imageBytes);
}
InputStream in = new ByteArrayInputStream(imageBytes);
BufferedImage image = ImageIO.read(in);
in.close();
System.out.println("largeur=" + image.getWidth());
(échec : l'expéditeur donne : java.net.SocketException: Connexion réinitialisée par l'hôte distant : erreur d'écriture de socket)
Tentative #5 :
En utilisant le snippet de code de Jon skeet, l'image arrive, mais seulement partiellement. Je l'ai enregistrée dans un fichier (1.jpg) pour voir ce qui se passait, et en réalité, il envoie 80 % de l'image, tandis que le reste du fichier est rempli d'espaces vides. Cela aboutit à une image partiellement corrompue. Voici le code que j'ai essayé (notez que captureImg() n'est pas en cause, enregistrer le fichier directement fonctionne) :
Expéditeur :
Socket s = new Socket("127.0.0.1", 1290);
OutputStream out = s.getOutputStream();
ByteArrayOutputStream bScrn = new ByteArrayOutputStream();
ImageIO.write(captureImg(), "JPG", bScrn);
byte imgBytes[] = bScrn.toByteArray();
bScrn.close();
out.write((Integer.toString(imgBytes.length)).getBytes());
out.write(imgBytes,0,imgBytes.length);
Récepteur :
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("terminé");
L'expéditeur donne toujours une erreur de réinitialisation de connexion par l'hôte distant : erreur d'écriture de socket. Cliquez ici pour une image en taille réelle