我正在寻找一种方法来解析大文件(约5-10Go)并搜索一些经常性字符串的位置(字节),尽可能最快。
我试图通过做类似下面的事情来使用RandomAccessFile阅读器:
RandomAccessFile lecteurFichier = new RandomAccessFile(<MyFile>, "r");
while (currentPointeurPosition < lecteurFichier.length()) {
char currentFileChar = (char) lecteurFichier.readByte();
// Test each char for matching my string (by appending chars until I found my string)
// and keep a trace of all found string's position
}
问题是这段代码太慢了(也许是因为我逐字节读取?)。
我也尝试了下面的解决方案,这在速度方面是完美的,但我不能得到我的弦乐器位置。
FileInputStream is = new FileInputStream(fichier.getFile());
FileChannel f = is.getChannel();
ByteBuffer buf = ByteBuffer.allocateDirect(64 * 1024);
Charset charset = Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
long len = 0;
while ((len = f.read(buf)) != -1) {
buf.flip();
String data = "";
try {
int old_position = buf.position();
data = decoder.decode(buf).toString();
// reset buffer's position to its original so it is not altered:
buf.position(old_position);
}
catch (Exception e) {
e.printStackTrace();
}
buf.clear();
}
f.close();
有人有更好的解决方案吗?
提前谢谢(对不起我的拼写,我是法国人)
答案 0 :(得分:1)
由于您的输入数据是以8位编码 * 编码的,因此您可以通过编码搜索字符串而不是解码文件来加快搜索速度:
byte[] encoded = searchString.getBytes("ISO-8859-1");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
int b;
long pos = -1;
while ((b = bis.read()) != -1) {
pos++;
if (encoded[0] == b) {
// see if rest of string matches
}
}
BufferedInputStream
应该非常快。使用ByteBuffer可能会更快,但这会使搜索逻辑变得更复杂,因为字符串匹配的可能性超过了缓冲区边界。
然后有各种聪明的方法来优化字符串搜索,可以适应这种情况......在那里你搜索一个字节/字符流而不是一个字节/字符数组。 String Searching上的维基百科页面是一个很好的起点。
请注意,由于我们以字节方式读取和匹配,因此位置只是读取(或跳过)的字节数,因此无需使用随机访问文件。
*实际上这个技巧也适用于许多多字节编码。
答案 1 :(得分:0)
在'haystack'中搜索'needle'是一个经过充分研究的问题 - 这是StackOverflow本身的一个相关link。我确信所讨论的算法的java实现也应该可用。为什么不尝试其中一些,看看它们是否适合这份工作?