缺少要关闭的流

问题描述

我正在制作一个照片分类程序。 FileUtils.moveFile(from,to) 大部分时间都可以正常工作。当我旋转和复制图像的元数据时它不起作用。如果我旋转并复制数据然后关闭程序,重新启动程序它将工作。但是,如果我旋转并复制元数据然后尝试移动文件,我会从 moveFile 方法中得到无法删除文件错误。我以前遇到过这个问题,这是由于我没有关闭流。当我编写旋转方法时,我以为我涵盖了所有内容,但我想我错过了一个。这是我旋转和复制图像元数据的两种方法

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();
        }

    }

好的,我接受了建议,并尝试使用资源进行尝试。这是我的新代码仍然无法正常工作:

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,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,src.getType());
            Graphics2D graphics2D = dest.createGraphics();
            graphics2D.translate((height - width) / 2,(height - width) / 2);
            graphics2D.rotate(Math.PI / 2,width / 2);
            graphics2D.draWrenderedImage(src,null);
            Iterator<ImageReader> iterator = ImageIO.getimageReaders(iis);
            ImageReader reader = iterator.next();
            String format = reader.getFormatName();
            ImageIO.write(dest,output);
        }catch(IOException e){
            e.printstacktrace();
        }
    }

解决方法

在提及 Try-Finally 和 Try-With-Resource 之前要澄清一下, 您的问题是当您调用 copyMetaRotateRight() 时,您无法在 ImageIO 流打开并附加到您尝试移动的同一文件时使用 rotateRight 方法。您必须为每个操作打开/关闭流或将内容写入临时文件并从那里开始处理。

有两种方法可以打开和关闭您可能不会遇到问题的流。 最好使用这些来构建您的代码,然后再想知道哪里出了问题。

        /**
         * 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!");
                }
            }
        }