在Java中,如何创建和访问索引,使其位于大文件的特定位置
我有一个大文件,格式如下: 唯一字符串在Java中,如何创建和访问索引,使其位于大文件的特定位置,java,indexing,Java,Indexing,我有一个大文件,格式如下: 唯一字符串\t信息 在我的程序中,我需要读取此文件,通过唯一字符串键获取信息。因为性能很重要,我不能每次都读每一行来寻找密钥,而且我不能在内存中加载文件,因为它太重了。然后我只想读取文件一次,然后用字符串键和该文件的位置(以字节为单位)构建一个索引。这个索引类似于HashMap,其中键是唯一的字符串,值是显示键的文件中的字节 似乎RandomAccessFile可以做到这一点,但我不知道如何做到 那么,我如何构建这个索引,然后通过这个索引访问特定的行呢 我需要阅读此文
\t
信息
在我的程序中,我需要读取此文件,通过唯一字符串键获取信息。因为性能很重要,我不能每次都读每一行来寻找密钥,而且我不能在内存中加载文件,因为它太重了。然后我只想读取文件一次,然后用字符串键和该文件的位置(以字节为单位)构建一个索引。这个索引类似于HashMap,其中键是唯一的字符串,值是显示键的文件中的字节
似乎RandomAccessFile可以做到这一点,但我不知道如何做到
那么,我如何构建这个索引,然后通过这个索引访问特定的行呢
我需要阅读此文件以通过唯一的
字符串键
关于您的上述问题,您必须逐行读取文件,使用split()
拆分读取的字符串,并将值放入Map
中,如下所示:
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
Map<String, int> map = new HashMap<String, int>();
int byte = 0;
while((line = bufferedReader.readLine()) != null) {
String arr[] = line.split("\t"); //make sure your file conatins data as you specified.
map.put(arr[0], byte);
byte += line.length() + 1;
}
bufferedReader.close();
}
catch(Exception ex) {
System.out.println("unable to open file '" + fileName + "'");
}
我建议的方法是阅读文件,并跟踪位置。将沿途的位置存储在地图中,以便以后查找 第一种方法是将文件用作
数据输入
,并使用随机访问文件#readline
RandomAccessFile raf = new RandomAccessFile("filename.txt", "r");
Map<String, Long> index = new HashMap<>();
现在,只要你需要回去获取数据
long position = index.get(key);
raf.seek(position);
String line = raf.readLine();
下面是一个完整的示例:
package helloworld;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;
/**
* Created by matt on 07/02/2017.
*/
public class IndexedFileAccess {
static String getKey(String line){
return line.split(":")[0];
}
public static void main(String[] args) throws IOException {
Map<String, Long> index = new HashMap<>();
RandomAccessFile file = new RandomAccessFile("junk.txt", "r");
//populate index and read file.
String s;
do{
long start = file.getFilePointer();
s = file.readLine();
if(s!=null){
String key = getKey(s);
index.put(key, start);
}
}while(s!=null);
for(String key: index.keySet()){
System.out.printf("key %s has a pos of %s\n", key, index.get(key));
file.seek(index.get(key));
System.out.println(file.readLine());
}
file.close();
}
}
最后,输出为:
key zebra has a pos of 24
zebra: p, z, t
key cat has a pos of 12
cat:4, 5, 6
key dog has a pos of 0
dog:1, 2, 3
钥匙斑马的位置是24
斑马:p,z,t
cat钥匙的位置为12
猫:4,5,6
钥匙狗的位置为0
狗:1,2,3
对此有很多警告。例如,如果您需要更健壮的编码,那么在第一次阅读时,您将希望创建一个能够管理编码的读取器,并将您的
RandomAccessFile
用作输入流。如果行太大,readLine()
方法将失败。然后,您必须设计自己的策略来提取密钥/数据对。提示:HashMap
将非常有用。@反斜杠读取文件以构建索引没有问题,因为它只执行一次。我需要的是构建索引(以字节为单位)以跳转到特定的字节。你说的问题是重复的,没有办法建立这个索引。@jackjay我想是的,但我不知道如何访问特定的索引byte@MarceloMachado“构建索引以访问特定字节”是什么意思?它是特定键的特定字节吗?为什么可以使用HashMap,其中键是唯一的字符串,值是字节数组?@MarceloMachado我需要阅读此文件,通过唯一的字符串键获取信息对于解决方案来说比建立索引重要得多。一旦你做了映射,你就不需要从文件中读取特定的字节。这个文件太重了,无法放入内存。此外,我已经有太多的东西存储在内存中。在我的程序中,我只需要特定的行,而要找到它们,我无法读取每一行,这就是我需要索引的原因。你可以在这里进行字节计算,并将映射修改为map
我想这就是我想要的,那么我该怎么做呢?@MarceloMachado现在你可以检查答案了。这正是我想要的!马特:我照你说的做了,但我有一个小问题,当我这么做的时候:多头仓位=索引。获取(键);寻找(位置);System.out.println(raf.readLine());结果总是下一行。而这条线的长度不是fixed@MarceloMachado我不太明白,最好的情况是举个例子。你在尝试什么?你得到了什么。
package helloworld;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;
/**
* Created by matt on 07/02/2017.
*/
public class IndexedFileAccess {
static String getKey(String line){
return line.split(":")[0];
}
public static void main(String[] args) throws IOException {
Map<String, Long> index = new HashMap<>();
RandomAccessFile file = new RandomAccessFile("junk.txt", "r");
//populate index and read file.
String s;
do{
long start = file.getFilePointer();
s = file.readLine();
if(s!=null){
String key = getKey(s);
index.put(key, start);
}
}while(s!=null);
for(String key: index.keySet()){
System.out.printf("key %s has a pos of %s\n", key, index.get(key));
file.seek(index.get(key));
System.out.println(file.readLine());
}
file.close();
}
}
dog:1, 2, 3
cat:4, 5, 6
zebra: p, z, t
key zebra has a pos of 24
zebra: p, z, t
key cat has a pos of 12
cat:4, 5, 6
key dog has a pos of 0
dog:1, 2, 3