机器学习和生物信息学实验室联盟

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
12
返回列表 发新帖
楼主: hsc
打印 上一主题 下一主题

关于Java读写文件速度的测试

  [复制链接]
11#
发表于 2012-3-27 20:57:16 | 只看该作者
本帖最后由 xmubingo 于 2012-3-27 21:05 编辑
hsc 发表于 2012-3-27 20:32
确实是编码的问题,但是使用重新编码之后,ReadAccessFile读取一行写入一行,380M的文件需要400多秒,而B ...


我可以举个例子。
1)A的读取方法:有个缓冲区,缓冲区大小为1000。每次读取数据先判断在不在我的内存缓冲区中,如果不再就再从硬盘连续读取1000.
2)B的读取方法:没有缓冲区,每次都从硬盘直接读取数据。
现在我让A和B读1000大小的内容,分成1000次读,每次读1的大小。

对于A来说,只需要一次访问硬盘,1000次访问内存。
对于B来说,需要1000次访问硬盘。

已知访问一次硬盘的时间是一次访问内存时间的百倍。

这就是本科操作系统课程缓冲区的优势。你可以再做个实验。BufferedReader的缓冲区大小是8K。让两种方法每次读8bytes。这样就没有编码的差别。效果应该也是BufferedReader好。
回复 支持 反对

使用道具 举报

12#
 楼主| 发表于 2012-3-28 00:41:35 | 只看该作者
xmubingo 发表于 2012-3-27 20:57
我可以举个例子。
1)A的读取方法:有个缓冲区,缓冲区大小为1000。每次读取数据先判断在不在我的内存 ...

No,效果还是RandomAccess好~
回复 支持 反对

使用道具 举报

13#
发表于 2012-3-28 09:24:40 | 只看该作者
本帖最后由 xmubingo 于 2012-3-28 09:25 编辑
hsc 发表于 2012-3-28 00:41
No,效果还是RandomAccess好~


完整代码文件?时间?
回复 支持 反对

使用道具 举报

14#
 楼主| 发表于 2012-3-28 12:01:05 | 只看该作者
xmubingo 发表于 2012-3-28 09:24
完整代码文件?时间?
  1. BufferedReader br = new BufferedReader(new FileReader(args[0]));
  2.         BufferedWriter bw=new BufferedWriter(new FileWriter(args[1]));
  3.         String line;
  4. //        while((line=br.readLine())!=null)
  5. //        {
  6. //                bw.write(line);
  7. //                bw.newLine();
  8. //        }
  9.         int count;
  10.         char[] buffer=new char[1024*8];
  11.         while((count=br.read(buffer))!=-1)
  12.         {
  13.                 //System.out.println(count);
  14.                 if(count!=buffer.length)
  15.                 {
  16.                         char[] t=new char[count];
  17.                         for(int i=0;i<count;++i)
  18.                         {
  19.                                 t[i]=buffer[i];
  20.                         }
  21.                         bw.write(t);
  22.                 }
  23.                 else bw.write(buffer);
  24.         }
  25.         bw.flush();
  26.         bw.close();
  27.         br.close();/**/
复制代码
第一次:6.155s
第二次:5.843s
  1. RandomAccessFile read = new RandomAccessFile(args[0],"r");   
  2.         RandomAccessFile writer = new RandomAccessFile(args[1],"rw");   
  3.         byte[] b = new byte[1024*8];
  4.         int count;
  5. //        String line;
  6. //        while((line=read.readLine())!=null)
  7. //        {
  8. //                line+="\r\n";
  9. //                writer.writeBytes(new String(line.getBytes(),"GBK"));
  10. //                //writer.writeBytes(new String("\r\n","gb2312"));
  11. //        }
  12.         while((count=read.read(b))!=-1)
  13.         {  
  14.                 //System.out.println(count);
  15.                 if(count!=b.length)
  16.                 {
  17.                         byte[] t=new byte[count];
  18.                         for(int i=0;i<count;++i)
  19.                                 t[i]=b[i];
  20.                         writer.write(t);
  21.                 }
  22.                 else writer.write(b);   
  23.         }  
  24.         writer.close();   
  25.         read.close();/**/
复制代码
第一次:0.486s
第二次:0.495s

如果说char类型的是双字节的话,我设置成1024*4时间不变
回复 支持 反对

使用道具 举报

15#
发表于 2012-3-28 13:23:58 | 只看该作者
本帖最后由 xmubingo 于 2012-3-28 13:55 编辑
hsc 发表于 2012-3-28 12:01
第一次:6.155s
第二次:5.843s第一次:0.486s
第二次:0.495s


晕!

