java - 如何使 Java URI 类停止使用文件

标签 java windows swing file url

我有一个小型 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;

这是我处理图像、调整图像大小并使用 JLabel 查看它们的部分。

我不只是使用 Java ImageIO 用图像填充该标签的原因是,ImageIO 只能显示动画 GIF 文件的第一帧。通过这种方式将图像转换为 URL 可以保持图像的动画效果(即使在调整大小后)。

ImageIcon icon = null;                    
Integer labelWidth = this.imageLabel.getWidth();
Integer labelHeight = this.imageLabel.getHeight();
URI img;
img = f.toURI();
URL umg = img.toURL();
icon = new ImageIcon(umg);

//some calculations for setting labelWidth and labelHeight here

icon.setImage(icon.getImage().getScaledInstance(labelWidth, labelHeight,
                                                                  Image.SCALE_DEFAULT));

最后,流被关闭。

this.imageLabel.setIcon(icon);
iis.close();
reader.dispose();

然后我尝试通过进程执行一些 exiftool 命令,它成功读取图像元数据。但更新数据时,如果图像是动画 GIF,则会显示“将临时文件重命名为 C:/Users/path... 时出错”。 如果图像是非动画图像、JPEG、PNG 或 GIF,则不会出现问题,我猜它可以读取和更新元数据。

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

关闭 ImageInputStream 或 ImageReader 没有帮助。

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

最佳答案

感谢您的评论,这是问题和解决方案。

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

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

URI img = f.toURI();
URL umg = img.toURL();
icon = new ImageIcon(umg);  

此代码保持与打开的文件的连接并阻止编辑图像文件的其他进程。 (仅限动画 GIF 文件,Windows 系统)

这是新代码:

//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 被关闭,因此该文件上的 block 被释放。 (如果“is.close()”行未执行,则文件仍在处理中并阻止其他写入操作)

关于java - 如何使 Java URI 类停止使用文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61294055/

相关文章:

java - 在运行时在 Jframe 上添加文本字段

Java JCheckBox Action 监听器

java - removeMouseListener() 不起作用(Java)

java - 当 Infinispan 作为数据网格时,是否可以配置 "unique"约束?

php - 在 Windows 上安装 codeigniter sparks 管理器

windows - 更换开始菜单

regex - 在 PowerShell 中,如果环境变量(如 $SystemRoot$)是字符串的一部分,我该如何转换它们?

java - 将 cosmosDB sdk 与 java 一起使用时出现 ALLOW_TRAILING_COMMA 错误

java - 我应该将 html 和 java 文件放在 Apache Wicket 的同一个包(文件夹)中吗?

Java:多字节字符串长度