[RESOLVIDO] Socket (Java-Imagem-C++)

23 respostas
Sad7

Boa tarde pessoal,
estou com um projeto aqui que utiliza socket, o meu server é em C++ e meu client em Java, esta tudo funcionando corretamente, porem eu tenho que passar um byte array de uma imagem para o server, eu li minha imagem e peguei o byte array dela:

public static byte[] getImageBytes(String _path) throws IOException {
		BufferedImage buff = ImageIO.read(new File(_path));
		ByteArrayOutputStream bas = new ByteArrayOutputStream();

		String ext = _path.substring(_path.lastIndexOf(".") + 1); 
		ImageIO.write(buff, ext, bas);

		byte[] byteArray = bas.toByteArray();
		
		bas.flush();
		bas.close();
		
		return byteArray;

	}

ate ai beleza, agora o problema esta para enviar isso juntamente com minha string, eu tenho que enviar no seguinte formato:

String stringDeEnvio = "<" + id + ":" + image_byte_array + ">";
// <id:imagearray>

para concatenar esse meu image array com minha string de envio eu faço:

String image_byte_array = new String(imageBytes);

porem quando recebo essa mensagem no meu server (em C++), na hora que chega na parte do image_byte_array ele me retorna “\022\031\0…” e assim vai…
alguem sabe o que pode estar contecendo?!

ou outra maneira de passar esse byte array via socket?!

Muito grato…
Abraços!!

23 Respostas

J

Já respondi uma dúzia de problemas como esse e todo mundo me criticou.
A culpa disso é do Gosling que não implementou tipos unsigned no java.

O problema é o seguinte.

Um byte no java é um valor de 8 bits sinalizado, com um intervalo entre -128 a 127, em contrapartida um byte no c++ é um unsigned char, ou seja, um valor não sinalizado de intervalo 0 a 255.

Você precisa converter esses bits de maneira que o c++ e qualquer outra linguagem da face da terra(só o java é sinalizado) possam entender.

Não é bicho de sete cabeças implementar uma conversão, mas realmente é um incômodo.

Leia esse artigo, é uma leitura muito útil.

http://darksleep.com/player/JavaAndUnsignedTypes.html
http://darksleep.com/player/JavaAndUnsignedTypes.html#why_no_unsigned_types

Aqui tem uma entrevista com ritchie, bjarne e gosling, falando dentre muitos assuntos. Esse está incluso.
http://www.gotw.ca/publications/c_family_interview.htm

Sad7

entendi,
me diga uma coisa, na hora que eu jogo meu byte array pra String, ele se transfora em uma coisa do tipo: ÿØÿà (e mais caracteres estranhos)
isso é normal !? e eu devo fazer essa conversao antes de passa para a string ou depois!?

J

É, porque um byte não é um caracter.

Olha só:

http://java.sun.com/docs/books/tutorial/i18n/text/stream.html

Você precisa converter na hora de enviar, ou na hora de receber. Trabalhei em um projeto que um hardware enviava mensagens para um programa java, e a conversão foi feita no programa.

No seu caso, se for haver troca de mensagens por bytes, você precisa implementar no c++ e no java.

Sad7

entendi, entao vou precisar somente no java pois minha intenção eh somente enviar, eu faço um processamento dessa imagem no server e retorno uma simples string pro cliente.

o complicado eh essa conversao…to dando uma olhada aqui no site que voce me passou.

J

não…o server c++ que precisa fazer a conversão. Não tem como você converter no java e mandar pro c++, ou vice versa.
os seus dois programas precisam fazer suas próprias conversões, senão eles não conversam.

nessa parte aqui eu errei


Você precisa converter na hora de enviar, ou na hora de receber. Trabalhei em um projeto que um hardware enviava mensagens para um programa java, e a conversão foi feita no programa.

Quem recebe que deve decodificar.

Sad7

ahh entao nao vai te jeito, vo te que fze as conversoes nos dois msm…
puts, e vc disse q nao era nehum bixo de sete kças…hehehehe…

J

Sad7:
ahh entao nao vai te jeito, vo te que fze as conversoes nos dois msm…
puts, e vc disse q nao era nehum bixo de sete kças…hehehehe…

A converção é um calculo simples, mas te falei que gerava incômodo.

Sad7

entao veja se eu entendi corretamente:

Client:
1 - Faço a conversao de elemento por elemento no meu ImageArray e jogo isso para um novo array.
2 - Transformo meu array em uma string e envio para o server.

Server:
1 - recebo a messagem do client e converto.

