Problema ImageIO [RESOLVIDO]

Oi gente, eu estou com um problemão aqui que não consigo resolver de jeito nenhum.

Bom, eu to usando o ImageIO do Java pra tentar carregar imagens na minha tabela do Javafx, permitindo que eu altere essas imagens. A parte de inserir as imagens e as informações estão dando certo, como podem ver:

Então eu fiz um método no meu Controller pra que quando o usuário clicasse duas vezes num registro da tabela, ele carregasse esse registro em uma outra tela .No caso, a tela Cadastro, que é essa daqui:

(ignorem as imagens desalinhadas)

Então, até aí tudo bem. O meu método de carregamento é esse aqui (Obs: leiam os comentários):

private void carregar() {
        
        //descobre qual o pet selecionado
        Pet selecionado = tabelaPet.getSelectionModel().getSelectedItem();
        if (selecionado == null) {
            return;
        }

        //preenche os TextFields pra edição
        txtNome.setText(selecionado.getNomePet());
        txtNomeDono.setText(selecionado.getDono().getNomeDono());
        this.selecionado = selecionado.getDono();
        txtObs.setText(selecionado.getObservacoes());
        txtRaca.setText(selecionado.getRaca());

        //formata o valor que veio do banco pra bater com o valor que tá no choicebox (espécie é um enum)
        String especieString = selecionado.getEspecie().toString().toLowerCase(),
                primeiroCaracter = new Character(especieString.charAt(0)).toString();

        choiceEspecie.setValue(especieString.replaceFirst(primeiroCaracter, primeiroCaracter.toUpperCase()));
        choicePorte.setValue(selecionado.getPorte());
        choiceSocial.setValue(selecionado.getConvivioSocial());

        //define as duas imagens que vão ser usadas
        Image imagemFoto, imagemCarteirinha;

        try {
            //esses métodos get uri na realidade não tem uri, eles tem uma string em um formato tipo file:/C:/imagensPet/pastaDaFoto/foto.extensão
            fotoPetselecionada = new File(selecionado.getUriFoto());
            imagemFoto = new Image(selecionado.getUriFoto());
        } catch (NullPointerException e) {
            fotoPetselecionada = null;
            imagemFoto = null;
        }
        try {
            cadernetaSelecionada = new File(selecionado.getUriCarteirinha());
            imagemCarteirinha = new Image(selecionado.getUriCarteirinha());
        } catch (NullPointerException e) {
            imagemCarteirinha = null;
            cadernetaSelecionada = null;
        }

        //o imageCarteirinha e o imageFoto são dois imageViews
        imageCarteirinha.setImage(imagemCarteirinha);
        imageFoto.setImage(imagemFoto);
        //aqui que tá o pulo do gato. Pra diferenciar as inserções das edições dos Pets, eu criei
        //um campo chamado carregado (que é um Pet). quando esse carregado está nulo, o programa faz inserção
        //e quando ele está preenchido, o programa faz edição. Vou explicar mais disso no próximo método
        carregado = selecionado;
        //aqui é mudada a tela
        tabPane.getSelectionModel().select(tabCadastro);
        //essa é uma mensagem que sobe no canto da tela só
        MensagensNotificacao.mostrarSucesso("Pet carregado");

    }

