使用缓冲写入/读取器提高读取和写入大文件的速度

时间:2016-01-11 15:37:32

标签: java bufferedreader bufferedwriter

我想阅读文本文件并将每个单词转换为数字。然后为每个文件写入数字序列而不是新文件中的单词。我使用HashMap为每个单词分配了一个数字(标识符),例如,单词 apple 被分配给数字 10 ,所以每当我看到 apple 在文本文件中我在序列中写了 10 。我需要只有一个HashMap来防止为一个单词分配多个标识符。我编写了以下代码,但它处理文件很慢。例如,将大小为165.7 MB的文本文件转换为序列文件需要20个小时。我需要将具有相同大小的600文本文件转换为序列文件。我想知道有没有办法提高我的代码的效率。为每个文本文件调用以下函数。

public void ConvertTextToSequence(File file) {
    try{

        FileWriter filewriter=new FileWriter(path.keywordDocIdsSequence,true);
        BufferedWriter bufferedWriter= new BufferedWriter(filewriter);

        String sequence="";
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line = bufferedReader.readLine();
        while(line!=null)
        {
            StringTokenizer tokens = new StringTokenizer(line); 

                    String str;
                    while (tokens.hasMoreTokens()) 
                    {
                        str = tokens.nextToken();
                         if(keywordsId.containsKey(str))
                              sequence= sequence+" "+keywordsId.get(stmWord);
                         else
                         {
                              keywordsId.put(str,id);
                              sequence= sequence+" "+id;
                              id++;
                          }


                         if(keywordsId.size()%10000==0)
                         {
                              bufferedWriter.append(sequence);
                              sequence="";

                               start=id;
                         }

                    }
                    String line = bufferedReader.readLine();
                }
        }

        if(start<id)
        {

              bufferedWriter.append(sequence);
        }

        bufferedReader.close();
        fileReader.close();

        bufferedWriter.close();
         filewriter.close();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }

}

该类的构造函数是:

public ConvertTextToKeywordIds(){
   path= new LocalPath();
   repository= new RepositorySQL();
   keywordsId= new HashMap<String, Integer>();
   id=1;
   start=1;}

2 个答案:

答案 0 :(得分:2)

我怀疑你的程序速度与哈希映射的重新划分有关,因为单词的数量在增长。随着哈希映射的大小增加,每次重新散列都会导致显着的时间损失。您可以尝试估计您期望的唯一单词的数量,并使用它来初始化哈希映射。

如@JB Nizet所述,您可能希望直接写入缓冲的编写器,而不是等待累积多个条目。由于缓冲写入器已经设置为仅在累积了足够的更改时才写入。

答案 1 :(得分:1)

您的StringBuilder可能会使用String代替sequence来提高效率。

每次超过一定长度时,我也会写{冲洗sequence,而不是每当你向地图添加10000字时。{/ p>

这张地图可能会变得非常庞大 - 你考虑过改进吗?如果您点击数百万条,您可以使用数据库获得更好的性能。