correto!?

J

se o seu client for ler alguma coisa vc precisa converter,
a mesma coisa com o server.

“Quem recebe decodifica”.

O detalhe é o seguinte, voce disse que seu server é c++. Imagina um unsigned char(0 a 255) recebendo -127?
O inverso no caso do java: byte(-127 a 128 ) recebendo um valor maior que 128.
vai violar memória. Por isso que você via aqueles caracteres estranhos.

Sad7

Nao mais aqueles caracteres estranhos vinham no proprio java, antes de eu enviar, no C++ ele aparecia dakela outra foram “\033\000\021”

olha, como exemplo meu primeiro elemento ta vindo como -1, quando eu faço aquela a conversao: firstByte = (0x000000FF & ((int)buf[index])); ele me retorna 255, esta correto?!

J
Sad7:
Nao mais aqueles caracteres estranhos vinham no proprio java, antes de eu enviar, no C++ ele aparecia dakela outra foram "\033\000\021"

olha, como exemplo meu primeiro elemento ta vindo como -1, quando eu faço aquela a conversao: firstByte = (0x000000FF & ((int)buf[index])); ele me retorna 255, esta correto?!

A conversão sim.

Sobre os caracteres estranhos é a codificação.

static void writeOutput(String str) {

    try {
	FileOutputStream fos = new FileOutputStream("test.txt");
	Writer out = new OutputStreamWriter(fos, "UTF8");
	out.write(str);
	out.close();
    } catch (IOException e) {
	e.printStackTrace();
    }
}

http://java.sun.com/docs/books/tutorial/i18n/text/stream.html

L

juliocbq:
Já respondi uma dúzia de problemas como esse e todo mundo me criticou.
A culpa disso é do Gosling que não implementou tipos unsigned no java.

O problema é o seguinte.

Um byte no java é um valor de 8 bits sinalizado, com um intervalo entre -128 a 127, em contrapartida um byte no c++ é um unsigned char, ou seja, um valor não sinalizado de intervalo 0 a 255.

Você precisa converter esses bits de maneira que o c++ e qualquer outra linguagem da face da terra(só o java é sinalizado) possam entender.

Não é bicho de sete cabeças implementar uma conversão, mas realmente é um incômodo.

Leia esse artigo, é uma leitura muito útil.

http://darksleep.com/player/JavaAndUnsignedTypes.html
http://darksleep.com/player/JavaAndUnsignedTypes.html#why_no_unsigned_types

Aqui tem uma entrevista com ritchie, bjarne e gosling, falando dentre muitos assuntos. Esse está incluso.
http://www.gotw.ca/publications/c_family_interview.htm

boa tarde pessoal !!!

e me desculpe a entromissão mas é que sou novo no forum e não consigo postar minha duvida e ja estou desesperado …então vai lá

eu fiz um programa semelhante ao substituir do bloco de notas até ai tudo bem o programa roda certinho ele pegas duas palavras como pramêtro e substitui num txt …
mais o problema foi na hora de criar as telas eu criei um frame que tem dois campos textos e um botão para fazer a substuição , mais não consigo pegar o que o usuario digita no campo texto

e jogar em uma string ,e como fazer para o botão iniciar a substituição …ai segue o códgo

e me descupem pois esta meio desorganizado é qui sou novo em java …

por favor se não puderem me ajudar postem minha duvida pois eu não consigo :frowning:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;   
	import java.io.FileReader;   
	import java.io.FileWriter;   
	import java.io.IOException;   
	import java.io.PrintWriter;   
	import java.util.ArrayList;   
