2012-02-01 54 views
10

cách nhanh nhất có thể đọc các tệp tương đối lớn với các phương thức I/O của Java là gì? Giải pháp hiện tại của tôi sử dụng tiết kiệm BufferedInputStream cho một mảng byte với 1024 byte được phân bổ cho nó. Mỗi bộ đệm được lưu trong một ArrayList để sử dụng sau này. Toàn bộ quá trình được gọi qua một thread riêng biệt (giao diện có thể gọi).Cách nhanh nhất để đọc các tệp byte tương đối lớn trong Java

Mặc dù không phải rất nhanh.

ArrayList<byte[]> outputArr = new ArrayList<byte[]>();  
    try { 
     BufferedInputStream reader = new BufferedInputStream(new FileInputStream (dir+filename)); 

     byte[] buffer = new byte[LIMIT]; // == 1024 
      int i = 0; 
      while (reader.available() != 0) { 
       reader.read(buffer); 
       i++; 
       if (i <= LIMIT){ 
        outputArr.add(buffer); 
        i = 0; 
        buffer = null; 
        buffer = new byte[LIMIT]; 
       } 
       else continue;    
      } 

     System.out.println("FileReader-Elements: "+outputArr.size()+" w. "+buffer.length+" byte each."); 
+0

Hãy xem thư viện Apache Commons để có thêm tùy chọn. Và để xác định tốc độ, hãy xem cuốn sách Hiệu chỉnh Java của O'Reilly. – therobyouknow

+5

Hiện tại bạn đang bỏ qua giá trị được trả về bởi lệnh gọi 'read()' của bạn. * Đừng làm vậy. * –

Trả lời

25

Tôi sẽ sử dụng tệp ánh xạ bộ nhớ đủ nhanh để thực hiện trong cùng một chuỗi.

final FileChannel channel = new FileInputStream(fileName).getChannel(); 
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); 

// when finished 
channel.close(); 

Giả định tệp này nhỏ hơn 2 GB và sẽ mất 10 milli giây trở xuống.

+1

Đẫm máu! Tại sao cái quái vật đó lại cực kì nhanh vậy? Cảm ơn anyways, hoạt động hoàn hảo. (chỉnh sửa: nó lấy tập tin từ bộ nhớ, các tài liệu java chỉ nói với tôi. thông minh) –

+1

Nếu bạn cần truy cập hơn 2 GB, bạn cần sử dụng nhiều bản đồ. –

3

Không sử dụng available(): không đáng tin cậy. Và đừng bỏ qua kết quả của phương thức read(): nó cho bạn biết số byte thực sự đã đọc. Và nếu bạn muốn đọc tất cả mọi thứ trong bộ nhớ, sử dụng một ByteArrayOutputStream hơn là sử dụng một List<byte[]>:

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
int read; 
while ((read = reader.read(buffer)) >= 0) { 
    baos.write(buffer, 0, read); 
} 
byte[] everything = baos.toByteArray(); 

Tôi nghĩ rằng 1024 là một chút nhỏ như một kích thước bộ đệm. Tôi sẽ sử dụng bộ đệm lớn hơn (ví dụ 16 KB hoặc 32KB)

Lưu ý rằng Apache commons IO và Guava có các phương thức tiện ích thực hiện việc này cho bạn và đã được tối ưu hóa.

1

Hãy xem API Java NIO (Non-Blocking Input/Output) API. Ngoài ra, this question có thể chứng minh là hữu ích.

Tôi không có nhiều kinh nghiệm với IO, nhưng tôi đã nghe rằng NIO là cách hiệu quả hơn để xử lý nhiều bộ dữ liệu lớn.

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