示例代码如下。它将目标文件和目录从一个位置复制到另一个位置。在通过网络处理文件时处理IO异常的最佳实践是什么?
我使用了printStackTrace(),但感觉这只是一个占位符,可以提供更好的解决方案。是否正在记录答案,并且除了实际记录“处理”错误外,还应该采取其他步骤吗?
谢谢您的反馈。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
This is a test program to copy a directory(s) & file(s) from one location to another.
*/
public class CopyTest{
public static void main(String[] args) {
//Declarations
String sourcePath = "I:\\MB\\PO";
String destPath = "C:\\testPO\\";
System.out.println("Source path: " + sourcePath);
System.out.println("Destination path: " + destPath);
File source = new File(sourcePath);
File dest = new File(destPath);
//Process
//Call to method copyUsingStream
long start = System.nanoTime(); //start recording how much time the copy takes.
copyUsingStream(source, dest); //method to copy the directory/files.
System.out.println("Time taken to copy the file: "+(System.nanoTime() -start) + " nanoseconds");
} //end main method
/**
The copyUsingStream method is a recursive method to copy folders and files from one location to another.
*/
private static void copyUsingStream(File source, File dest) {
if (!source.isDirectory()){
// If source is a file -> copy it to the new folder
InputStream inStream = null;
OutputStream outStream = null;
try {
inStream = new FileInputStream(source);
outStream = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = inStream.read(buffer)) > 0) {
outStream.write(buffer, 0, length);
}
} catch(IOException ioe) {
ioe.printStackTrace();
} finally {
try{
inStream.close();
outStream.close();
System.out.println("File copied from " + source + " to " + dest + "successfully");
} catch(IOException ioe2) {
ioe2.printStackTrace();
}
}
} else {
//If a directory -> create the directory inside the new destination
//List all contents
if (!dest.exists()) {
dest.mkdir();
System.out.println("Directory copied from " + source + " to " + dest + "successfully");
}
String folder_contents[] = source.list();
for (String file : folder_contents) {
File srcFile = new File(source, file);
File destFile = new File(dest, file);
copyUsingStream(srcFile, destFile);
}
}
} //end method copyUsingStream
} //end class CopyTest
这在很大程度上取决于您的应用程序。
无论如何仍会继续运行的应用程序(例如Web服务器,守护程序和批处理处理器)通常会将此类错误以及时间戳,线程ID以及可能的其他有用信息一起记录在文件中。
我对结合使用两个日志文件有很好的经验。
myapp.log
仅接收重要的消息,通常是警告和错误。该文件适用于普通用户和系统操作员。 debug.log
适用于开发人员。它提供调试消息,直到发生错误为止,但由于一切正常,因此没有消息。为此,需要一个内存缓冲区。 如果您对该缓冲区感兴趣,可以查看http://stefanfrings.de/bfUtilities/index.html。该网站为德语,但图书馆及其文档为英语。
在桌面GUI应用程序上,该应用程序立即中止了所请求的操作,最好在弹出窗口中显示一条简短的错误消息,并将详细信息(堆栈跟踪)隐藏在可扩展框中。不要忘记清楚地告诉用户什么操作失败。对于开发人员来说,异常本身可能已经足够清楚,但是普通用户希望使用的技术文章较少。例如:“从服务weather.com加载天气信息失败:连接失败”,然后是堆栈跟踪。
对于立即停止的控制台应用程序,我更喜欢直接在屏幕上查看由printStackTrace()
编写的堆栈跟踪。
如Stefan所说,这取决于应用程序。
一个好的经验法则是:除非您准备采取除打印或记录日志之外的特定操作,或者没有可以向其传播的调用者,否则不要捕获异常。
[如果您有复制文件的通用方法,则该方法不应假设其被调用的原因。它的工作是复制文件。只有成功完成该任务,它才应返回。如果未成功,则应抛出异常而不是返回。
因此,对于一般的复制方法,您需要将throws IOException
添加到方法签名中,并且方法本身具有零个try / catch块。这使呼叫者可以决定如何处理故障。 GUI应用程序可能会显示一个错误对话框。服务可能只是记录该异常,然后重试。
您自己应该只捕获并记录最高级别的异常。 GUI应用程序会在显示错误对话框之前立即将其记录下来。 (您可能还希望在对话框的可扩展“显示详细信息”部分中包含堆栈跟踪的文本。)服务可能具有主循环或主执行方法,在该方法中没有更高的调用方可以对其进行异常处理被传播,因此除了记录它外别无其他。