我正在尝试创建一个小应用程序,它可以在文本文件中进行搜索并识别其中使用的语言(首先是英语和土耳其语之间)。为此我正在搜索字母" k"的字节外观。根据一些研究,这封信广泛用于土耳其语,在英语中使用较少,字节数相同。然而问题是用我的代码在110k字母的文本中找到字母k的外观需要大约20秒(或者可能多一点i7 7700hq comp),所以这对我来说是个大问题,因为我打算在1k文本文件上运行此代码。我应该使用另一种java方法进行搜索,还是以最快的方式进行搜索?
提前致谢
我的代码是:
package deneme;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.stream.IntStream;
public class deneme {
public static int howmany =0;
public static double ratio;
public static void main(String args[]) throws IOException{
File file = new File("c:\\tr1.srt");
byte[] bytesArray = new byte[(int) file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(bytesArray); //read file into bytes[]
fis.close();
byte searchVal = 107; // 'k' letter in byte code
for(byte textbytes:bytesArray){
Arrays.sort(bytesArray);
int retVal = Arrays.binarySearch(bytesArray,0,bytesArray.length,searchVal);
if(retVal >-1){
bytesArray[retVal]=0;
howmany++;
}
}
System.out.println("Character \"k\" appears " + howmany +" times in the text");
ratio = (double)howmany/(double)bytesArray.length;
System.out.println("How many: "+howmany);
System.out.println("Length: "+bytesArray.length);
System.out.println("Ratio: "+ratio);
if(ratio<0.01){
System.out.println("Text file is probably not turkish");
}else{
System.out.println("Text file is probably turkish");
}
}
}
答案 0 :(得分:2)
排序将访问每个字节,因此您不需要排序,只需访问每个字节一次。
如果你这样做,你实际上可以计算所有字节的频率:
int[] freqs = new int[256];
for(byte b: bytearray)
freqs[b&0x0ff]++;
然后只需查找你喜欢的字节,如freqs ['k'] + freqs ['K']。
另外,你可以在fileinputstream上打开一个bufferedinputstream,并避免使用巨大的byte [],只需迭代bufferedinputstream.read()(这是一个int 0..255)并在-1时停止。
答案 1 :(得分:1)
排序是一项代价高昂的操作。而且你正在为每个角色排序你的数组,这是低效的。相反,你可以按顺序遍历所有角色,如果那个特定角色是&#39; k&#39;,那么只需递增计数器。这是一个示例代码
for(byte textBytes: bytesArray) {
if(textBytes == searchVal) {
howmany++;
}
}
使用此循环代替您的循环。你应该更快地得到结果。
答案 2 :(得分:1)
首先,如果您使用字母,请使用Reader
,而不是InputStream
:
Reader reader = new BufferedReader(new FileReader(file));
接下来,您实施计数字母的方式&#39; k&#39;是......我应该怎么说......非常有创意。你二元搜索&#39; k&#39;只要找到它就会多次。虽然这有效,但它远非最佳。我认为它是O(n*log n)
,而O(n)
只需一次通过读取字符即可轻松解决。一些事情:
private static final char CHAR_k = 'k';
// ...
int count_k = 0;
int r;
while ((r = reader.read()) != -1) {
char ch = (char) r;
if (ch == CHAR_k) {
count_k++
}
}