2010-09-29 10 views
7

Mam plik, który zawiera około 200 000 długich wartości, które chcę przeczytać tak szybko, jak to możliwe w długim []. Jest to aplikacja na Androida; wywołania funkcji są powolne (więc wszystko co wymaga długiego czytania za pomocą pętli "for" będzie bardzo powolne) i potrzebuję szybkiego załadowania. Co mogę użyć? Wszystko, na co patrzę, wydaje się szybko czytać tylko bajty.Najszybszy sposób odczytu długiego [] z pliku?

Użyłem wcześniej ByteBuffer i FileChannel z pakietu NIO i wydaje się to naprawdę szybki sposób na załadowanie tablic wartości z plików. Jednak nie mogę się dowiedzieć, jak użyć tego do odczytu danych na długi []. Próbowałem owijać długi [] jako LongBuffer, ale nie widzę sposobu, w jaki mogę przesłać dane z pliku do LongBuffer.

Edycja: Niezależnie od używanej przeze mnie metody, muszę mieć możliwość użycia Arrays.binarySearch w tablicy long[] na końcu.

+0

Nie jestem pewien, w jaki sposób te pomoc. Nie widzę, jak odpowiadają na moje pytanie. – memcom

Odpowiedz

3

Nie ma sposobu, aby obsadzić a byte[] w long[]. Można jednak spróbować użyć pliku FileChannel, aby odczytać zawartość do postaci ByteBuffer, a następnie uzyskać od do ByteBuffer.asLongBuffer, z której można uzyskać long[] do LongBuffer.array().

Możesz również wypróbować FileChannel.map, aby uzyskać MappedByteBuffer pliku. To może być szybsze niż przejście przez FileChannel.read.

Jeśli to nie zadziała możesz spróbować użyć FileChannel przeczytać zawartość w ByteBuffer a następnie przejść do long s wewnątrz niego, używając ByteBuffer.getLong(index).


Alternatywne rozwiązanie. (żadna metoda-rozmowy w pętli :-)

byte[] byteArray = new byte[longCount * 8]; 
FileInputStream fis = new FileInputStream("lotsoflongs"); 
fis.read(byteArray); 
fis.close(); 
for (int i = 0; i < longCount; i += 8) 
    longArray[i >> 3] = ((long) byteArray[0+i]  << 56) + 
         ((long)(byteArray[1+i] & 255) << 48) + 
         ((long)(byteArray[2+i] & 255) << 40) + 
         ((long)(byteArray[3+i] & 255) << 32) + 
         ((long)(byteArray[4+i] & 255) << 24) + 
           ((byteArray[5+i] & 255) << 16) + 
           ((byteArray[6+i] & 255) << 8) + 
           ((byteArray[7+i] & 255) << 0); 

Mam odwzorować kilka rozwiązań teraz, a ten wydaje się być najszybszy sposób to zrobić. Zwróć też uwagę, że rzeczywiste bajty odczytane w fis.read(byteArray) mogą być mniejsze niż rzeczywisty rozmiar obiektu byteArray. Tak więc, jeśli to powinno być zrobione poprawnie, musisz umieścić go w pętli, która będzie iterować aż do przeczytania wszystkich bajtów.

+0

Muszę być w stanie użyć długiego [] jak długiego [] po np. używanie go z Arrays.binarySearch – memcom

+0

Co powiesz na implementację 'List' of longs, wspieranej przez tablicę bajtów i użycie Collections.binarySearch? – aioobe

+0

Nie jestem pewien co masz na myśli? Jak utworzyć taki obiekt List? – memcom

1

Spróbuj użyć urządzenia DataInputStream. Ponieważ możesz łatwo sprawdzić długość pliku, wiesz również, ile zawiera on elementów (rozmiar pliku/8 bajtów).

DataInputStream dataStream = new DataInputStream(inputStream); 

long count = filesize/8; 
long[] longArray = new long[count]; 

for(int i=0;i<count;i++) 
    longArray[i] = dataStream.getLong(); 

Zgadnij, że powinno wystarczyć, aby dać ci pomysł.

+0

OP wykluczył czytanie po jednym długim naraz w pętli for. – aioobe

+0

@aioobe: Dlaczego po prostu nie zaimplementujesz własnej wersji binarySearch dla LongBuffer? Powinno być dość łatwe, a potem gotowe. :-) – mreichelt

Powiązane problemy