Как я могу создать и получить доступ к индексу, чтобы перейти в определенную позицию большого файла в Java
У меня есть этот большой файл в следующем формате:
Уникальная Строка \t
Информация
В моей программе мне нужно прочитать этот файл, чтобы получить информацию через ключ уникальной строки. Поскольку производительность важна, я не могу читать каждую строку в поисках ключа каждый раз, кроме того, я не могу загрузить файл в память, потому что он слишком тяжелый. Затем я хотел бы прочитать файл только один раз, а затем создать индекс с ключом String и его позицией (в байтах) в файле. Этот индекс похож на HashMap, ключом которого является уникальная строка, а значением являются байты в файле, где появляется ключ.
Кажется, что RandomAccessFile мог бы сделать это, но я не знаю как.
Итак, как я могу построить этот индекс, а затем получить доступ к определенной строке по этому индексу?
2 ответа
Способ, который я собираюсь предложить, - это прочитать файл и следить за положением. Сохраняйте положение на карте, чтобы вы могли посмотреть позже.
Первый способ сделать это - использовать ваш файл как DataInput
и использовать RandomAccessFile#readline
RandomAccessFile raf = new RandomAccessFile("filename.txt", "r");
Map<String, Long> index = new HashMap<>();
Теперь, как хранятся ваши данные? Если он хранится построчно, а кодирование соответствует DataInput
стандарты, то вы можете использовать.
long start = raf.getFilePointer();
String line = raf.readLine();
String key = extractKeyFromLine(line);
index.put(key, start);
Теперь в любое время вам нужно вернуться и получить данные.
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();
}
}
junk.txt
содержит:
собака:1, 2, 3 кот:4, 5, 6 зебра: p, z, t
Наконец, вывод:
Ключ Зебра имеет позицию 24 зебра: p, z, t Ключевой кот имеет позицию 12 кот:4, 5, 6 ключевая собака имеет позицию 0 собака:1, 2, 3
Есть много предостережений к этому. Например, если вам нужна более надежная кодировка, то при первом ее прочтении вы захотите создать ридер, который сможет управлять кодировкой, и просто использовать RandomAccessFile
в качестве входного потока. readLine()
метод потерпит неудачу, если строки слишком велики. Тогда вам придется разработать свою собственную стратегию для извлечения пары ключ / данные.
Мне нужно прочитать этот файл, чтобы получить информацию через ключ уникальной строки.
Что касается вашего вышеупомянутого вопроса, вы должны прочитать файл построчно, разделить строку чтения, используя 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 + "'");
}
Теперь вы можете получить доступ к любому information
когда у тебя есть specificString
следующее,
map.get("specificString"); // will return corresponding information as int type.