有A和B两个文件,现要将B文件追加在A文件末尾,生成新文件C。
方案一:读A和B文件到内存中,然后合并生成新文件C;
方案二:读B文件到内存中,并将之写到A文件的输出流中;
显然,第二种方案的效率要比第一种方案的效率高,因为只需要把B文件的数据读到内存中即可。
我想问问有没有办法使两个文件的数据都不用读到内存中进行合并呢?谢谢大家。

解决方案 »

  1.   

    那如果是几十GB的话,读的次数也很多啊,io的开销照样很大,继续求救,多谢大家。
      

  2.   

    自己看JDK 啊  java.io包
    用BufferedReader和BufferedWriter
      

  3.   

    给你个办法,在DOS下:copy a+b c就可以了
      

  4.   

    to7楼:这种方法也需要吧数据读到内存中,我是想问有没有不用把数据读到内存中的合并方法,多谢
    to8楼:这种方法在windows可以,但我们的程序有可能在其他系统上跑啊,谢谢哦
    继续求救~~~~~~~
      

  5.   

    to11楼:缓存到byte[]内也需要将数据读到内存啊,我想问有没有不用将数据读到内存中的方法啊,多谢~~~
      

  6.   

               我以为要和并2个文件必然需要使用到缓存          
                    File file = new File("D:\\test.txt");
    File file1 = new File("D:\\test1.txt");
    PrintWriter out = 
    new PrintWriter(new BufferedWriter(new FileWriter(file,true),1000));
    BufferedReader in
       = new BufferedReader(new FileReader(file1),1000);

    char[] ch = new char[1000];
    int length;
    while((length=in.read(ch))!=-1){
    out.write(ch);
    }
    out.close();
    in.close();
      

  7.   

    你想要在各种操作系统上跑你的程序,不读到内存合并,不太可能吧.
    文件最终是要操作系统管理的.
    二个文件合并,不读文件的内容,那只能把第一个文件结束标记去掉,在文件分配表中修改第一个文件占用的磁盘空间,把第二个文件占的磁盘空间链接到第一个文件占的空间上.
    好了,我说的是在windows系统上的操作,在其它系统上如果操作?那要看其它系统是怎么管理文件的.
    所以说,你的程序的操作本来就是和操作系统相关的,java又没有相关的API实现,不读到内存实现合并,不可能.
      

  8.   

    缓存应该一定是要用的 
    就算DOS 也是要的 除非在一个分区 
    要想使具体机型无关 DataArrayInputStream 和 DataArrayOutputStream 这两个类可以使用 
    其他就想不倒了
    等下面的答复
      

  9.   

    打开文件b ctrl+c 再打开文件a在最后使用 ctrl+v save 关闭a 重命名 c,,啥系统都行 
      

  10.   

    答:都不读到内存,还没有想到。
    若B文件较大(A在不大无所谓),可否考虑用FileChannel?
    A文件是用于写的,因而获取到A文件的FileChannel(写的Channel),
    B文件较大,用于读的,可获取B文件的FileChannel(读的Channel),并MAP到内存中[若文件小(K级加紧),则MAP到内存开销就不合算了],然后合并。因为FileChannel是使用本地操作系统的基础设施,比纯JAVA中的BUF应该性能快些。以上仅供楼主参考
      

  11.   

    不将数据读到内存你怎么操作啊?个人认为不可能,你就是打开A,crtl+c然后ctrl+v到b也是要读到内存的啊。
      

  12.   

    好,多谢各位,再问问17楼:一般多大的文件用FileChannel读写的方式比较合算呢?有没有一个经验值啊,再次感谢了,嘿嘿~~
      

  13.   

    FileChannel时,大的文件用来写,小的文件为读.把小的读进来,加到大的尾部.
    如果两个文件是有顺序的,那就不说了.
      

  14.   

    楼主不要再妄想了,对硬件知识稍微有点了解就应该知道,电脑的任何操作都是需要在内存中进行的,包括文件复制以及剪切,cpu只能在内存中寻址操作,不能够直接访问外部存储设备,必须通过内存调用指令来进行访问,也就是说,无论数据从何而来或向何而去,总要经过内存的。你只能尽量来减小内存的开销,但是不能绕过内存。
      

  15.   

    你可以一边读,一边往里面写啊。一个 BufferedReader 负责读,BufferedWriter 负责将刚读出来的一行写到文件中去。
      

  16.   


    如果用BufferedReader, BufferedWriter,两个文件都必须读一遍和写一遍吧?
      

  17.   

    思路(链表结构),可以参考windows的碎片整理
      

  18.   

    电脑课上老师说,文件系统就像一本书,有目录(记录开始地址和结束地址)(文件名)和章节(data区),又听说一个文件能不连续存储的(文件碎片)(链表结构),打住!!!
      

  19.   

    使用FileChannel类进行操作,是目前,我知道的最高效的方法。
    注意关注transferFrom方法和transferTo方法。
      

  20.   

    NIO中的管道传输应该是JAVA中间最快的了,一般的方法会在JVM堆里产生一个数据块,同时在JVM外也有个同样的冗余块,来回的拷,而管道只会在JVM堆里取一个数据引用指向JVM外,不会进行重复的拷贝操作
      

  21.   

     不知道可不可以用ObjcetOutputStream 和ObjectInputStream 不???   这可以写一个对象出去啊,,,,
      

  22.   

    import static java.lang.System.out;import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.util.Arrays;
    public class test {

    public static final int BUFSIZE = 1024 * 8;

    public static void mergeFiles(String outFile, String[] files) {
    FileChannel outChannel = null;
    out.println("Merge " + Arrays.toString(files) + " into " + outFile);
    try {
    outChannel = new FileOutputStream(outFile).getChannel();
    for(String f : files){
    FileChannel fc = new FileInputStream(f).getChannel(); 
    ByteBuffer bb = ByteBuffer.allocate(BUFSIZE);
    while(fc.read(bb) != -1){
    bb.flip();
    outChannel.write(bb);
    bb.clear();
    }
    fc.close();
    }
    out.println("Merged!! ");
    } catch (IOException ioe) {
    ioe.printStackTrace();
    } finally {
    try {if (outChannel != null) {outChannel.close();}} catch (IOException ignore) {}
    }
    }

    public static void main(String[] args) {
    mergeFiles("D:/output.txt", new String[]{"D:/in_1.txt", "D:/in_2.txt", "D:/in_3.txt"});
    }
    }
      

  23.   


    package 文本文件合并;import static java.lang.System.out;import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.util.Arrays;public class Test { public static final int BUFSIZE = 1024 * 8; public static void mergeFiles(String outFile, String[] files) {
    FileChannel outChannel = null;
    out.println("Merge " + Arrays.toString(files) + " into " + outFile);
    try {
    outChannel = new FileOutputStream(outFile,true).getChannel();
    for (String f : files) {
    FileChannel fc = new FileInputStream(f).getChannel();
    ByteBuffer bb = ByteBuffer.allocate(BUFSIZE);
    while (fc.read(bb) != -1) {
    bb.flip();
    outChannel.write(bb);
    bb.clear();
    }
    fc.close();
    }
    out.println("Merged!! ");
    } catch (IOException ioe) {
    ioe.printStackTrace();
    } finally {
    try {
    if (outChannel != null) {
    outChannel.close();
    }
    } catch (IOException ignore) {
    }
    }
    } public static void main(String[] args) {
    mergeFiles("D:/output.txt", new String[] { "D:/in_1.txt","D:/in_2.txt", "D:/in_3.txt" });
    }
    }
    我这个方法是33楼的哥们的。
    但是他的那个方法会覆盖原文件
    我的是追加。
    不知道楼主能不能看出来。!