问题描述
我正在制作一个照片分类程序。 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!");
}
}
}