使用 Buffered 提高读写大文件的速度 Write/Reader
Improve the speed of reading and writing big files with Buffered Write/Reader
我想读取文本文件并将每个单词转换为数字。然后为每个文件在新文件中写入数字序列而不是单词。我使用 HashMap 为每个单词分配一个数字(标识符),例如,单词 apple 被分配给数字 10 所以无论何时,我在按顺序编写 10 的文本文件中看到 apple。我只需要一个 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();
}
}
class 的构造函数是:
public ConvertTextToKeywordIds(){
path= new LocalPath();
repository= new RepositorySQL();
keywordsId= new HashMap<String, Integer>();
id=1;
start=1;}
我怀疑随着字数的增加,您的程序速度与散列映射的重新散列有关。随着散列映射大小的增长,每次重新散列都会导致显着的时间损失。您可以尝试估计您期望的唯一单词的数量,并使用它来初始化哈希映射。
如@JB Nizet 所述,您可能希望直接写入缓冲写入器,而不是等待累积大量条目。由于缓冲写入器已经设置为仅在积累了足够的更改时才写入。
您最有效的性能提升可能是使用 StringBuilder
而不是 String
来实现您的 sequence
。
我也会在每次超过一定长度时写入并刷新 sequence
,而不是每当您向地图添加 10000
个单词时。
这张地图可能会变得很大 - 您是否考虑过改进它?如果您达到数百万个条目,您可能会使用数据库获得更好的性能。
我想读取文本文件并将每个单词转换为数字。然后为每个文件在新文件中写入数字序列而不是单词。我使用 HashMap 为每个单词分配一个数字(标识符),例如,单词 apple 被分配给数字 10 所以无论何时,我在按顺序编写 10 的文本文件中看到 apple。我只需要一个 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();
}
}
class 的构造函数是:
public ConvertTextToKeywordIds(){
path= new LocalPath();
repository= new RepositorySQL();
keywordsId= new HashMap<String, Integer>();
id=1;
start=1;}
我怀疑随着字数的增加,您的程序速度与散列映射的重新散列有关。随着散列映射大小的增长,每次重新散列都会导致显着的时间损失。您可以尝试估计您期望的唯一单词的数量,并使用它来初始化哈希映射。
如@JB Nizet 所述,您可能希望直接写入缓冲写入器,而不是等待累积大量条目。由于缓冲写入器已经设置为仅在积累了足够的更改时才写入。
您最有效的性能提升可能是使用 StringBuilder
而不是 String
来实现您的 sequence
。
我也会在每次超过一定长度时写入并刷新 sequence
,而不是每当您向地图添加 10000
个单词时。
这张地图可能会变得很大 - 您是否考虑过改进它?如果您达到数百万个条目,您可能会使用数据库获得更好的性能。