import java.util.List;   

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
	  
	  
	public class sub {   
	  
	    private static final ActionEvent ActionEvent =null;

		public static void main(String[] args) throws IOException {  
	    	
	    	Frame menu= new Frame ();
	    	
	    	
	    	
	    	
	    	
	      
	      
	    	   
	    	   menu.label = new JLabel("Nome do Banco de Dados:");
	    	   menu.textField = new JTextField(20);

	    	   menu.button = new JButton("Alterar");
	    	   menu.label2 = new JLabel("Nome da Operação:");
	    	   menu.textField2 = new JTextField(20);
	    	  
	    	   
	    	   menu.panel = new JPanel();

	    	   menu.panel.add(menu.label);
	    	   menu.panel.add(menu.textField);
	    	   menu.panel.add(menu.label2);
	    	   menu.panel.add(menu.textField2);
	    	   menu.panel.add(menu.button);
	    	   

	    	   menu.frame = new JFrame("ALTERAÇÃO DO BANCO DE DADOS");
	    	   menu.frame.add(menu.panel);
	    	   menu.frame.pack();
	    	   menu.frame.setVisible(true);
	    	   menu.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    	   
	    	   
	    	 
	    	   
	    	   String  procurarPor= menu.textField.getText();;  
		        String  procurar1=menu.textField2.getText();
		        String substitui= "053";
		        String substituirPor = "ATPNET";   
		        String arquivo = "teste.sql"; 
		        
	    	

	    	   
	    	     if (procurarPor == "") {
	    	    	 
	    	    	 System.out.println ("NOME INVALIDO");
	    	     }
	    	     
	    	     
	    	      menu.botao();
	    	    	  
	    	    	  
	    	    	  
	    	      
	       
	    	   
	       
	       


	    	  
	    	    		  
	        
	           
	        //ler o arquivo   
	        List<String> linhas = new ArrayList<String>();   
	        BufferedReader reader = new BufferedReader(new FileReader(arquivo));   
	        String linhaArquivo;   
	        while(((linhaArquivo = reader.readLine())!= null)){   
	            //substituir o conteudo 
	        	
	       
	        
	        	
	            linhaArquivo = linhaArquivo.replace(procurarPor, substituirPor).replace(procurar1,substitui); ;   
	            linhas.add(linhaArquivo);
	            
	           
	        
	            //C:/Documents and Settings/Administrador/Meus documentos/teste.sql
	            
	            
	        	}	
	    
	        
	        
	       reader.close();
	           
	        //gravar arquivo   
	        PrintWriter writer = new PrintWriter(new FileWriter(arquivo), true);   
	        for (String linha : linhas) {   
	            writer.println(linha);   
	        }   
	        writer.close(); 
	        
	        String msg = " os paramêtros foram alterados com sucesso " + "" + "!";
	    	JOptionPane.showMessageDialog(null, msg);

	        
	        System.out.println("ARQUIVO ALTERADO COM SUCESSO");
	       }

		
		}

esta é a classe do programa principal

public class Frame implements ActionListener {
	
	
	sub ler = new sub();
	
	
	
public JLabel label;
public JLabel label2;
public JTextField textField;
public JTextField textField2;
public JTextField textField33;
public JButton button;
public JPanel panel;
public JFrame frame;


public void montarFormulario() {

label = new JLabel("Nome do Banco de Dados:");
textField = new JTextField(20);

button = new JButton("Alterar");
label2 = new JLabel("Nome da Operação:");
textField2 = new JTextField(20);
button.addActionListener(this);
textField33 = new JTextField(20);
panel = new JPanel();

panel.add(label);
panel.add(textField);
panel.add(label2);
panel.add(textField2);
panel.add(button);
panel.add(textField33);

frame = new JFrame("Configuração do Banco Scorpions");

frame.setIconImage (new ImageIcon ("a.JPEG").getImage());
frame.add(panel);
frame.pack();
frame.show();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);




}



public void actionPerformed (ActionEvent e) {
  String procurarPor =textField.getText();
  textField2.getText();

JOptionPane.showMessageDialog(frame, procurarPor);


}
public void botao() {   
    this.button.addActionListener(   
                new ActionListener() {   
                        public void actionPerformed(ActionEvent evt) {   
                                 String procurarPor  = textField.getText();   
                                 String procurar1  = textField2.getText();   
                               System.out.println(procurarPor);
                               System.out.println(procurar1);
                        }   
                });   
}   










public void main (String [] args){
	
	
	
	
	montarFormulario();
	
	
	
	
	
	
	
	

}
}

esta é do meu frame …

a só mais uma coisa o se eu mesmo iniciar as variaveis ele funciona perfeitamente ,mas gostaria que o usuario entrasse com o valor ,desde já agradeço e me descupem

pela entromissão é que estou desesperado:@

Sad7

favor nao desvie o assunto do topico

Sad7

Julio,
eu consegui fazer a conversao inteira do meu array de bytes, porem agorah preciso transformar ele numa string, para poder concatenar na minha stringDeEnvio, porem nao estou conseguindo.

J
Sad7:
Nao mais aqueles caracteres estranhos vinham no proprio java, antes de eu enviar, no C++ ele aparecia dakela outra foram "\033\000\021"

olha, como exemplo meu primeiro elemento ta vindo como -1, quando eu faço aquela a conversao: firstByte = (0x000000FF & ((int)buf[index])); ele me retorna 255, esta correto?!

