Как я могу создать и получить доступ к индексу, чтобы перейти в определенную позицию большого файла в 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.
Другие вопросы по тегам