2015-10-18 17 views
5

Vì vậy, bạn biết bạn có thể sử dụng AsynchronousFileChannel để đọc toàn bộ tập tin vào một String:Làm thế nào để sử dụng AsynchronousFileChannel để đọc cho một StringBuffer hiệu quả

AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(filePath, StandardOpenOption.READ); 
      long len = fileChannel.size(); 

      ReadAttachment readAttachment = new ReadAttachment(); 
      readAttachment.byteBuffer = ByteBuffer.allocate((int) len); 
      readAttachment.asynchronousChannel = fileChannel; 

      CompletionHandler<Integer, ReadAttachment> completionHandler = new CompletionHandler<Integer, ReadAttachment>() { 

       @Override 
       public void completed(Integer result, ReadAttachment attachment) { 

        String content = new String(attachment.byteBuffer.array()); 
        try { 
         attachment.asynchronousChannel.close(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
        completeCallback.accept(content); 
       } 

       @Override 
       public void failed(Throwable exc, ReadAttachment attachment) { 
        exc.printStackTrace(); 
        exceptionError(errorCallback, completeCallback, String.format("error while reading file [%s]: %s", path, exc.getMessage())); 
       } 
      }; 

      fileChannel.read(
        readAttachment.byteBuffer, 
        0, 
        readAttachment, 
        completionHandler); 

Giả sử bây giờ, tôi không muốn phân bổ toàn bộ một ByteBuffer , nhưng đọc từng dòng một. Tôi có thể sử dụng ByteBuffer chiều rộng cố định và giữ lại read nhiều lần, luôn sao chép và thêm vào StringBuffer cho đến khi tôi không nhận được dòng mới ... Mối quan tâm duy nhất của tôi là: vì mã hóa tệp mà tôi đang đọc có thể là đa byte cho mỗi ký tự (UTF cái gì đó), nó có thể xảy ra rằng byte đọc kết thúc với một ký tự chưa hoàn thành. Làm thế nào tôi có thể chắc chắn rằng tôi đang chuyển đổi các byte phải thành chuỗi và không rối tung lên các mã hóa?

CẬP NHẬT: câu trả lời nằm trong nhận xét của câu trả lời đã chọn, nhưng về cơ bản chỉ đến CharsetDecoder.

+3

Không sử dụng async I/O để đọc dòng. Nó chỉ là không phù hợp. Bạn có thể đọc hàng triệu dòng trên giây với 'BufferedReader.readLine(). ' – EJP

+0

Tôi cần hoạt động không chặn! – gotch4

+0

Vậy tại sao bạn sử dụng I/O không đồng bộ? Đó không phải là không chặn. Đây là một mô hình thứ ba, sau khi chặn và không chặn. Nhưng tại sao bạn nghĩ rằng bạn không thể sử dụng chặn I/O ở nơi đầu tiên? – EJP

Trả lời

1

Nếu bạn có dấu phân cách ASCII rõ ràng trong trường hợp của bạn (\ n), bạn sẽ không cần quan tâm đến chuỗi không đầy đủ vì ký tự này ánh xạ sang một byte đơn (và ngược lại).

Vì vậy, chỉ cần tìm kiếm '\ n' byte trong đầu vào của bạn và đọc và chuyển đổi mọi thứ trước thành Chuỗi. Lặp lại cho đến khi không tìm thấy thêm dòng mới nào. Sau đó, nhỏ gọn bộ đệm và tái sử dụng nó để đọc tiếp theo. Nếu bạn không tìm thấy dòng mới, bạn sẽ phải cấp phát bộ đệm lớn hơn, sao chép nội dung của bộ đệm cũ và chỉ sau đó gọi lại lần nữa.

EDIT: Như đã đề cập trong nhận xét, bạn có thể chuyển ByteBuffer sang CharsetDecoder khi đang di chuyển và dịch nó thành CharBuffer (sau đó nối thêm vào StringBuilder hoặc bất kỳ giải pháp nào được đặt trước).

+0

Bằng cách này, dù sao tôi đã lưu trữ toàn bộ một dòng như một bộ đệm byte ... Chúng ta hãy quên một chút rằng tôi đang xử lý các dòng ... Và bộ đệm của tôi bị giới hạn (các dòng có thể rất dài). Làm thế nào chúng ta sẽ làm gì? – gotch4

+1

Bạn có thể sử dụng http://docs.oracle.com/javase/7/docs/api/java/nio/charset/CharsetDecoder.html#decode(java.nio.ByteBuffer,%20java.nio.CharBuffer,%20boolean) để chuyển đổi đầu vào khi đang di chuyển. Bạn sẽ vẫn phải quản lý bộ đệm vì nó có thể chứa các ký tự còn lại giữa các lần đọc. –

+0

Hoàn hảo! Cảm ơn, hãy cân nhắc việc cập nhật câu trả lời – gotch4

0

Hãy thử Scanner:

Scanner sc = new Scanner(FileChannel.open(filePath, StandardOpenOption.READ)); 
    String line = sc.readLine(); 

FileChannel là InterruptibleChannel

+0

một lần nữa, tôi không cần gián đoạn, tôi cần bắt đầu đọc và gọi lại sau ... – gotch4

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