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 if (channel.isOpen()) {
56 channel.close();
57 }
58 }
59
60 @Override
61 public synchronized long position() {
62 return position;
63 }
64
65 @Override
66 public synchronized void write(final byte[] b, final int off, final int len) throws IOException {
67 ZipIoUtil.writeFully(this.channel, ByteBuffer.wrap(b, off, len));
68 position += len;
69 }
70
71 @Override
72 public void writeFully(final byte[] b, final int off, final int len, final long atPosition) throws IOException {
73 final ByteBuffer buf = ByteBuffer.wrap(b, off, len);
74 for (long currentPos = atPosition; buf.hasRemaining();) {
75 final int written = this.channel.write(buf, currentPos);
76 if (written <= 0) {
77 throw new IOException("Failed to fully write to file: written=" + written);
78 }
79 currentPos += written;
80 }
81 }
82 }