如何使用AsynchronousFileChannel高效读取StringBuffer

时间:2015-10-18 12:47:12

标签: java nio utf

因此,您知道可以使用AsynchronousFileChannel将整个文件读取到String:

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

假设现在,我不想分配整个ByteBuffer,而是逐行阅读。我可以使用ByteBuffer固定宽度并多次调用read,总是复制并附加到StringBuffer,直到我没有换到新线...我唯一关心的是:因为我正在读取的文件的编码可能是每个字符多字节(UTF的东西),所以读取字节可能会以不完整的字符结束。如何确保将正确的字节转换为字符串而不是弄乱编码?

更新:回答位于所选答案的评论中,但它基本上指向CharsetDecoder

2 个答案:

答案 0 :(得分:1)

如果你的情况下有明确的ASCII分隔符(\ n),那么你不需要关心不完整的字符串,因为这个字符映射到单字节(反之亦然)。

所以只需搜索&#39; \ n&#39;输入中的字节,读取并转换为String之前的任何内容。循环直到找不到更多新行。然后压缩缓冲区并重复使用以进行下一次读取。如果你找不到新的行,你将不得不分配更大的缓冲区,复制旧的缓冲区的内容,然后再次调用读取。

编辑:正如评论中所提到的,您可以动态地将ByteBuffer传递给CharsetDecoder并将其转换为CharBuffer(然后附加到StringBuilder或任何优先解决方案)。

答案 1 :(得分:-1)

试试扫描仪:

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

FileChannel是InterruptibleChannel