在行大小不固定的UTF-8编码文本文件上使用Java进行二进制搜索
我有一个选项卡分隔的UTF-8文件,其中记录按一个字段排序。但是,线的大小不是固定的,因此不能直接跳到特定的位置。我如何对此进行二进制搜索 例如: 第1行:阿尔弗雷德·布伦德尔/m/011hww/m/0crsgs6、/m/0crvt9h、/m/0cs5n_1、/m/0crtj4t、/m/0crwpnw、/m/0cr_n2s、/m/0crsgyh在行大小不固定的UTF-8编码文本文件上使用Java进行二进制搜索,java,file-io,binary-search,Java,File Io,Binary Search,我有一个选项卡分隔的UTF-8文件,其中记录按一个字段排序。但是,线的大小不是固定的,因此不能直接跳到特定的位置。我如何对此进行二进制搜索 例如: 第1行:阿尔弗雷德·布伦德尔/m/011hww/m/0crsgs6、/m/0crvt9h、/m/0cs5n_1、/m/0crtj4t、/m/0crwpnw、/m/0cr_n2s、/m/0crsgyh 第2行:Rupert Sheldrake/m/011ybj/m/0crtsz您知道孔文件包含的字节数。比如说n ->搜索间隔[l,r]与l=0,r=n
第2行:Rupert Sheldrake/m/011ybj/m/0crtsz您知道孔文件包含的字节数。比如说
n
->搜索间隔[l,r]
与l=0
,r=n
- 估计搜索间隔的中间值
。在此位置向左移动尽可能多的字节(也可以向右移动),直到找到制表符(字节==9(9是制表符的ASCII和UTF8代码))[让我们命名此位置m=(r-l)/2
],并解码该制表符开头的一行mReal
- 确定在下一个搜索步骤中,您是否必须使用前半部分(=>新搜索间隔为
)或后半部分(=>新搜索间隔为[l,mReal]
)[mReal,r]
然而,当你甚至猜不到行的长度时,我认为最好从生成随机数中进行选择。你可以跳到字节的中间。从那里你可以找到那一行的结尾,你可以从那一点读下一行。如果你需要向后搜索,每次取四分之一点或四分之三点,然后找到那条线。最终你会把它缩小到一行。你说的行大小不固定是什么意思?你能展示一个测试用例吗?简言之,他的意思是每一行的长度不是均匀的。(为了向其他读者澄清)你能详细说明一下吗?对不起,我没有得到你的解决方案。请你详细说明一下好吗?@BlackPlanet:至少在我的计算机上\t==9[在ASCII和UTF8中]我的评论并不是想暗示你在ASCII代码上是错误的,只是不清楚你所说的byte==9是什么意思。@BlackPlanet:对不起,我误解了你的评论[有时在你不是母语人士时发生]即使对以英语为母语的人来说,这个词的意思也是模棱两可的。不用担心。你能详细说明一下如何在文件的二进制搜索中使用它吗?这将为你提供所有由EPF_EOL字符串分隔的令牌。因此,您可以轻松接收所有字段
public class YourTokenizer {
public static final String EPF_EOL = "\t";
public static final int READ_SIZE = 4 * 1024 ;
/** The EPF stream buffer. */
private StringBuilder buffer = new StringBuilder();
/** The EPF stream. */
private InputStream stream = null;
public YourTokenizer(final InputStream stream) {
this.stream = stream;
}
private String getNextLine() throws IOException {
int pos = buffer.indexOf(EPF_EOL);
if (pos == -1) {
// eof-of-line sequence isn't available yet, read more of the file
final byte[] bytes = new byte[READ_SIZE];
final int readSize = stream.read(bytes, 0, READ_SIZE);
buffer.append(new String(bytes));
pos = buffer.indexOf(EPF_EOL);
if (pos == -1) {
if (readSize < READ_SIZE) {
// we have reached the end of the stream and what we're looking for still can't be found
throw new IOException("Premature end of stream");
}
return getNextLine();
}
}
final String data = buffer.substring(0, pos);
pos += EPF_EOL.length();
buffer = buffer.delete(0, pos);
return data;
}
}
final InputStream stream = new FileInputStream(file);
final YourTokenizer tokenizer = new YourTokenizer(stream);
String line = tokenizer.getNextLine();
while(line != line) {
//do something
line = tokenizer.getNextLine();
}