在 FTP/Database 连接期间删除文件失败
Deleting file during FTP/Database connection failed
我的程序旨在加载图像、调整大小、保存、发送到 FTP 服务器,然后删除调整大小的图像。完整代码 - HERE
我遇到的问题是在从名为 AddBreedBuilder.java 的文件中按下 finish 按钮后:程序发送调整大小的文件到服务器,冻结约 1 秒,它正在尝试删除调整大小的文件(但这是不可能的)。
我尝试使用(目前这部分已从 java 文件中删除,第 165 行):File fileToDelete = new File(imgPath);
boolean success = fileToDelete.delete();
但 success
总是 false
。删除此文件的唯一方法是不要 运行 sendToFTP()
.
据我所知,我的程序在文件删除操作中正在使用这个文件,所以无法删除。
我的问题是:是否可以延迟文件删除直到程序解冻?
或者也许有办法在不保存的情况下发送调整大小的文件?
From what I think, my program is using this file during file delete operation, so it cannot be deleted.
没错。
原因是您的 sendToFTP
方法打开了它发送到服务器的文件,但它没有(永远)关闭它。由于文件仍处于打开状态,Windows 不会让应用删除它
解决方案:修改您的 sendToFTP
方法,使 FileInputStream
始终 关闭。
除了您提出的问题之外,代码本身还有一些问题,它会影响问题的答案。我稍后会解决这些问题。但是,首先要直接解决您的问题:
是的。您可以通过启动一个处理 FTP 传输的新线程来执行此操作,因为传输是作为 GUI 事件的结果启动的,因此它不会冻结您的应用程序。 (处理 GUI 的事件分派线程只启动新线程而不等待它完成。)在 sendToFTP()
中,执行:
public static void sendToFTP(String fileName, String name) {
Thread sender = new Thread() {
public void run() {
FTPClient client = new FTPClient();
try {
FileInputStream fis = new FileInputStream(new File(fileName));
client.connect("serwer1978625.home.pl");
client.login("nissmel@chooseyourpuppy.pl", MyBreed.getPassword());
client.changeWorkingDirectory("/breeds");
client.setFileType(FTP.BINARY_FILE_TYPE);
client.storeFile(name, fis);
// client.rename(fileName, name); // not necessary
client.logout();
// At this point you must close the FileInputStream, since that is what is using the file, as you noticed.
fis.close();
// TODO: your code to delete the file comes in here, if everything goes well
// Alternatively, you could do these in the finally block to run irrespective of how the above code executes
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
client.disconnect();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
};
// the event dispatch thread only starts the sender thread and exits this function,
// hence no freezing occurs
sender.start();
}
然后在调用函数中,buildAdd()
// ...
sendToFTP(imgPath, userBreedInfo[0] + ".jpg");
// ...
您绝对可以发送文件(更准确地说,文件内容)而无需生成文件。您可以直接将 BufferedImage
提供给 sendToFTP()
方法,然后将其转换为 client.storeFile()
所需的 InputStream
。在这种情况下,如果您在本地计算机上不需要它,您甚至根本不需要首先存储该文件。
public static void sendToFTP(BufferedImage bimage, String name) {
// ... some code
// Here we need an input stream for storeFile(), so we get that from an output stream
// produced in turn by the buffered image
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ImageIO.write(bimage, "png", outStream);
InputStream is = new ByteArrayInputStream(outStream.toByteArray());
// ... some code
client.storeFile(name, is);
// ... rest of code
}
然后在调用函数中,buildAdd()
// ...
sendToFTP(bimage, userBreedInfo[0] + ".jpg");
// ...
请注意 sendToFTP()
第二版签名的变化。你可以用不同的方式玩这个想法,而是用这个 InputStream
替换 buildAdd()
中的文件写入调用,然后将流传递给 sendToFTP()
.
备注
您可以使用 try-with-resources 习惯用法来确保上面使用的流自动关闭:请参阅
here 例如。
解决的其他问题:
- 存储在 FTP 端点后无需重命名文件:只需
第一次使用最终名称。
- 一定要关闭流。这就是导致您报告错误的原因。
- 在更好的情况下,无需首先在本地系统上创建文件(即在
buildAdd()
内)。
我的程序旨在加载图像、调整大小、保存、发送到 FTP 服务器,然后删除调整大小的图像。完整代码 - HERE
我遇到的问题是在从名为 AddBreedBuilder.java 的文件中按下 finish 按钮后:程序发送调整大小的文件到服务器,冻结约 1 秒,它正在尝试删除调整大小的文件(但这是不可能的)。
我尝试使用(目前这部分已从 java 文件中删除,第 165 行):File fileToDelete = new File(imgPath);
boolean success = fileToDelete.delete();
但 success
总是 false
。删除此文件的唯一方法是不要 运行 sendToFTP()
.
据我所知,我的程序在文件删除操作中正在使用这个文件,所以无法删除。
我的问题是:是否可以延迟文件删除直到程序解冻? 或者也许有办法在不保存的情况下发送调整大小的文件?
From what I think, my program is using this file during file delete operation, so it cannot be deleted.
没错。
原因是您的 sendToFTP
方法打开了它发送到服务器的文件,但它没有(永远)关闭它。由于文件仍处于打开状态,Windows 不会让应用删除它
解决方案:修改您的 sendToFTP
方法,使 FileInputStream
始终 关闭。
除了您提出的问题之外,代码本身还有一些问题,它会影响问题的答案。我稍后会解决这些问题。但是,首先要直接解决您的问题:
是的。您可以通过启动一个处理 FTP 传输的新线程来执行此操作,因为传输是作为 GUI 事件的结果启动的,因此它不会冻结您的应用程序。 (处理 GUI 的事件分派线程只启动新线程而不等待它完成。)在
sendToFTP()
中,执行:public static void sendToFTP(String fileName, String name) { Thread sender = new Thread() { public void run() { FTPClient client = new FTPClient(); try { FileInputStream fis = new FileInputStream(new File(fileName)); client.connect("serwer1978625.home.pl"); client.login("nissmel@chooseyourpuppy.pl", MyBreed.getPassword()); client.changeWorkingDirectory("/breeds"); client.setFileType(FTP.BINARY_FILE_TYPE); client.storeFile(name, fis); // client.rename(fileName, name); // not necessary client.logout(); // At this point you must close the FileInputStream, since that is what is using the file, as you noticed. fis.close(); // TODO: your code to delete the file comes in here, if everything goes well // Alternatively, you could do these in the finally block to run irrespective of how the above code executes } catch (IOException e) { e.printStackTrace(); } finally { try { client.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } }; // the event dispatch thread only starts the sender thread and exits this function, // hence no freezing occurs sender.start(); }
然后在调用函数中,
buildAdd()
// ... sendToFTP(imgPath, userBreedInfo[0] + ".jpg"); // ...
您绝对可以发送文件(更准确地说,文件内容)而无需生成文件。您可以直接将
BufferedImage
提供给sendToFTP()
方法,然后将其转换为client.storeFile()
所需的InputStream
。在这种情况下,如果您在本地计算机上不需要它,您甚至根本不需要首先存储该文件。public static void sendToFTP(BufferedImage bimage, String name) { // ... some code // Here we need an input stream for storeFile(), so we get that from an output stream // produced in turn by the buffered image ByteArrayOutputStream outStream = new ByteArrayOutputStream(); ImageIO.write(bimage, "png", outStream); InputStream is = new ByteArrayInputStream(outStream.toByteArray()); // ... some code client.storeFile(name, is); // ... rest of code }
然后在调用函数中,buildAdd()
// ...
sendToFTP(bimage, userBreedInfo[0] + ".jpg");
// ...
请注意 sendToFTP()
第二版签名的变化。你可以用不同的方式玩这个想法,而是用这个 InputStream
替换 buildAdd()
中的文件写入调用,然后将流传递给 sendToFTP()
.
备注 您可以使用 try-with-resources 习惯用法来确保上面使用的流自动关闭:请参阅 here 例如。
解决的其他问题:
- 存储在 FTP 端点后无需重命名文件:只需 第一次使用最终名称。
- 一定要关闭流。这就是导致您报告错误的原因。
- 在更好的情况下,无需首先在本地系统上创建文件(即在
buildAdd()
内)。