2017-02-06 3 views
0

での大きなファイルの特定の位置に行くためのインデックスにアクセス私のプログラム情報からユニークな文字列キーを取得するには、このファイルを読む必要があります。パフォーマンスは重要なので、毎回キーを探している各行を読み取ることができず、ファイルが重すぎるためメモリにファイルをロードできません。次に、ファイルを一度しか読み込まずに、Stringキーとファイル内の位置(バイト単位)を持つインデックスを作成したいと思います。このインデックスは、HashMapのようなもので、キーは一意の文字列であり、値はキーが表示されるファイルのバイトです。は、私は、この大規模なフォロー形式のファイルを持っているJavaの

RandomAccessFileがこれを行うことができると思われますが、どうすればよいかわかりません。

このインデックスを作成し、このインデックスで特定の行にアクセスするにはどうすればよいですか。

+1

ヒント: 'HashMap'が便利です。 –

+0

@BackSlash索引を作成するためにファイルを読むのは一度だけですので、問題はありません。私が必要とするのは、特定のバイトにジャンプするためのインデックス(バイト単位)を構築することです。 あなたが言った質問は複製されていますが、このインデックスを作成する解決策はありません。 –

+0

@ジャッキー私はそうだと思いますが、特定のバイトにアクセスする方法がわかりません。 –

答えて

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は含まれています

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 

これには多くの注意点があります。たとえば、より堅牢なエンコーディングが必要な場合は、初めてエンコーディングを管理するリーダーを作成し、入力ストリームとしてRandomAccessFileを使用するだけです。線が大きすぎるとreadLine()メソッドが失敗します。次に、キー/データのペアを抽出する独自の戦略を考案する必要があります。

+0

これはまさに私が探していたものです! –

+0

マット私はあなたが言ったことをしましたが、私はこれを行うときに少し問題があります:long position = index.get(key); raf.seek(position); System.out.println(raf.readLine()); 結果は常に次の行です。そしてラインの長さは固定されていません –

+0

@MarceloMachado私はまったくフォローしていません、最良のケースscenerioは例を作ることです。例えば。あなたは何をしようとしていますか? – matt

1

このファイルを読んで、固有の 文字列キーを使用して情報を取得する必要があります。あなたの上記の質問に関しては

、あなたが行毎にファイルを読み込む必要が、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. 
+0

ファイルはメモリに入れるために重くなります。それに、私はすでにあまりにも多くのものを記憶に蓄積している。私のプログラムでは、特定の行しか必要とせず、各行を読むことができないので、Indexが必要です。 –

+0

ここでバイト計算を行い、マップを 'Map ' –

+0

として修正することができます。これは私が望むものだと思います。どうすればいいですか? –

関連する問題