以下示例展示了如何使用streams复制文件。
private void copyWithStreams(File aSourceFile, File aTargetFile, boolean aAppend) {
log("Copying files with streams.");
ensureTargetDirectoryExists(aTargetFile.getParentFile());
InputStream inStream = null;
OutputStream outStream = null;
try{
try {
byte[] bucket = new byte[32*1024];
inStream = new BufferedInputStream(new FileInputStream(aSourceFile));
outStream = new BufferedOutputStream(new FileOutputStream(aTargetFile, aAppend));
int bytesRead = 0;
while(bytesRead != -1){
bytesRead = inStream.read(bucket); //-1, 0, or more
if(bytesRead > 0){
outStream.write(bucket, 0, bytesRead);
}
}
}
finally {
if (inStream != null) inStream.close();
if (outStream != null) outStream.close();
}
}
catch (FileNotFoundException ex){
log("File not found: " + ex);
}
catch (IOException ex){
log(ex);
}
}
private void ensureTargetDirectoryExists(File aTargetDir){
if(!aTargetDir.exists()){
aTargetDir.mkdirs();
}
}
private static void log(Object aThing){
System.out.println(String.valueOf(aThing));
}对于上面的代码片段,我对以下四点感到困惑:
1) Bucket的分配方式为: byte[] bucket =新字节32*1024,大小是否有选择标准,如32*1024
2)为什么它必须在这里“捕捉”?在编写程序时有没有包含catch的规则?
3)我也不太清楚try在这里的用法。似乎作者在这个程序中使用了嵌套的try。
发布于 2011-10-13 11:01:38
1)没有标准来定义字节数组的大小。在给定的代码中,它使用了32k字节,但您可以使用任何值。字节数组的大小和文件的大小决定了您将读取文件的次数,较大的缓冲区会导致较少的读取调用,但如果您正在处理小文件,则不是必需的。
2)每当在Java中使用可能抛出异常的方法时,都需要捕获该异常并对其执行某些操作。您可以在代码中处理异常(通常打印堆栈跟踪以进行调试),也可以抛出它,这意味着当有人使用您的代码时,需要捕获您的代码的异常。
3)他所做的是捕获两个可能的异常,并指定哪个异常会发生。因为FileNotFoundException扩展了IOException,他可以简单地使用一次尝试,并且只捕获IOException,所以他以这种方式编码,以知道IOException是FileNotFoundException还是任何其他IOException。就我个人而言,我不会以作者的方式编写代码,它不容易阅读。
也许重写代码会让你更容易理解其中的尝试和陷阱:
System.out.println("Copying files with streams.");
InputStream inStream = null;
OutputStream outStream = null;
try {
inStream = new BufferedInputStream(new FileInputStream(aSourceFile));
outStream = new BufferedOutputStream(new FileOutputStream(aTargetFile, aAppend));
} catch (FileNotFoundException ex){
// TODO Handle FileNotFoundException
ex.printStackTrace();
}
try {
byte[] bucket = new byte[32*1024];
int bytesRead = 0;
while(bytesRead != -1){
bytesRead = inStream.read(bucket); //-1, 0, or more
outStream.write(bucket, 0, bytesRead);
}
} catch (IOException ex){
// TODO Handle IOException
ex.printStackTrace();
} finally {
try {
if (inStream != null) inStream.close();
if (outStream != null) outStream.close();
} catch (IOException ex){
// TODO Handle IOException
ex.printStackTrace();
}
}它做同样的事情。
发布于 2011-10-13 10:22:33
try{}和catch{} (或finally{})语句块将其包围,也可以向上抛出异常,以调用此方法。在本例中,您有一条try{}语句,因此伴随的statements.catch和finally做了一些不必要的事情:他本可以使用一个try{},然后将finally{}块放在catch{}语句之后。相反,内部try{}在执行finally{}块之后将异常传递给外部try{}。在此之后,将根据抛出的Exception类型激活catch{}块。发布于 2011-10-13 10:23:55
1) 32 * 1024等于32 an,我认为这是格式化NTFS卷时的默认分配单位大小。通过匹配底层文件系统,可能会有一些性能提升,因为如果没有正确缓存,就不会重写磁盘的扇区。缓冲区越大,操作通常越流畅。不过,你不能在较小的设备上使用巨大的缓冲区(尽管手机的内存越来越大)
2)这里的陷阱可能非常烦人。如果您请求复制文件,而原始文件并不存在,那么您得到的只是一个日志,调用此方法的程序可能会假定它是有效的。此方法可能会重新抛出异常,调用程序将处理找不到的文件。IO问题也是如此。
3)最后是很重要的,因为无论发生什么,你都要确保资源是关闭的。如果在记录其他异常后关闭资源,那么使用嵌套的try语句并不会带来运行时的好处。(次要问题,如果在关闭inStream时发生异常抛出,outStream将不会关闭,任何其他异常都将丢失)。程序员可能会认为将close语句放在读取和写入附近看起来更干净,但它们很可能被移到外部try
https://stackoverflow.com/questions/7748657
复制相似问题