BufferedReader是自带缓冲区的,可以通过参数设置缓冲区的大小,BufferedReader(Reader, int size),你把它设置成8*1024bytes.

而RandomAccessFile是不带缓冲区的。

你就每次
while(没有读完){
读8bytes数据
写8bytes数据


每次读的是8bytes不是8*1024bytes也不是8*1024char.

你现在每次读的是8KB,相当于BufferedReader没有发挥缓冲区的价值,反而还要浪费时间在填充缓冲区上,当然时间多了。

读1275KB的文件效果!
  1. package test;
  2. import java.io.*;
  3. public class testforbuffer {
  4.         public static void main(String[] args) throws Exception
  5.         {
  6.         BufferedReader br = new BufferedReader(new FileReader("c:\\testin.txt"),8*1024);//缓冲区大小8*1024byte
  7.         BufferedWriter bw=new BufferedWriter(new FileWriter("c:\\testout.txt"));
  8.         int count;
  9.         char[] buffer=new char[4];//用char读8byte
  10.         Long startTime = System.currentTimeMillis();
  11.         while((count=br.read(buffer))!=-1)
  12.         {
  13.                 //System.out.println(count);
  14.                 if(count!=buffer.length)
  15.                 {
  16.                         char[] t=new char[count];
  17.                         for(int i=0;i<count;++i)
  18.                         {
  19.                                 t[i]=buffer[i];
  20.                         }
  21.                         bw.write(t);
  22.                 }
  23.                 else bw.write(buffer);
  24.         }
  25.         bw.flush();
  26.         bw.close();
  27.         br.close();
  28.         Long endTime = System.currentTimeMillis();
  29.         System.out.println("Totle time is "+ (endTime - startTime) + "milliseconds");
  30.         
  31.         //////////////////////////////////////////////////////////////
  32.         
  33.         RandomAccessFile read = new RandomAccessFile("c:\\testin.txt","r");   
  34.         RandomAccessFile writer = new RandomAccessFile("c:\\testout.txt","rw");   
  35.         byte[] b = new byte[8];//读8byte

  36.         startTime = System.currentTimeMillis();
  37.         while((count=read.read(b))!=-1)
  38.         {  
  39.                 //System.out.println(count);
  40.                 if(count!=b.length)
  41.                 {
  42.                         byte[] t=new byte[count];
  43.                         for(int i=0;i<count;++i)
  44.                                 t[i]=b[i];
  45.                         writer.write(t);
  46.                 }
  47.                 else writer.write(b);   
  48.         }
  49.         writer.close();   
  50.         read.close();
  51.         endTime = System.currentTimeMillis();
  52.         System.out.println("Totle time is "+ (endTime - startTime) + "milliseconds");
  53.         }
  54. }
复制代码
输出:
Totle time is 43milliseconds
Totle time is 871milliseconds


BufferedReader只要43毫秒。RandomAccessFile要871毫秒。

缓冲区就是这个作用啊!当你读的东西比较小,比如读一行的时候,我就不需要再向硬盘要数据,而是向内存直接取。这就是为什么我们实验室要用BufferedReader,因为我们都是处理一行行。苍天啊...还要我怎么解释。
回复 支持 反对

使用道具 举报

16#
 楼主| 发表于 2012-3-28 17:44:42 | 只看该作者
xmubingo 发表于 2012-3-28 13:23
晕!

BufferedReader是自带缓冲区的,可以通过参数设置缓冲区的大小,BufferedReader(Reader, int s ...

哦,你说是八个字节是吧,我看成8K了,不过一般来说8个字节的缓冲区太小了,读起来会很慢,尽管在同一级别上比较,这个是快了点,但是用我设置的那个缓冲区长度,读380M的文件也只需要0.5s左右,在时间作为第一要素的选择上,感觉还是这样的比较好一点,不过当然了,每一种方式都有他的优点和缺点,针对特殊情况选择合适的读取方式才是王道~
回复 支持 反对

使用道具 举报

17#
发表于 2012-3-28 19:00:22 | 只看该作者
本帖最后由 xmubingo 于 2012-3-28 19:28 编辑
hsc 发表于 2012-3-28 17:44
哦,你说是八个字节是吧,我看成8K了,不过一般来说8个字节的缓冲区太小了,读起来会很慢,尽管在同一级别 ...


晕死。我这里根本没有什么八字节的缓冲区。缓冲区大小是8*1024,在定义BufferedReader的时候就设定了!我这里是任务每次要读8个字节的数据。那程序里边的buffer根本就不是缓冲区,是你定义的用来存放取出来的8字节内容啊。
你看好下面的程序我把buffer改成fuck,fuck指代你每次要读取数据的长度
  1. package test;
  2. import java.io.*;
  3. public class testforbuffer {
  4.         public static void main(String[] args) throws Exception
  5.         {
  6.         BufferedReader br = new BufferedReader(new FileReader("c:\\testin.txt"),8*1024);//缓冲区大小8*1024byte
  7.         BufferedWriter bw=new BufferedWriter(new FileWriter("c:\\testout.txt"));
  8.         int count;
  9.         char[] fuck=new char[4];//用char读8byte
  10.         Long startTime = System.currentTimeMillis();
  11.         while((count=br.read(fuck))!=-1)
  12.         {
  13.                 //System.out.println(count);
  14.                 if(count!=fuck.length)
  15.                 {
  16.                         char[] t=new char[count];
  17.                         for(int i=0;i<count;++i)
  18.                         {
  19.                                 t[i]=fuck[i];
  20.                         }
  21.                         bw.write(t);
  22.                 }
  23.                 else bw.write(fuck);
  24.         }
  25.         bw.flush();
  26.         bw.close();
  27.         br.close();
  28.         Long endTime = System.currentTimeMillis();
  29.         System.out.println("Totle time is "+ (endTime - startTime) + "milliseconds");
  30.         
  31.         //////////////////////////////////////////////////////////////
  32.         
  33.         RandomAccessFile read = new RandomAccessFile("c:\\testin.txt","r");   
  34.         RandomAccessFile writer = new RandomAccessFile("c:\\testout.txt","rw");   
  35.         byte[] b = new byte[8];//读8byte

  36.         startTime = System.currentTimeMillis();
  37.         while((count=read.read(b))!=-1)
  38.         {  
  39.                 //System.out.println(count);
  40.                 if(count!=b.length)
  41.                 {
  42.                         byte[] t=new byte[count];
  43.                         for(int i=0;i<count;++i)
  44.                                 t[i]=b[i];
  45.                         writer.write(t);
  46.                 }
  47.                 else writer.write(b);   
  48.         }
  49.         writer.close();   
  50.         read.close();
  51.         endTime = System.currentTimeMillis();
  52.         System.out.println("Totle time is "+ (endTime - startTime) + "milliseconds");
  53.         }
  54. }
复制代码
你可以把成BufferedReader的缓冲区设置成8M。然后每次读8k的数据,依然并且肯定是BufferedReader快!

只要你告诉我每次要读取的数据大小s,我把缓冲区设置成s的倍数。永远都是BufferedReader快!
回复 支持 反对

使用道具 举报

18#
 楼主| 发表于 2012-3-28 21:36:14 | 只看该作者
xmubingo 发表于 2012-3-28 19:00
晕死。我这里根本没有什么八字节的缓冲区。缓冲区大小是8*1024,在定义BufferedReader的时候就设定了!我 ...

好吧,其实我没有跟你争论什么,刚开始的我只是偶然之间测试了一下速度而已,仅供参考而已,你说的这一点,我确实没有考虑到,每一种方法都有他的优点和缺点,我们取长补短就好了
回复 支持 反对

使用道具 举报

19#
发表于 2012-3-28 22:17:56 | 只看该作者
本帖最后由 xmubingo 于 2012-3-28 22:21 编辑
hsc 发表于 2012-3-28 21:36
好吧,其实我没有跟你争论什么,刚开始的我只是偶然之间测试了一下速度而已,仅供参考而已,你说的 ...


CSDN上的解答比我的回复更加尖锐。很少人愿意给你贴完整代码或者debug。
这是个很简单的缓冲区问题。你说得对,每种方法都有优势。
RandomAccessFile能很快的把整个文件取出来中,抛出去。
在网络应用中,他可以很快速的读取特定字节的内容送出去。
它还有seek,在网络传输的断点续传中,快速偏移的地址,然后读取数据。这些都是“随机访问”的优点。
当然网络传输一般同时需要大缓冲区的支持。
包括map法,它在内存允许范围内存取速度比谁都快。

我们不是在争论,这些细节问题一定要描述清楚,不然下次用到依然要百度google。
回复 支持 反对

使用道具 举报

20#
 楼主| 发表于 2012-3-28 23:33:48 | 只看该作者
xmubingo 发表于 2012-3-28 22:17
CSDN上的解答比我的回复更加尖锐。很少人愿意给你贴完整代码或者debug。
这是个很简单的缓冲区问题。你 ...

嗯,确实是,我相信以后大家在选用读取方式的时候,会有一个比较清晰的认识了,其实刚开始的时候我对他们的分类也都还不是很清楚,所以拿来做比较的时候就有点鲁莽了,学习了!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

机器学习和生物信息学实验室联盟  

GMT+8, 2024-11-23 09:25 , Processed in 0.074631 second(s), 17 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表