Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.4k views
in Technique[技术] by (71.8m points)

java - Missing a stream to close

I am making a photo sorting program. The FileUtils.moveFile(from, to) works fine most of the time. It does not work when I rotate and copy the meta data of an image. If I rotate and copy the data then close the program, restart the program it will work. But if I rotate and copy the meta data then try and move a file I get the cannot delete source file error from the moveFile method. I had this problem before and it was due to me not closing streams. When I wrote the rotate method I thought I covered them all but I guess I am missing one. Here is my 2 methods to rotate and copy the meta data of an image:

private void copyMetaRotateRight(File imageInput, File imageOutput) throws IOException {
        ImageReader reader = ImageIO.getImageReadersBySuffix("jpg").next();
        reader.setInput(ImageIO.createImageInputStream(imageInput));
        IIOMetadata metadata = null;
        try {
            metadata = reader.getImageMetadata(0);
        }catch(IIOException e){
            e.printStackTrace();
        }
        rotateRight(imageInput,imageOutput);
        BufferedImage bi = reader.read(0);

        ImageOutputStream ios = ImageIO.createImageOutputStream(imageOutput);

        Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpeg");
        ImageWriter writer = iter.next();
        writer.setOutput(ios);
        writer.write(null,new IIOImage(bi, null, metadata), null);
        writer.dispose();
        reader.dispose();
        ios.close();
        displayImage(currentIndex);
    }
    public void rotateRight(File input, File output) {
        BufferedImage src = null;
        try {
            src = read(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
        assert src != null;
        int width = src.getWidth();
        int height = src.getHeight();

        BufferedImage dest = new BufferedImage(height, width, src.getType());

        Graphics2D graphics2D = dest.createGraphics();
        graphics2D.translate((height - width) / 2, (height - width) / 2);
        graphics2D.rotate(Math.PI / 2, height / 2, width / 2);
        graphics2D.drawRenderedImage(src, null);
        try {
        ImageInputStream iis = ImageIO.createImageInputStream(input);
        Iterator<ImageReader> iterator = ImageIO.getImageReaders(iis);
        ImageReader reader = iterator.next();
        String format = reader.getFormatName();
        ImageIO.write(dest,format,output);
        reader.dispose();
        graphics2D.dispose();
        iis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

Okay I took the advice and I tried the try with resource. Here is my new still not working code:

private void copyMetaRotateRight(File imageInput, File imageOutput) throws IOException {
        
        try(ImageOutputStream ios = ImageIO.createImageOutputStream(imageOutput);
            ImageInputStream inputStream = ImageIO.createImageInputStream(imageInput);
            ){
            ImageReader reader = ImageIO.getImageReadersBySuffix("jpg").next();
            reader.setInput(inputStream);
            IIOMetadata metadata = reader.getImageMetadata(0);
            rotateRight(imageInput,imageOutput);
            BufferedImage bi = reader.read(0);
            Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpeg");
            ImageWriter writer = iter.next();
            writer.setOutput(ios);
            writer.write(null,new IIOImage(bi, null, metadata), null);
            displayImage(currentIndex);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }



 public void rotateRight(File input, File output) {
        
        try(FileInputStream stream = new FileInputStream(input);
            ImageInputStream iis = ImageIO.createImageInputStream(input);
            ){
            BufferedImage src = ImageIO.read(stream);
            assert src != null;
            int width = src.getWidth();
            int height = src.getHeight();

            BufferedImage dest = new BufferedImage(height, width, src.getType());
            Graphics2D graphics2D = dest.createGraphics();
            graphics2D.translate((height - width) / 2, (height - width) / 2);
            graphics2D.rotate(Math.PI / 2, height / 2, width / 2);
            graphics2D.drawRenderedImage(src, null);
            Iterator<ImageReader> iterator = ImageIO.getImageReaders(iis);
            ImageReader reader = iterator.next();
            String format = reader.getFormatName();
            ImageIO.write(dest,format,output);
        }catch(IOException e){
            e.printStackTrace();
        }
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Just to clarify before mentioning the Try-Finally and Try-With-Resources, your issue is when you call copyMetaRotateRight() you can't use your rotateRight method while the ImageIO stream is open and attached to the same file you are trying to move. You have to open/close the stream for each operation or write the contents to a temp file and work on it from there.

There are 2 ways to open and close streams where you are likely to not have your problems. It would be better to structure your code using these and then wonder where it all is going wrong.

        /**
         * METHOD 1 for ALL closable resources
         */
        try (FileInputStream stream = new FileInputStream(new File("fake path"))) {

        } catch (FileNotFoundException ex) {

        } catch (IOException ex) {

        }

        
        /**
         * METHOD 2 for ALL closable resources
         */
        FileInputStream oldSchool = null;
        try {

            oldSchool = new FileInputStream("fake file path");
        } catch (Exception ex) {
            // catch
        } finally {
            if (oldSchool != null) {
                try {
                    oldSchool.close();
                } catch (Exception ex2) {
                    System.err.println("OMG THANKYOU FOR TRY-WITH-RESOURCES-AND-NOT-WITH-CARPAL-TUNNEL-SYDROME!");
                }
            }
        }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
...