A sua converção está correta. Você simplesmente fez um AND do seu valor com um byte ativado(0xff hexa = 255 decimal)

Aqui um exemplo sem usar operadores lógicos.
ex:

public static byte readSignedByte(DataInput in) throws IOException {
        byte[] b = (byte[]) AlgumObjeto.get();
        in.readFully(b, 0, 1);
        return b[0];
    }

    public static short readUnsignedByte(DataInput in) throws IOException {
        short q = readSignedByte(in);
        if (q < 0) {
            q += 256;
        }
        return q;
    }
Sad7
juliocbq:
Sad7:
Nao mais aqueles caracteres estranhos vinham no proprio java, antes de eu enviar, no C++ ele aparecia dakela outra foram "\033\000\021"

olha, como exemplo meu primeiro elemento ta vindo como -1, quando eu faço aquela a conversao: firstByte = (0x000000FF & ((int)buf[index])); ele me retorna 255, esta correto?!

A sua converção está correta. Você simplesmente fez um AND do seu valor com um byte ativado(0xff hexa = 255 decimal)

Aqui um exemplo sem usar operadores lógicos.
ex:

public static byte readSignedByte(DataInput in) throws IOException {
        byte[] b = (byte[]) AlgumObjeto.get();
        in.readFully(b, 0, 1);
        return b[0];
    }

    public static short readUnsignedByte(DataInput in) throws IOException {
        short q = readSignedByte(in);
        if (q < 0) {
            q += 256;
        }
        return q;
    }

entendi +- , veja como eu comecei..
comcei codificando no meu client (JAVA) :
tenho um array de byte e preciso passar para um array de int (que sao os valores de 0 ate 255 * unsigned char), agorah meu problema esta sendo como eu passo esse array de int junto com minha string que deve ser:

arraydeint>

essse eh meu problema atual =/

Sad7

ainda nao consegui :frowning:
pois depois que eu converto tdo no java, meu byte[] se transofrma em um int[] , e o metodo do BufferedOutputStream.write() so aceita um byte[] e nao um int[] … alguem sabe como eu posso enviar um int[] !?

J

você não vai enviar o int, você vai usar o int somente para o java ler.
O problema que acontece no c++ server é que ele não está decodificando também. Precisa implementar a mesma solução nele.

||java||Decodificador(unsigned para signed) <<===========================>> (signed para unsigned)Decodificador||c++||

Sad7

juliocbq:
você não vai enviar o int, você vai usar o int somente para o java ler.
O problema que acontece no c++ server é que ele não está decodificando também. Precisa implementar a mesma solução nele.

||java||Decodificador(unsigned para signed) <<===========================>> (signed para unsigned)Decodificador||c++||

entao meu cliente vai enviar signed exemplo -1 e meu c++ vai receber e fazer a conversao?! entendi certo agora?! :smiley:

J

Sad7:
juliocbq:
você não vai enviar o int, você vai usar o int somente para o java ler.
O problema que acontece no c++ server é que ele não está decodificando também. Precisa implementar a mesma solução nele.

||java||Decodificador(unsigned para signed) <<===========================>> (signed para unsigned)Decodificador||c++||

entao meu cliente vai enviar signed exemplo -1 e meu c++ vai receber e fazer a conversao?! entendi certo agora?! :smiley:

Isso mesmo.

Sad7

mais aquele exemplo que vc me mandou esta em Java, veja se voce pode me ajudar com o C++, eu dei uma olhada no google mais nao entendi as coisas que eu vi…
eu estou recebendo do meu client um char buffer[1], quando eu leio esse char, ele me retorna /033, como eu devo fzer pra ele me retornar -1 que eh o valor que eu tenho q obter pra criar minha imagem?!

obrigado!

Sad7

Puts, consegui, eu nao acreditoq ue era tao simples cara…

simplesmente na hora de receber o signed do java, eu leio meu o byte no formato de int, muito simpless cara… eu nao acredito que fiquei um dia pra ve isso :smiley:
muito obrigado cara, vlw msm!!

J

Sad7:
Puts, consegui, eu nao acreditoq ue era tao simples cara…

simplesmente na hora de receber o signed do java, eu leio meu o byte no formato de int, muito simpless cara… eu nao acredito que fiquei um dia pra ve isso :smiley:
muito obrigado cara, vlw msm!!

Coloca [Resolvido] no título do tópico.

Criado 31 de março de 2010
Ultima resposta 1 de abr. de 2010
Respostas 23
Participantes 3