O carregamento acontece normalmente, mas o problema está quando o usuário clica no botão confirmar, pois então é disparado um método chamado cadastrar. Leiam os comentários novamente:

 private void cadastrar() {

        //O método controiPet retorna uma nova instancia de Pet. Vou indexar ele em baixo
        //desse método cadastrar
        Pet novo = constroiPet();
        //se der algum erro de validação no método constroiPet, ele retorna null, e então a operação é abortada
        if (novo == null) {
            return;
        }
        
        //Estamos chegando perto da raiz do problema! O método salvar imagem usa o ImageIO pra ler as imagens postas
        //em dois campos do tipo File: fotoPetSelecionada e cadernetaSelecionada. No caso, eu estou gerando dois arquivos,
        //um pra cada if. Vou indexar esse método comentado também. 
        //Obs: esses File.separator são uma barra só. Nos ifs tem também 
        //a condição exists, pra saber se o usuário já não cadastrou aquela foto, não precisando assim gerar um novo arquivo
        
        if (novo.getUriFoto() != null && !new File(novo.getUriFoto()).exists()) {
            salvarImagem(fotoPetselecionada, "C:" + File.separator + "imagensPet" + File.separator + "imagensPerfil" + File.separator);
        }
        if (novo.getUriCarteirinha() != null && !new File(novo.getUriCarteirinha()).exists()) {
            salvarImagem(cadernetaSelecionada, "C:" + File.separator + "imagensPet" + File.separator + "imagensCadernetas" + File.separator);
        }

        try {
            //Aqui que é aplicado aquilo que eu disse do carregado,
            //que para nulo é inserção e preenchido edição. Quando o usuário clica duas vezes
            //num registro da tabela, é realizada uma edição
            if (carregado != null) {

                //sets
 
                carregado.setConvivioSocial(novo.getConvivioSocial());
                carregado.setDono(novo.getDono());
                carregado.setEspecie(novo.getEspecie());
                carregado.setNomePet(novo.getNomePet());
                carregado.setObservacoes(novo.getObservacoes());
                carregado.setPorte(novo.getPorte());
                carregado.setRaca(novo.getRaca());
                carregado.setUriCarteirinha(novo.getUriCarteirinha());
                carregado.setUriFoto(novo.getUriFoto());

                //Aqui é realizado um merge via JPA na base de dados (essa parte está funcionando perfeitamente)
                petDAO.alterar(carregado);
            } else {
                //Aqui é para o caso de inserção (carregado nulo)
                petDAO.inserir(novo);
                MensagensNotificacao.mostrarSucesso("Pet de nome " + novo.getNomePet() + " cadastrado com sucesso!");
            }
            //esse método limpa os TextFields e deixa os campos nulos (aqueles Files e o carregado são esses campos)
            limpar();
            //esse método tira todos os itens da tabela e em seguida preenche ela com os valores do banco
            atualizaTabela();
        } catch (Exception e) {
            FxDialogs.showException("", "", e);
            MensagensNotificacao.mostrarErro("Erro ao cadastrar o Pet!");
        }

    }

Método salvarImagem (onde ocorre a exceção)

 private void salvarImagem(File fotoPetselecionada, String caminho) {
        //Aqui é o pulo do gato de vez. Vou explicar os parâmetros:
        //o primeiro é o arquivo que vai ser cadastrado. Como eu disse
        //antes, são as imagens que são carregadas por um FileChooser.
        if (fotoPetselecionada == null) {
            MensagensNotificacao.mostrarErro("Nenhuma foto selecionada para o Pet.");
            return;
        }
        try {
            //Aqui é assim: peguei uma classe na internet (essa FxDialogs)
            //pra poder receber as mensagens tipo um sysout. O mais estranho é:
            //pra algumas imagens...
            FxDialogs.showInformation("", fotoPetselecionada.toURI().toURL().toString());//<---- esse fotoPetselecionada.toURI().toURL().toString()...
            //mostra um formato de arquivo e pra outras ele mostra outro formato.
            
            //Vou deixar duas imagens com os dois formatos pra vocês tentarem entender o que está acontecendo
            
            //aqui é gerada a exceção javax.imageio.IIOException: Can't read input file!
            BufferedImage img = ImageIO.read(fotoPetselecionada);
            
            //Aqui eu pego a extensão do arquivo pra usar no write (é um dos parâmetros)
            String formato = fotoPetselecionada.getName().substring(
                    fotoPetselecionada.getName().lastIndexOf(".") + 1, fotoPetselecionada.getName().length());

            //aqui eu garanto que as pastas estão criadas
            File path = new File(caminho);
            path.mkdirs();

            //aqui é gerado o arquivo (era pra ser)
            ImageIO.write(img, formato, new File(caminho + fotoPetselecionada.getName()));

        } catch (IOException ex) {
            FxDialogs.showException("", "", ex);
            MensagensNotificacao.mostrarErro("Erro ao salvar a imagem!");
        }

    }

