2010-09-29 31 views
7

Tôi có một tệp có chứa khoảng 200.000 giá trị dài mà tôi muốn đọc nhanh nhất có thể thành một [] dài. Nó dành cho một ứng dụng Android; chức năng gọi chậm (vì vậy bất cứ điều gì liên quan đến việc đọc một thời gian dài với một vòng lặp "cho" sẽ được siêu chậm) và tôi cần tải để được nhanh chóng. Tôi có thể sử dụng cái gì? Tất cả mọi thứ tôi nhìn vào dường như chỉ đọc byte nhanh.Cách nhanh nhất để đọc dài [] từ tệp?

Tôi đã sử dụng ByteBufferFileChannel từ gói NIO trước đây và điều này có vẻ là một cách thực sự nhanh để tải mảng giá trị từ tệp. Tuy nhiên, tôi không thể tìm ra cách sử dụng để đọc dữ liệu thành một [] dài. Tôi đã cố gắng gói dài [] như một LongBuffer, nhưng tôi không thể nhìn thấy bất kỳ cách nào tôi có thể ăn dữ liệu từ một tập tin vào một LongBuffer.

Chỉnh sửa: Dù phương pháp nào tôi sử dụng, tôi cần có thể sử dụng Arrays.binarySearch trên mảng long[] ở cuối.

+0

Tôi không chắc chắn cách thức trợ giúp này. Tôi không thể thấy cách họ trả lời câu hỏi của tôi. – memcom

Trả lời

3

Không có cách nào để truyền a byte[] vào long[]. Tuy nhiên, bạn có thể thử sử dụng một số FileChannel để đọc nội dung vào một số ByteBuffer và sau đó giữ một số LongBuffer đến ByteBuffer.asLongBuffer mà từ đó bạn có thể nhận được long[] thông qua LongBuffer.array().

Bạn cũng có thể thử FileChannel.map để nhận được MappedByteBuffer của tệp. Điều này có thể nhanh hơn thông qua một FileChannel.read.

Nếu cách này không hiệu quả, bạn có thể thử sử dụng FileChannel để đọc nội dung vào ByteBuffer và sau đó truy cập long bên trong nó, sử dụng ByteBuffer.getLong(index).


Giải pháp thay thế. (Không có cuộc gọi phương thức nào trong vòng lặp :-)

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); 

Tôi đã đánh giá một vài giải pháp ngay bây giờ và cách này có vẻ là cách nhanh nhất để thực hiện. Ngoài ra, lưu ý rằng các byte thực được đọc trong fis.read(byteArray) có thể nhỏ hơn kích thước thực của byteArray. Vì vậy, nếu điều này nên được thực hiện đúng, bạn cần phải đặt nó trong một vòng lặp lặp cho đến khi tất cả các byte đã được đọc.

+0

Tôi cần có thể sử dụng [] lâu dài như một [] dài mặc dù ví dụ: sử dụng nó với Arrays.binarySearch – memcom

+0

Làm thế nào về việc triển khai thực hiện một 'Danh sách' dài, được hỗ trợ bởi một mảng byte và sử dụng Collections.binarySearch? – aioobe

+0

Tôi không chắc chắn ý của bạn là gì? Làm thế nào tôi sẽ tạo ra một đối tượng List? – memcom

1

Thử sử dụng DataInputStream. Vì bạn có thể dễ dàng tìm ra độ dài của tệp, bạn cũng biết có bao nhiêu phần tử chứa (tệp/8 byte).

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(); 

Đoán điều đó là đủ để cung cấp cho bạn ý tưởng.

+0

OP đã loại trừ việc đọc dài một lần tại một vòng lặp for. – aioobe

+0

@aioobe: Tại sao bạn không chỉ triển khai phiên bản binarySearch của riêng bạn cho LongBuffer? Nên khá dễ dàng, và sau đó bạn đã làm xong. :-) – mreichelt

Các vấn đề liên quan