1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.archivers.zip;
18
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 import java.nio.channels.FileChannel;
22 import java.nio.file.OpenOption;
23 import java.nio.file.Path;
24 import java.nio.file.StandardOpenOption;
25 import java.util.Objects;
26
27
28
29
30
31 class FileRandomAccessOutputStream extends RandomAccessOutputStream {
32
33 private final FileChannel channel;
34
35 private long position;
36
37 FileRandomAccessOutputStream(final FileChannel channel) {
38 this.channel = Objects.requireNonNull(channel, "channel");
39 }
40
41 FileRandomAccessOutputStream(final Path file) throws IOException {
42 this(file, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
43 }
44
45 FileRandomAccessOutputStream(final Path file, final OpenOption... options) throws IOException {
46 this(FileChannel.open(file, options));
47 }
48
49 FileChannel channel() {
50 return channel;
51 }
52
53 @Override
54 public void close() throws IOException {
55 channel.close();
56 }
57
58 @Override
59 public synchronized long position() {
60 return position;
61 }
62
63 @Override
64 public synchronized void write(final byte[] b, final int off, final int len) throws IOException {
65 ZipIoUtil.writeFully(this.channel, ByteBuffer.wrap(b, off, len));
66 position += len;
67 }
68
69 @Override
70 public void writeFully(final byte[] b, final int off, final int len, final long atPosition) throws IOException {
71 final ByteBuffer buf = ByteBuffer.wrap(b, off, len);
72 for (long currentPos = atPosition; buf.hasRemaining();) {
73 final int written = this.channel.write(buf, currentPos);
74 if (written <= 0) {
75 throw new IOException("Failed to fully write to file: written=" + written);
76 }
77 currentPos += written;
78 }
79 }
80 }