2015-11-04 12 views
5

4 Gigabyte RAM'li bir bilgisayar ve 10 Gigabyte bellek kullanımına sahip bir dosyam var. Şimdi dosyasındaki her satır yüzden yazdım Aşağıdaki kod benzersiz olup olmadığını kontrol etmek istiyorum:4 GB RAM ile 10 GB dosyada benzersiz satırlar nasıl oluşturulur

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileReader; 
import java.io.FileWriter; 
import java.io.IOException; 
import java.util.HashSet; 
import java.util.Set; 

public class Cleaner { 

    public static void main(String[] args) throws IOException { 
     if (args.length < 2) { 
      System.out.println("Too less parameters!"); 
      return; 
     } 

     File file = new File(args[0]); 
     BufferedReader buff = new BufferedReader(new FileReader(file)); 
     String line; 
     Set<String> set = new HashSet<String>(); 
     while ((line = buff.readLine()) != null) { 
      set.add(line); 
     } 
     FileWriter fw = new FileWriter(args[1]); 
     for (String s : set) { 
      fw.write(s + "\n"); 
      fw.flush(); 
     } 
     fw.close(); 
     buff.close(); 

    } 

} 

Ama benim sorum bu yüzden bir OutOfMemoryException olsun:
benim hemen benim kodunu değiştirmek gerekir nasıl her satırın benzersiz olduğu bir dosya mı?
Yardımlarınız için şimdiden teşekkür ederiz.

+0

Parçalara bölün ve iki kez karşılaştırın. Ya da her bir çizgiyi karıştır ve sadece hashı hatla birlikte sakla. – user

+0

Karma ile ilgili sorun, her satırın yalnızca bir karma olduğunu ve muhtemelen bazı yinelenen satırları kaçırmamı nasıl engelleyeceğidir. –

+0

RandomAccessFile'a bir bakın, RandomAccessFile 'a' satır 1'i okuyabilir ve RandomAccessFile 'b' nin diğer tüm satırlarıyla karşılaştırabilirsiniz. Bundan sonra satır 2 ve benzeri – user

cevap

0

potansiyel yinelenen satırları tanımlamak için ilk sağlamalarının yardımcı olur:

Map<Integer, Integer> hashes = new HashMap<>(); 
Map<Integer, Integer> dupes = new HashMap<>(); 
int i = 0; 
while ((line = buff.readLine()) != null) { 
    int hash = line.hashCode(); 
    Integer previous = hashes.get(hash); 
    if (previous != null) { //potential duplicate 
    dupes.put(i, previous); 
    } else { 
    hashes.put(hash, i); 
    } 
    ++i; 
} 

olası kopyaların bir listesi var sonunda. dupes boşsa, çoğaltma yapılmadı, eğer değilse, satırların gerçekten aynı olup olmadığını kontrol etmek için dosya üzerinde ikinci bir geçiş yapabilirsiniz. çalıştırmak için 1GB RAM hakkında daha fazla gerektirmemelidir

def hashes = [] 
def writer = new PrintWriter(new FileWriter("out.txt")) 
new File('test.txt').eachLine { line -> 
    def hashCode = DigestUtils.sha256Hex(line) //Commons digest library 
    if (!(hashCode in hashes)) { 
     hashes << hashCode 
     writer.println(line) 
    } 
} 
writer.close() 

(örnek Groovy olmakla eşdeğer Java çalışacak):

+1

Ayrıca Koloboke ['IntIntMap'] (http://openhft.github.io/Koloboke/api/0.6/java7/net/openhft/koloboke/collect/map/IntIntMap.html kullanmak için çok daha fazla bellek verimli olurdu) ya da haritayı temsil etmek için ['TIntIntHashMap'] (http://trove4j.sourceforge.net/javadocs/gnu/trove/map/hash/TIntIntHashMap.html). –

+0

Bu ikinci geçiş hakkında, rastgele erişime izin verilen dosyalara geçiş yaparsanız onu atlayabilirsiniz. Ardından, geriye doğru gidebilir ve olası her bir kopyadaki satırı kontrol edebilirsiniz. Aslında, ikinci geçiş, rasgele erişim olmadan zaten imkansız olurdu. – bezmax

+0

@bezmax Rasgele erişim xyz satırına gitmenize yardımcı olamaz - sadece bir kaç bayt atlayabilirsiniz - örneğimde, satır numarasının yerine bayt konumunu saklayabilirim. – assylias

0

Bu işlemi RAM belleğinizden dolayı yapamazsınız. Bunun yerine, dosyayı okuyabilir ve sabit boyutlu (f.e: 10.000 satırlık) n dosyaları üretebilir ve bir satırı okuyabilir ve gerçek dosyaya koyabilirsiniz. Dosya sınırına ulaştığınızda, yeni bir tane açın, bellek kaydetmek için tüm nesneleri serbest bırakın, sonra ikinci bir döngü yapın ve n oluşturulmuş dosyalar ile bir dize (satır için) kullanarak orijinal dosyanın her satırını karşılaştırın. Belki bu şekilde hafıza boşluğunu önleyebilirsiniz.

Biraz garip ve yavaş bir süreç olacak, ancak bu şekilde gereksinimlerinizi karşılayabileceğinizi düşünüyorum.

Kod gerekiyorsa, bana bildirin.

Umut yinelenen satır arayın deneyebilirsiniz

+0

Tüm dosyayı belleğe yüklemeniz gerekmediğini biliyorsunuz, öyle değil mi? – Marco

-1

Böyle bir şey ile hile. SHA256 hash'ları, standart hashCode yöntemine göre bir satırın benzersizliği konusunda muhtemelen daha kesin bir sonuç verecektir.

+1

Bu karma çarpışmalar nedeniyle işe yaramaz. – bezmax

+0

Karmaşıklıkların algılanması gerekiyor çünkü sadece kendine özgü çizgilere sahip bir dosya istiyordu. Dur tahmin edeyim, sen bunu reddeden adam değilsin ... –

İlgili konular