Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使JavaURI类停止使用文件_Java_Windows_Swing_File_Url - Fatal编程技术网

如何使JavaURI类停止使用文件

如何使JavaURI类停止使用文件,java,windows,swing,file,url,Java,Windows,Swing,File,Url,我有一个小型Java桌面应用程序,它读取一些图像文件并显示它们。问题是,当我想在这些文件上执行某些操作(比如说,exiftool操作)时,它会拒绝,因为Java仍在使用它们 编辑:这只发生在Windows上,您不能在Java正在处理(显示)的动画GIF文件(转换为URL对象)上写入,但在Ubuntu上您可以编辑该文件元数据,系统不认为该文件正在处理 这是我代码的一部分 我看了文件 ImageInputStream iis = null; ImageReader reader = null; ii

我有一个小型Java桌面应用程序,它读取一些图像文件并显示它们。问题是,当我想在这些文件上执行某些操作(比如说,exiftool操作)时,它会拒绝,因为Java仍在使用它们

编辑:这只发生在Windows上,您不能在Java正在处理(显示)的动画GIF文件(转换为URL对象)上写入,但在Ubuntu上您可以编辑该文件元数据,系统不认为该文件正在处理

这是我代码的一部分

我看了文件

ImageInputStream iis = null;
ImageReader reader = null;
iis = ImageIO.createImageInputStream(
                    f);
Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(iis);
reader = (ImageReader) imageReaders.next();

Path pathe = f.toPath();
String mimeType = Files.probeContentType(pathe);
ImageIcon icon = null;
最后,溪流被关闭

this.imageLabel.setIcon(icon);
iis.close();
reader.dispose();
然后我尝试通过一个进程执行一些exiftool命令,它成功地读取了图像元数据。但在更新数据时,如果图像是动画GIF,则会显示“将临时文件重命名为C:/Users/path时出错…”。 如果图像是非动画图像(JPEG、PNG或GIF),则不会出现任何问题,我想它可以读取和更新元数据

当我取消显示部分代码的图像时,我可以在图像元数据上写入而不会出错。如果我读取JPEG文件并显示它,仍然没有问题。如果我读取动画GIF并显示它(动画,它是否保持文件连接打开?),则在调试会话未关闭时,无法对该文件进行任何修改,无论是在我的程序中还是在cmd.exe上。退出调试后,cmd.exe上的exiftool进程开始正常工作

关闭ImageInputStream或ImageReader没有帮助


有没有办法让Java进程(如果文件是动画的,我使用URI、URL类)在读取操作后释放文件?我提到的这些类是否有释放、关闭、关闭、终止进程等方法。我需要读取动画图像,并将其显示为动画,并对其进行更新操作。

是否尝试使用方法加载图像

