如题:本人想用IO流读取个文件将文件信息添加到SWT的Table中,但是文件太大,速度较慢,所以想使用多线程一次读100或1000行,将这些行添加到Tale后在读指定行数,应该怎么实现?谢谢各位高手

解决方案 »

  1.   

    java有个MappedByteBuffer类,他的作用可以把一个文件映射到内存中,然后就能像访问数组一样去读取这个文件。这样不用多线程也可以,你试试public void readResource() {
      long fileLength = 0;
      final int BUFFER_SIZE = 0x300000;// 3M的缓冲
      
      for(String fileDirectory:this.readResourceDirectory())//得到文件存放路径,我这里使用了一个方法从XML文件中读出文件的
                  //存放路径,当然也可以用绝对路径来代替这里的fileDriectory
      {
       File file = new File(fileDirectory);
       fileLength = file.length();
       try {
        MappedByteBuffer inputBuffer =
         new RandomAccessFile(file,"r").getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileLength);//读取大文件
        
        byte[] dst = new byte[BUFFER_SIZE];//每次读出3M的内容
        
        for(int offset=0; offset < fileLength; offset+= BUFFER_SIZE)
        {
           if(fileLength - offset >= BUFFER_SIZE)
           {
              for(int i = 0;i < BUFFER_SIZE;i++)
              dst = inputBuffer.get(offset + i);
           }
           else
           {
             for(int i = 0;i < fileLength - offset;i++)
                   dst = inputBuffer.get(offset + i);
            }
           //将得到的3M内容给Scanner,这里的XXX是指Scanner解析的分隔符
           Scanner scan = new Scanner(new ByteArrayInputStream(dst)).useDelimiter("XXX");
           while(scan.hasNext())
           {
               //这里为对读取文本解析的方法
           }        
          scan.close();
         }
       } catch (Exception e)
       {
        e.printStackTrace();
       }
      }
    }
      

  2.   

    Dintin请问有相关的实力代码么?参考下,谢谢
      

  3.   

    多线程,每个线程分别读取2万行左右。
      //线程,按指定行数读取文本文件内容
      public class NewThread implements Runnable
      {
        String ThreadName; //线程名称
        Thread ThreadObject;  //线程
        ...
         NewThread(String threadname , String filename)
        {
          ThreadName = threadname; 
          FileName = filename; 
          String ReturnStr = "";
         new Thread(this , ThreadName).start();
        }     public void run()
        {
          try
          {
            int CurrentLineNo = 0; //当前行号
             System.out.println(ThreadName + "开始干活了");
            long Time1 = System.currentTimeMillis();
            File f = new File(FileName);
            if(f.exists() == false || f.isDirectory() || f.canRead() == false)
            {
              System.out.println("打文件错误!");
            }        FileReader fr = new FileReader(FileName);
            BufferedReader read = new BufferedReader(fr);
            while((sline = read.readLine()) != null)
            { tmpsline1 = sline; //操作前的文本
              if(sline.length() > 0 && sline.indexOf(",") > 0)
              {
                //按行写入数据
                try
                {
                  SQL[i] = GetSpecialSQL(sline);//由该行文本取得要执行的SQL
                    ...
                  每50条语句批量操作一次
                    stms.executeBatch(SQL); 
                  ...                }
                catch(Exception e)
                { TxtlineCount--;
                  RecordErrorLog(sline + e.toString()); //记录错误
                  e.printStackTrace();
                }
              }
              CurrentLineNo++; //有效行,行数才加
            }        read.close();
            fr.close();
            stmt.close(); //关闭数据库操作对象
             con.close(); //关闭数据库连接
             f.delete(); //删除临时文件
        }  //创建线程读取文本并写库
      public TestReadFileAndIntoDB(){
        int PreBufferLines = 20000; //每个Buffer的文本行数
        byte b[] = new byte[1024];
        NewThread UpDBThread; //定义一个更新数据库的进程    long FileTotalLines[] = {0 , 0}; //
        long Realcount = 0 , TotalCount = 0;
        File f = new File(fileName);
        if(f.exists() == false || f.isDirectory() || f.canRead() == false)
        {
          System.out.println("打文件错误!");
          return "打文件错误!";
        }
        try
        { //E:\JavaProject\UpdateDBTest\defaultroot/file/testFile.txt //约17万行,40M
          String sline;
          //先创建临时文件名 格式:路径+源文件名+序号+扩展名
          TempFileName = TrueFullPath + "/" + TrueFileName + j + "." + TrueExtName;
          System.out.println("正在读取源文件" + TrueFileName + "." + TrueExtName + "并自动生成临时文件..");
          FileReader fr = new FileReader(fileName);
          BufferedReader read = new BufferedReader(fr);
          //FileWriter fw = new FileWriter(TempFileName);
          //BufferedWriter write = new BufferedWriter(fw);
          File fw = new File(TempFileName);
          FileOutputStream write = new FileOutputStream(fw);
          try
          {
            while((sline = read.readLine()) != null)
            {
              if(sline.length() > 0)
              {
                //FileContentList.add(sline);
                Realcount++; //该行不为空,则有效行数加1
                if(i < PreBufferLines)
                { //当前行数小于指定的分割点时,写入原定的临时文件
                  sline += "\r\n";  //加上回车换行
                  b=sline.getBytes() ;//转换成二制流
                  write.write(b);              i++;
                }
                else
                { //当前行大小分割点时,要换临时文件名了
                  j++;
                  //关闭原来的读写文件的对象。并按新临时文件重新打开
                  write.close();
                  //fw.close();
                  new NewThread(j + "-" + (Realcount - 1) , TempFileName ); //执行线程
                  //生成新的文件临时文件名
                  TempFileName = TrueFullPath + "/" + TrueFileName + j + "." + TrueExtName;
                  fw = new File(TempFileName);
                  write = new FileOutputStream(fw);
                  sline += "\r\n";  //加上回车换行
                  b=sline.getBytes() ;//转换成二制流
                  write.write(b);
                  i = 1;
                }          }
              TotalCount++; //不管该行是否空,总行数加1
            }      }
          catch(Exception e)
          {
           System.out.println("读写文件并开线程的错误:" + e.toString());
          }
                write.close();
          //fw.close();
          new NewThread("最后一线程:" + Realcount , TempFileName); //执行线程
          read.close(); //读文件关闭
          fr.close(); //
          read = null;
          fr = null;
          f = null;
      }
    这段代码是几年给客户网站做的一个导数据的程序。
    主要功能是多线程分块读取源文件,多线程导入数据。
    采取的是分块读取并生成临时文件,然后在线程内读取临时文件并导入。
    LZ可看看历史贴子,当时也遇到不少问题,主要是RedHat9 Linux 环境下程序运行可能与windows下有差异。
    http://topic.csdn.net/t/20040424/18/3004091.html
    http://topic.csdn.net/t/20040414/10/2962641.html
    http://topic.csdn.net/t/20040202/10/2694219.html
      

  4.   

    个人意见:MappedByteBuffer 主要是用来处理一个文件被多次读取的情况,而且对读取大文件性能没有太大的提升。