Vou deixar o método constroiPet aqui caso ajude:

 private Pet constroiPet() {
        if (selecionado == null) {
            MensagensNotificacao.mostrarErro("Selecione um tutor para cadastrar o Pet.");
            return null;
        }

        //Declarando as variáveis
        String nomePet = txtNome.getText(), porte = choicePorte.getValue(), convivioSocial = choiceSocial.getValue(),
                raca = txtRaca.getText(), uriCarteirinha = null,
                observacoes = txtObs.getText(),
                uriFoto = null, especieString = choiceEspecie.getValue();

        //verificando se as URLs das fotos são válidas
        if (fotoPetselecionada != null) {
            try {
                uriFoto = new File("C:" + File.separator + "imagensPet/imagensPerfil/" + fotoPetselecionada.getName()).toURI().toURL().toExternalForm();
            } catch (MalformedURLException ex) {
                MensagensNotificacao.mostrarErro("Caminho especificado para a foto do Pet é inválidos.");
            }
        }

        if (cadernetaSelecionada != null) {
            try {
                uriCarteirinha = new File("C:/i"
                        + "magensPet/imagensCadernetas/" + cadernetaSelecionada.getName()).toURI().toURL().toExternalForm();
            } catch (MalformedURLException ex) {
                MensagensNotificacao.mostrarErro("Caminho especificado para a foto da caderneta de vacinação é inválido.");
            }
        }

        //verificando se algum dos campos está vazio
        if (raca == null) {
            raca = "Nenhuma Especificada";
        }
        if (nomePet == null) {
            MensagensNotificacao.mostrarErro("Informe o nome do Pet a ser cadastrado.");
            return null;
        }

        //transformando espécie string em enum
        Especie especie = Especie.OUTRO;
        if (especieString.equals("Gato")) {
            especie = Especie.GATO;
        } else if (especieString.equals("Cão")) {
            especie = Especie.CÃO;
        }

        return new Pet(selecionado, nomePet, porte, convivioSocial, raca, especie, uriCarteirinha, observacoes, uriFoto);
    }

Vou fazer um passo a passo do que acontece em imagens:

1-) Abre o menu de Pets

2-) Clica duas vezes e seleciona um pet

3-) Mudando as fotos

4-)Caminho da primeira imagem:

5-) Caminho da segunda imagem:

6-) Até aí tudo bem, porque eu mudei as duas imagens. Agora vou mudar uma só:

7-) Aqui está aquele formato estranho da URL, que tem dois file:/ (em nenhum momento isso é especificado por mim)!

Exceção gigantesca gerada:

javax.imageio.IIOException: Can't read input file!
	at javax.imageio.ImageIO.read(ImageIO.java:1301)
	at trickstival.CadastroPetsController.salvarImagem(CadastroPetsController.java:404)
	at trickstival.CadastroPetsController.cadastrar(CadastroPetsController.java:284)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
	at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Node.fireEvent(Node.java:8411)
	at javafx.scene.control.Button.fire(Button.java:185)
	at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
	at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
	at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
	at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
	at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
	at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$355(GlassViewEventHandler.java:388)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
	at com.sun.glass.ui.View.notifyMouse(View.java:937)
	at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191)
	at java.lang.Thread.run(Thread.java:745)

Resultado ao carregar o mesmo Pet novamente:

A foto sumiu!!!

Olhando no banco:

A imagem continua!
Mas mesmo reiniciando a aplicação, a imagem não é carregada.

Por favor me ajudem!!!

No método carregar, já carrega a imagem do tipo Image do JavaFx, onde está:

imagemFoto = new Image(selecionado.getUriFoto());

então altere o salvarImagem para receber imagemFoto como parâmetro:

private void salvarImagem(Image imagemFoto, String caminho) {

e insira o código:

File outputFile = new File(caminho);
BufferedImage bImage = SwingFXUtils.fromFXImage(imagemFoto, null);
try {
  ImageIO.write(bImage, "png", outputFile);
} catch (IOException e) {
  throw new RuntimeException(e);
}

http://www.java2s.com/Tutorials/Java/JavaFX_How_to/Image/Save_an_Image_to_a_file.htm

1 curtida

Diego muito obrigado cara!!! PQP, você não faz ideia do como eu quebrei a cabeça e você me dá a solução assim na tranquilidade. Muito obrigado mesmo, está funcionando perfeitamente. Fico feliz que ainda existam pessoas boas como você, Abraço!