diff --git a/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java b/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java index 3b26f87cceb..e8e04f2f216 100644 --- a/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java +++ b/vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java @@ -11,6 +11,7 @@ package io.vertx.core.file.impl; +import io.netty.buffer.ByteBuf; import io.vertx.codegen.annotations.Nullable; import io.vertx.core.Future; import io.vertx.core.buffer.Buffer; @@ -23,6 +24,7 @@ import io.vertx.core.file.OpenOptions; import io.vertx.core.internal.ContextInternal; import io.vertx.core.internal.VertxInternal; +import io.vertx.core.internal.buffer.BufferInternal; import java.io.File; import java.io.FilenameFilter; @@ -37,8 +39,10 @@ import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.channels.FileChannel; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; +import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.GroupPrincipal; @@ -875,8 +879,41 @@ private BlockingAction readFileInternal(String path) { public Buffer perform() { try { Path target = resolveFile(path).toPath(); - byte[] bytes = Files.readAllBytes(target); - return Buffer.buffer(bytes); + try (FileChannel fc = FileChannel.open(target, StandardOpenOption.READ)) { + long initialSize = fc.size(); + final long MAX = (long) Integer.MAX_VALUE - 8; + if (initialSize > MAX) { + throw new OutOfMemoryError("Required array size too large"); + } + + BufferInternal res = BufferInternal.buffer(initialSize > 0 ? (int) initialSize : 0); + final ByteBuf bb = res.getByteBuf(); + if (initialSize > 0) { + bb.ensureWritable((int) initialSize); + } + + long position = 0L; + for (;;) { + int writable = bb.writableBytes(); + if (writable == 0) { + long soFar = bb.readableBytes(); + long remaining = MAX - soFar; + if (remaining <= 0) { + throw new OutOfMemoryError("Required array size too large"); + } + int ensure = (int) Math.min(remaining, 1 << 20); + bb.ensureWritable(ensure); + writable = bb.writableBytes(); + } + int read = bb.writeBytes(fc, position, writable); + if (read <= 0) { + break; + } + position += read; + } + + return res; + } } catch (IOException e) { throw new FileSystemException(getFileAccessErrorMessage("read", path), e); } @@ -884,6 +921,7 @@ public Buffer perform() { }; } + private BlockingAction writeFileInternal(String path, Buffer data) { Objects.requireNonNull(path); Objects.requireNonNull(data);