试一试:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Main {
    private static class DrawPanel extends JPanel {
        private Image i = null;

        public void loadImage(final File f) {
            //Most important point: load image via Toolkit.
            //I think it must support GIF, JPEG and PNG.
            i = getToolkit().createImage(f.getAbsolutePath());
            repaint();
        }

        @Override
        protected void paintComponent(final Graphics g) {
            super.paintComponent(g);
            if (i != null) {
                //g.drawImage(i, 0, 0, this); //Draw full scale image.
                g.drawImage(i, 0, 0, getWidth(), getHeight(), this); //Draw scaled/streched image.
                //Supplying 'this' in place of ImageObserver argument to the drawImage method is also very important!
            }
        }
    }

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(() -> {
            final DrawPanel imagePanel = new DrawPanel();
            imagePanel.setPreferredSize(new Dimension(500, 350));

            final JFileChooser fileChooser = new JFileChooser();
            fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
            fileChooser.setMultiSelectionEnabled(true);

            final JButton load = new JButton("Load");
            load.addActionListener(e -> {
                if (fileChooser.showOpenDialog(imagePanel) == JFileChooser.APPROVE_OPTION)
                    imagePanel.loadImage(fileChooser.getSelectedFile());
            });

            final JPanel contents = new JPanel(new BorderLayout());
            contents.add(imagePanel, BorderLayout.CENTER);
            contents.add(load, BorderLayout.PAGE_END);

            final JFrame frame = new JFrame("Images");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(contents);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}
  • 有几种
    createImage
    方法可供选择
  • 我认为他们支持动画GIF,以及非动画JPG和PNG。我只测试了一个GIF,但我在过去也使用过JPG和PNG
  • 我认为动画图像已完全加载到内存中(所有帧)。因此,在阅读图像后修改图像应该不会有问题
  • 获取与
    组件相关的
    工具包
    ,该组件将显示
    图像
    。我认为在某些情况下,
    Toolkit.getDefaultToolkit
    也应该完成这项工作。然后使用
    Graphics
    对象的
    drawImage
    方法绘制图像。有几种
    drawImage
    方法可供选择。例如,可以使用动态缩放图像的方法(通过提供新的宽度和高度以及绘制位置)重要:确保为
    绘图图像
    提供组件,该组件将其呈现为
    图像观察者
    (注意
    组件实现图像观察者

  • 谢谢你的评论,这里是问题和解决方案

    首先,我从代码中删除了不必要的部分。ImageInputStream和ImageReader用于检查图像验证和检测图像格式(必须对GIF文件使用不同的操作),我不再需要这些了

    我仍然需要使用文件->URI->URL转换来显示动画GIF。这是我的旧代码

    URI img = f.toURI();
    URL umg = img.toURL();
    icon = new ImageIcon(umg);  
    
    此代码保持与文件的连接处于打开状态,并阻止了编辑图像文件的其他进程。(在Windows系统上,仅动画GIF文件)

    以下是新代码:

    //these 2 lines are same
    URI img = f.toURI();
    URL umg = img.toURL();
    
    InputStream is = umg.openStream();
    byte[] byteChunk = new byte[4096]; 
    int n;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    while ((n = is.read(byteChunk)) > 0) 
    {
    baos.write(byteChunk, 0, n);
    }
    byte[] dd= baos.toByteArray();
    icon = new ImageIcon(dd);
    is.close();
    

    使用这种方法,URI(图像)通过流读取,ImageIcon是从图像文件的字节数组创建的,而不是直接从URL创建的,在该操作之后,InputStream被关闭,因此该文件上的块被释放。(如果未执行“is.close()”行,则文件仍在处理中,并被阻止进行其他写入操作)

    您是否在windows上?然后,我认为这是windows内部的文件访问机制。这就像你在outlook中以附件的形式发送文件,windows会一直保持访问权限,直到outlook关闭为止(无论邮件是否已发送)。我强烈建议使用此机制确保关闭/处置邮件。Hi@bish,是的,我在Windows10上,在你的评论之后,我尝试在Ubuntu上执行我的代码,它没有问题。因此,在Windows系统上,如果将GIF文件作为URL对象读取并显示,Java会锁定该文件,但会忽略JPEG文件。在Ubuntu上,它一点也不在乎,你可以对正在处理的文件做任何你想做的事情。谢谢你的评论,在我尝试你的建议之前,我已经为我的案例创建了一个解决方案。如果你解决了自己的问题,那么请在这里发布答案,以便其他人知道你做了什么。我想知道如何解决这个问题(我相信其他人也会这么做),所以我也把它贴出来。当最短的自我接受时间过去时,别忘了接受你自己的答案。我一找到解决方案,就回到这里回答我的问题,只是先回答你的评论。再次感谢。
    //these 2 lines are same
    URI img = f.toURI();
    URL umg = img.toURL();
    
    InputStream is = umg.openStream();
    byte[] byteChunk = new byte[4096]; 
    int n;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    while ((n = is.read(byteChunk)) > 0) 
    {
    baos.write(byteChunk, 0, n);
    }
    byte[] dd= baos.toByteArray();
    icon = new ImageIcon(dd);
    is.close();