使用字节流读写文件

Java提供了一些类和方法让你读写文件,当然,最常用的文件类型还是磁盘文件.在Java中,所有的文件都是由字节组成的,而且Java也提供了从文件读字节的方法.因此,使用字节流来读写文件是很常见的.然而,Java可以让你将一个由字节组成的文件包含在一个基于字符的对象中.
为创建一个与文件相链接的字节流,需要使用FileInputStream和FileOutputStream.要打开文件,只需要创建这些类的一个对象,将文件名指定为构造函数的一个实参.一旦文件被打开,就可以对其进行读取或写入.
1.从文件输入
通过创建一个FileInputStream对象可以打开一个用于输入的文件.下面是他最常用的构造函数:
FileInputStream(String fileName) throws FileNotFoundException
这里,fileName指定了你想要打开的文件的名称.如果该文件不存在,就会抛出FileNotFoundException,这是IOException的一个子类.
需要使用read()方法来读取文件,我们将使用read()版本如下所示:
int read() throws IOException;
每次read()被调用时,他都会从文件读取一个字节,并将其做为整数值返回.当到达文件结尾时,read()会返回-1.出现错误时,会抛出IOException.因此,这个read()版本与用来从控制台读取数据的版本相同.
当处理完文件后,必须调用close()来关闭他,其基本形式如下所示:
void close() throws IOException
关闭文件可以释放分配给文件的系统资源,以允许这些资源被其他文件使用.不关闭文件会导致内存泄漏,因为不再使用的资源仍然会占用分配的内存空间.
下面的程序使用read()来输入文件,并显示文本文件的内容,文件名被指定为一个命令行实参.注意try/catch块如何处理可能发生的IO错误.
public class test2
{
    // @param args
    public static void main(String args[])
    throws IOException
    {
     int i;
        String filePath = "test.txt";
        FileInputStream fin;
        
        try {
            fin = new FileInputStream(filePath);
        } catch(FileNotFoundException exc) {
            System.out.println(exc.toString());
            return;
        }
        
        try {
            do {
                i = fin.read();
            } while(i != -1);
        } catch(IOException exc) {
            System.out.println("Error Reading  file");
        }
        
        try {
            fin.close();
        }catch(IOException exc) {
            System.out.println("Error closing  file");
        }
        
        System.out.println("done");
        
    }
}
注意,前面的代码在读取文件的try代码块完成后关闭了文件流.虽然这种方法在某些情况下有用,但是Java提供了一种在通常情况下更好的方法,即,在finally代码中调用close(),在这种方法中,访问文件的所有方法都包含在一个try代码块中,finally代码用来关闭文件.这样,无论try代码块如何终止,文件都会被关闭.使用前面的示例,下面演示了如何重新编写读取文件的try代码块:
        try {
            do {
                i = fin.read();
            } while(i != -1);
        } catch(IOException exc) {
            System.out.println("Error Reading  file");
        }finally {
            try {
                fin.close();
            }catch(IOException exc) {
                System.out.println("Error  closing file");
            }
        }
这种方法的优点之一是,如果访问文件的代码由于某种与IO无关的异常而终止,finally代码块仍然会关闭文件.虽然在这个例子(和其他多数示例程序)中这不是一个问题,因为在发生未预料到的异常时程序简单的结束了,但是在大型程序中却可能造成很多麻烦.使用finally可以避免这些麻烦.
有时候,将程序中打开文件和访问文件的部分放到一个try代码块(而不是分开他们),然后使用一个finally代码块关闭文件,这样更加简单:
    public static void main(String args[])
    throws IOException
    {
     int i;
        String filePath = "test.txt";
        FileInputStream fin = null;
        
        try {
            fin = new FileInputStream(filePath);
            do {
                i = fin.read();
            } while(i != -1);
        } catch(FileNotFoundException exc) {
            System.out.println(exc.toString());
        } catch(IOException exc) {
            System.out.println("Error Reading  file");
        }finally {
            try {
                if(fin != null) fin.close();
            }catch(IOException exc) {
                System.out.println("Error  closing file");
            }
        }
        
        System.out.println("done");
        
    }
问:我注意到当文件到达结尾时,read()返回-1,然而当文件出错时,却不返回任何特殊值,为什么?
答:在Java中,错误由异常来处理.因此,如果read()或是其他任何IO方法返回一个值,这就意味着没有错误发生.这比使用特殊代码来处理IO错误要清楚的多.
2.写入文件
为打开一个文件用于输出,需要创建一个FileOutputStream对象.下面是他们的两个最常用的构造函数.
FileOutputStream(String fileName) throws FileNotFoundException
FileOutputStream(String fileName,boolean append) throws FileNotFoundException
如果无法创建文件,就会抛出FileNotFoundException.在第一种形式中,当一个输出文件打开后,以前任何已有同名文件都会被销毁.在第二种形式中,如果apend为true,那么输出会添加到文件的末尾.否则,文件会被重写.
需要使用write()方法来写入文件.他的最简形式如下所示:
void write(int byteval) throws IOExcetion
该方法向文件写入由byteval指定的字节.尽管byteval被声明为整数,但他只有低8位可以写入文件.如果在写的过程中发生错误,就会抛出IOException.
一旦处理完输出文件,就必须使用close()关闭他,如下所示:
void close() throws IOException
关闭文件可以释放分配给文件的系统资源,以允许这些资源被其他文件使用.他还可以确保保存在磁盘缓冲区中的输出都真正写入到了磁盘.
下面的程序复制了一个文本文件,源文件名和目的文件名都在命令行中指定:
    public static void main(String args[])
    throws IOException
    {
     int i;
        String filePath = "test.txt";
        String filePath2 = "test_copy.txt";
        FileInputStream fin = null;
        FileOutputStream fout = null;
        
        try {
            fin = new FileInputStream(filePath);
            fout = new  FileOutputStream(filePath2);
            do {
                i = fin.read();
                if(i!=-1) fout.write(i);
            } while(i != -1);
        } catch(FileNotFoundException exc) {
            System.out.println(exc.toString());
        } catch(IOException exc) {
            System.out.println("Error Reading  file");
        }finally {
            try {
                if(fin != null) fin.close();
                if(fout != null) fout.close();
            }catch(IOException exc) {
                System.out.println("Error  closing file");
            }
        }
        System.out.println("done");
    }