`

文件读写工具类

 
阅读更多
1、文本文件读写工具类
view plain
<span style="font-size:16px;">package mine.util; 
 
import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.FileReader; 
import java.io.FileWriter; 
import java.io.IOException; 
 
/**
* 此工具类用于文本文件的读写

* @author Touch
*/ 
public class TextFile { 
    // 读取指定路径文本文件 
    public static String read(String filePath) { 
        StringBuilder str = new StringBuilder(); 
        BufferedReader in = null; 
        try { 
            in = new BufferedReader(new FileReader(filePath)); 
            String s; 
            try { 
                while ((s = in.readLine()) != null) 
                    str.append(s + '\n'); 
            } finally { 
                in.close(); 
            } 
        } catch (IOException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 
        return str.toString(); 
    } 
 
    // 写入指定的文本文件,append为true表示追加,false表示重头开始写, 
    //text是要写入的文本字符串,text为null时直接返回 
    public static void write(String filePath, boolean append, String text) { 
        if (text == null) 
            return; 
        try { 
            BufferedWriter out = new BufferedWriter(new FileWriter(filePath, 
                    append)); 
            try { 
                out.write(text); 
            } finally { 
                out.close(); 
            } 
        } catch (IOException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 
    } 

</span> 

view plain
<span style="font-size:16px;">package mine.util; 
 
public class TestTextFile { 
    public static void main(String[] args) { 
        TextFile.write("file/textfile.txt", false, 
                "这是一个文本文件的读写测试\nTouch\n刘海房\n男\n"); 
        TextFile.write("file/textfile.txt", true, "武汉工业学院\n软件工程"); 
        System.out.println(TextFile.read("file/textfile.txt")); 
    } 

</span> 

2、二进制文件读写工具类
view plain
<span style="font-size:16px;">package mine.util; 
 
import java.io.BufferedInputStream; 
import java.io.BufferedOutputStream; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
 
/**
* 此工具类用于二进制文件的读写

* @author Touch
*/ 
public class BinaryFile { 
    // 把二进制文件读入字节数组,如果没有内容,字节数组为null 
    public static byte[] read(String filePath) { 
        byte[] data = null; 
        try { 
            BufferedInputStream in = new BufferedInputStream( 
                    new FileInputStream(filePath)); 
            try { 
                data = new byte[in.available()]; 
                in.read(data); 
            } finally { 
                in.close(); 
            } 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
        return data; 
    } 
 
    // 把字节数组为写入二进制文件,数组为null时直接返回 
    public static void write(String filePath, byte[] data) { 
        if (data == null) 
            return; 
        try { 
            BufferedOutputStream out = new BufferedOutputStream( 
                    new FileOutputStream(filePath)); 
            try { 
                out.write(data); 
            } finally { 
                out.close(); 
            } 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 

</span> 


view plain
<span style="font-size:16px;">package mine.util; 
 
import java.util.Arrays; 
 
public class TestBinaryFile { 
    public static void main(String[] args) { 
        BinaryFile.write("file/binaryfile.dat", new byte[] { 1, 2, 3, 4, 5, 6, 
                7, 8, 9, 10, 'a', 'b', 'c' }); 
        byte[] data = BinaryFile.read("file/binaryfile.dat"); 
        System.out.println(Arrays.toString(data)); 
    } 

</span> 


3、对象读写工具类(有问题,在读取多个对象时有问题,怎样把一个对象文件中的所有对象读出来?)
view plain
<span style="font-size:16px;">package mine.util; 
 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
 
/**
* 此类用于对象的读写

* @author Touch
*/ 
public class ObjectFile { 
    // 把一个对象写入文件,isAppend为true表示追加方式写,false表示重新写 
    public static void write(String filePath, Object o, boolean isAppend) { 
        if (o == null) 
            return; 
        try { 
            ObjectOutputStream out = new ObjectOutputStream( 
                    new FileOutputStream(filePath, isAppend)); 
            try { 
                out.writeObject(o); 
            } finally { 
                out.close(); 
            } 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
 
    // 把一个对象数组写入文件,isAppend为true表示追加方式写,false表示重新写 
    public static void write(String filePath, Object[] objects, boolean isAppend) { 
        if (objects == null) 
            return; 
        try { 
            ObjectOutputStream out = new ObjectOutputStream( 
                    new FileOutputStream(filePath, isAppend)); 
            try { 
                for (Object o : objects) 
                    out.writeObject(o); 
            } finally { 
                out.close(); 
            } 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
 
    // 读取对象,返回一个对象 
    public static Object read(String filePath) { 
        Object o = null; 
        try { 
            ObjectInputStream in = new ObjectInputStream(new FileInputStream( 
                    filePath)); 
            try { 
                o = in.readObject(); 
            } finally { 
                in.close(); 
            } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        return o; 
    } 
 
    // 读取对象,返回一个对象数组,count表示要读的对象的个数 
    public static Object[] read(String filePath, int count) { 
        Object[] objects = new Object[count]; 
        try { 
            ObjectInputStream in = new ObjectInputStream(new FileInputStream( 
                    filePath)); 
            try { 
                for (int i = 0; i < count; i++) { 
                    //第二次调用in.readObject()就抛出异常,这是为什么? 
                    objects[i] = in.readObject(); 
                } 
            } finally { 
                in.close(); 
            } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        return objects; 
    } 

</span> 


view plain
<span style="font-size:16px;">package mine.util; 
 
import java.io.Serializable; 
 
public class TestObjectFile { 
    public static void main(String[] args) { 
        ObjectFile.write("file/object1", new Person(), false); 
        ObjectFile.write("file/object1", new Person(), true); 
        ObjectFile.write("file/object1", new Person[] { new Person("Touch", 1), 
                new Person("Rainbow", 0), new Person() }, true); 
        for (Object o : ObjectFile.read("file/object1", 5)) 
            ((Person) o).display(); 
    } 

 
class Person implements Serializable { 
    private String name = "刘海房"; 
    private int sex = 0; 
 
    Person(String name, int sex) { 
        this.name = name; 
        this.sex = sex; 
    } 
 
    Person() { 
    } 
 
    void display() { 
        System.out.println("my name is :" + name); 
        String s = (sex == 0) ? "男" : "女"; 
        System.out.println("性别:" + s); 
    } 
}</span> 

4、对象读写工具类(解决了3中的问题,能够写入及读取多个对象)
          3中到底问题出在哪呢?先来看一段ObjectOutputStream构造方法的源代码,此源代码来自jdk1.6版。
view plain
<span style="font-size:16px;">    public ObjectOutputStream(OutputStream out) throws IOException { 
    verifySubclass(); 
    bout = new BlockDataOutputStream(out); 
    handles = new HandleTable(10, (float) 3.00); 
    subs = new ReplaceTable(10, (float) 3.00); 
    enableOverride = false; 
    </span><span style="font-size:16px;"><span style="color:#ff0000;">writeStreamHeader(); 
</span>   bout.setBlockDataMode(true); 
        if (extendedDebugInfo) { 
        debugInfoStack = new DebugTraceInfoStack(); 
    } else { 
        debugInfoStack = null; 
        }    
    }</span> 

这段代码中我们只需要关注writeStreamHeader();方法,这个方法在源代码中的解释是
view plain
<span style="font-size:16px;"> /**
     * The writeStreamHeader method is provided so subclasses can append or
     * prepend their own header to the stream.  It writes the magic number and
     * version to the stream.
     *
     * @throws  IOException if I/O errors occur while writing to the underlying
     *      stream
     */</span> 
也就是说我们打开(new)一个ObjectOutputStream的时候,这个ObjectOutputStream流中就已经被写入了一些信息,这些信息会写入到我们的文件中。在第一次写入文件时,这些头部信息时需要的,因为ObjectInputStream读的时候会帮我们过滤掉。但是当我们追加写入一个文件时,这些头部信息也会写入文件中,读取的时候只会把文件第一次出现的头部信息过滤掉,并不会把文件中间的头部信息也过滤掉,这就是问题的根源所在。
      怎么解决呢?正如lichong_87提到的
      一、可以在每次写入的时候把文件中所有对象读出来,然后重新写入,这种方法效率比较低。
      二、如果不是第一次写入文件,在写入时去掉头部信息,怎么去掉呢?头部信息是在writeStreamHeader();方法中写入的,所以我们可以通过继承ObjectOutputStream来覆盖这个方法,如果不是第一次写入文件,这个方法什么也不做。
     下面是第二种解决方案的源代码及测试
view plain
<span style="font-size:16px;">package mine.util.io; 
 
import java.io.File; 
import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.io.OutputStream; 
 
/**
* 此类继承ObjectOutputStream,重写writeStreamHeader()方法,以实现追加写入时去掉头部信息
*/ 
public class MyObjectOutputStream extends ObjectOutputStream { 
    private static File f; 
 
    // writeStreamHeader()方法是在ObjectOutputStream的构造方法里调用的 
    // 由于覆盖后的writeStreamHeader()方法用到了f。如果直接用此构造方法创建 
    // 一个MyObjectOutputStream对象,那么writeStreamHeader()中的f是空指针 
    // 因为f还没有初始化。所以这里采用单态模式 
    private MyObjectOutputStream(OutputStream out, File f) throws IOException, 
            SecurityException { 
        super(out); 
    } 
 
    // 返回一个MyObjectOutputStream对象,这里保证了new MyObjectOutputStream(out, f) 
    // 之前f已经指向一个File对象 
    public static MyObjectOutputStream newInstance(File file, OutputStream out) 
            throws IOException { 
        f = file;// 本方法最重要的地方:构建文件对象,两个引用指向同一个文件对象 
        return new MyObjectOutputStream(out, f); 
    } 
 
    @Override 
    protected void writeStreamHeader() throws IOException { 
        // 文件不存在或文件为空,此时是第一次写入文件,所以要把头部信息写入。 
        if (!f.exists() || (f.exists() && f.length() == 0)) { 
            super.writeStreamHeader(); 
        } else { 
            // 不需要做任何事情 
        } 
    } 

</span> 


view plain
<span style="font-size:16px;">package mine.util.io; 
 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
 
/**
* 此类用于对象的读写

* @author Touch
*/ 
public class ObjectFile { 
    // 把一个对象写入文件,isAppend为true表示追加方式写,false表示重新写 
    public static void write(String filePath, Object o, boolean isAppend) { 
        if (o == null) 
            return; 
        try { 
            File f = new File(filePath); 
            MyObjectOutputStream out = MyObjectOutputStream.newInstance(f, 
                    new FileOutputStream(f, isAppend)); 
            try { 
                out.writeObject(o); 
            } finally { 
                out.close(); 
            } 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
 
    // 把一个对象数组写入文件,isAppend为true表示追加方式写,false表示重新写 
    public static void write(String filePath, Object[] objects, boolean isAppend) { 
        if (objects == null) 
            return; 
        try { 
            File f = new File(filePath); 
            MyObjectOutputStream out = MyObjectOutputStream.newInstance(f, 
                    new FileOutputStream(f, isAppend)); 
            try { 
                for (Object o : objects) 
                    out.writeObject(o); 
            } finally { 
                out.close(); 
            } 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
 
    // 读取对象,返回一个对象 
    public static Object read(String filePath) { 
        Object o = null; 
        try { 
            ObjectInputStream in = new ObjectInputStream(new FileInputStream( 
                    filePath)); 
            try { 
                o = in.readObject(); 
            } finally { 
                in.close(); 
            } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        return o; 
    } 
 
    // 读取对象,返回一个对象数组,count表示要读的对象的个数 
    public static Object[] read(String filePath, int count) { 
        Object[] objects = new Object[count]; 
        try { 
            ObjectInputStream in = new ObjectInputStream(new FileInputStream( 
                    filePath)); 
            try { 
                for (int i = 0; i < count; i++) { 
                     
                    objects[i] = in.readObject(); 
                } 
            } finally { 
                in.close(); 
            } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        return objects; 
    } 

</span> 


view plain
<span style="font-size:16px;">package mine.util.io; 
 
import java.io.Serializable; 
 
public class TestObjectFile { 
    public static void main(String[] args) { 
        ObjectFile.write("file/t.dat", new Person(), false); 
        ObjectFile.write("file/t.dat", new Person(), true); 
        ObjectFile.write("file/t.dat", new Person[] { new Person("Touch", 1), 
                new Person("Rainbow", 0), new Person() }, true); 
        for (Object o : ObjectFile.read("file/t.dat", 5)) 
            ((Person) o).display(); 
    } 

 
class Person implements Serializable { 
    private static final long serialVersionUID = 1L; 
    private String name = "刘海房"; 
    private int sex = 0; 
 
    Person(String name, int sex) { 
        this.name = name; 
        this.sex = sex; 
    } 
 
    Person() { 
    } 
 
    void display() { 
        System.out.println("my name is :" + name); 
        String s = (sex == 0) ? "男" : "女"; 
        System.out.println("性别:" + s); 
    } 
}</span> 

运行结果:
my name is :刘海房
性别:男
my name is :刘海房
性别:男
my name is :Touch
性别:女
my name is :Rainbow
性别:男
my name is :刘海房
性别:男
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics