23
23
import java .io .InputStream ;
24
24
import java .io .OutputStream ;
25
25
import java .nio .ByteBuffer ;
26
- import java .nio .channels .FileChannel ;
27
26
import java .nio .file .Files ;
28
27
import java .nio .file .Path ;
29
28
import java .nio .file .StandardCopyOption ;
30
- import java .nio .file .StandardOpenOption ;
31
29
import java .util .concurrent .ThreadLocalRandom ;
32
30
import java .util .concurrent .atomic .AtomicBoolean ;
33
31
39
37
* @since 1.9.0
40
38
*/
41
39
public final class FileUtils {
42
- // Logic borrowed from Commons-Lang3: we really need only this, to decide do we fsync on directories or not
40
+ // Logic borrowed from Commons-Lang3: we really need only this, to decide do we "atomic move" or not
43
41
private static final boolean IS_WINDOWS =
44
42
System .getProperty ("os.name" , "unknown" ).startsWith ("Windows" );
45
43
@@ -66,6 +64,11 @@ public interface CollocatedTempFile extends TempFile {
66
64
* Invocation of this method merely signals that caller ultimately wants temp file to replace the target
67
65
* file, but when this method returns, the move operation did not yet happen, it will happen when this
68
66
* instance is closed.
67
+ * <p>
68
+ * Invoking this method <em>without writing to temp file</em> {@link #getPath()} (thus, not creating a temp
69
+ * file to be moved) is considered a bug, a mistake of the caller. Caller of this method should ensure
70
+ * that this method is invoked ONLY when the temp file is created and moving it to its final place is
71
+ * required.
69
72
*/
70
73
void move () throws IOException ;
71
74
}
@@ -125,13 +128,11 @@ public void move() {
125
128
126
129
@ Override
127
130
public void close () throws IOException {
128
- if (wantsMove .get () && Files . isReadable ( tempFile ) ) {
131
+ if (wantsMove .get ()) {
129
132
if (IS_WINDOWS ) {
130
133
copy (tempFile , file );
131
134
} else {
132
- fsyncFile (tempFile );
133
135
Files .move (tempFile , file , StandardCopyOption .ATOMIC_MOVE );
134
- fsyncParent (tempFile );
135
136
}
136
137
}
137
138
Files .deleteIfExists (tempFile );
@@ -157,33 +158,6 @@ private static void copy(Path source, Path target) throws IOException {
157
158
}
158
159
}
159
160
160
- /**
161
- * Performs fsync: makes sure no OS "dirty buffers" exist for given file.
162
- *
163
- * @param target Path that must not be {@code null}, must exist as plain file.
164
- */
165
- private static void fsyncFile (Path target ) throws IOException {
166
- try (FileChannel file = FileChannel .open (target , StandardOpenOption .WRITE )) {
167
- file .force (true );
168
- }
169
- }
170
-
171
- /**
172
- * Performs directory fsync: not usable on Windows, but some other OSes may also throw, hence thrown IO exception
173
- * is just ignored.
174
- *
175
- * @param target Path that must not be {@code null}, must exist as plain file, and must have parent.
176
- */
177
- private static void fsyncParent (Path target ) throws IOException {
178
- try (FileChannel parent = FileChannel .open (target .getParent (), StandardOpenOption .READ )) {
179
- try {
180
- parent .force (true );
181
- } catch (IOException e ) {
182
- // ignore
183
- }
184
- }
185
- }
186
-
187
161
/**
188
162
* A file writer, that accepts a {@link Path} to write some content to. Note: the file denoted by path may exist,
189
163
* hence implementation have to ensure it is able to achieve its goal ("replace existing" option or equivalent
0 commit comments