@@ -60,9 +60,12 @@ public class FileHandle extends AbstractDataHandle<FileLocation> {
60
60
61
61
// -- FileHandle methods --
62
62
63
- /** Gets the random access file object backing this FileHandle. */
63
+ /**
64
+ * Gets the random access file object backing this FileHandle. If the
65
+ * underlying file does not exist yet, it will be created.
66
+ */
64
67
public RandomAccessFile getRandomAccessFile () throws IOException {
65
- return raf ();
68
+ return writer ();
66
69
}
67
70
68
71
public String getMode () {
@@ -101,199 +104,199 @@ public Date lastModified() {
101
104
102
105
@ Override
103
106
public long offset () throws IOException {
104
- return raf () .getFilePointer ();
107
+ return exists () ? reader () .getFilePointer () : 0 ;
105
108
}
106
109
107
110
@ Override
108
111
public long length () throws IOException {
109
- return exists () ? raf ().length () : -1 ;
112
+ return exists () ? reader ().length () : -1 ;
110
113
}
111
114
112
115
@ Override
113
116
public void setLength (final long length ) throws IOException {
114
- raf ().setLength (length );
117
+ writer ().setLength (length );
115
118
}
116
119
117
120
@ Override
118
121
public int read () throws IOException {
119
- return raf ().read ();
122
+ return reader ().read ();
120
123
}
121
124
122
125
@ Override
123
126
public int read (final byte [] b ) throws IOException {
124
- return raf ().read (b );
127
+ return reader ().read (b );
125
128
}
126
129
127
130
@ Override
128
131
public int read (final byte [] b , final int off , final int len )
129
132
throws IOException
130
133
{
131
- return raf ().read (b , off , len );
134
+ return reader ().read (b , off , len );
132
135
}
133
136
134
137
@ Override
135
138
public void seek (final long pos ) throws IOException {
136
- raf ().seek (pos );
139
+ reader ().seek (pos );
137
140
}
138
141
139
142
// -- DataInput methods --
140
143
141
144
@ Override
142
145
public boolean readBoolean () throws IOException {
143
- return raf ().readBoolean ();
146
+ return reader ().readBoolean ();
144
147
}
145
148
146
149
@ Override
147
150
public byte readByte () throws IOException {
148
- return raf ().readByte ();
151
+ return reader ().readByte ();
149
152
}
150
153
151
154
@ Override
152
155
public char readChar () throws IOException {
153
- return raf ().readChar ();
156
+ return reader ().readChar ();
154
157
}
155
158
156
159
@ Override
157
160
public double readDouble () throws IOException {
158
- return raf ().readDouble ();
161
+ return reader ().readDouble ();
159
162
}
160
163
161
164
@ Override
162
165
public float readFloat () throws IOException {
163
- return raf ().readFloat ();
166
+ return reader ().readFloat ();
164
167
}
165
168
166
169
@ Override
167
170
public void readFully (final byte [] b ) throws IOException {
168
- raf ().readFully (b );
171
+ reader ().readFully (b );
169
172
}
170
173
171
174
@ Override
172
175
public void readFully (final byte [] b , final int off , final int len )
173
176
throws IOException
174
177
{
175
- raf ().readFully (b , off , len );
178
+ reader ().readFully (b , off , len );
176
179
}
177
180
178
181
@ Override
179
182
public int readInt () throws IOException {
180
- return raf ().readInt ();
183
+ return reader ().readInt ();
181
184
}
182
185
183
186
@ Override
184
187
public String readLine () throws IOException {
185
- return raf ().readLine ();
188
+ return reader ().readLine ();
186
189
}
187
190
188
191
@ Override
189
192
public long readLong () throws IOException {
190
- return raf ().readLong ();
193
+ return reader ().readLong ();
191
194
}
192
195
193
196
@ Override
194
197
public short readShort () throws IOException {
195
- return raf ().readShort ();
198
+ return reader ().readShort ();
196
199
}
197
200
198
201
@ Override
199
202
public int readUnsignedByte () throws IOException {
200
- return raf ().readUnsignedByte ();
203
+ return reader ().readUnsignedByte ();
201
204
}
202
205
203
206
@ Override
204
207
public int readUnsignedShort () throws IOException {
205
- return raf ().readUnsignedShort ();
208
+ return reader ().readUnsignedShort ();
206
209
}
207
210
208
211
@ Override
209
212
public String readUTF () throws IOException {
210
- return raf ().readUTF ();
213
+ return reader ().readUTF ();
211
214
}
212
215
213
216
@ Override
214
217
public int skipBytes (final int n ) throws IOException {
215
- return raf ().skipBytes (n );
218
+ return reader ().skipBytes (n );
216
219
}
217
220
218
221
// -- DataOutput methods --
219
222
220
223
@ Override
221
224
public void write (final byte [] b ) throws IOException {
222
- raf ().write (b );
225
+ writer ().write (b );
223
226
}
224
227
225
228
@ Override
226
229
public void write (final byte [] b , final int off , final int len )
227
230
throws IOException
228
231
{
229
- raf ().write (b , off , len );
232
+ writer ().write (b , off , len );
230
233
}
231
234
232
235
@ Override
233
236
public void write (final int b ) throws IOException {
234
- raf ().write (b );
237
+ writer ().write (b );
235
238
}
236
239
237
240
@ Override
238
241
public void writeBoolean (final boolean v ) throws IOException {
239
- raf ().writeBoolean (v );
242
+ writer ().writeBoolean (v );
240
243
}
241
244
242
245
@ Override
243
246
public void writeByte (final int v ) throws IOException {
244
- raf ().writeByte (v );
247
+ writer ().writeByte (v );
245
248
}
246
249
247
250
@ Override
248
251
public void writeBytes (final String s ) throws IOException {
249
- raf ().writeBytes (s );
252
+ writer ().writeBytes (s );
250
253
}
251
254
252
255
@ Override
253
256
public void writeChar (final int v ) throws IOException {
254
- raf ().writeChar (v );
257
+ writer ().writeChar (v );
255
258
}
256
259
257
260
@ Override
258
261
public void writeChars (final String s ) throws IOException {
259
- raf ().writeChars (s );
262
+ writer ().writeChars (s );
260
263
}
261
264
262
265
@ Override
263
266
public void writeDouble (final double v ) throws IOException {
264
- raf ().writeDouble (v );
267
+ writer ().writeDouble (v );
265
268
}
266
269
267
270
@ Override
268
271
public void writeFloat (final float v ) throws IOException {
269
- raf ().writeFloat (v );
272
+ writer ().writeFloat (v );
270
273
}
271
274
272
275
@ Override
273
276
public void writeInt (final int v ) throws IOException {
274
- raf ().writeInt (v );
277
+ writer ().writeInt (v );
275
278
}
276
279
277
280
@ Override
278
281
public void writeLong (final long v ) throws IOException {
279
- raf ().writeLong (v );
282
+ writer ().writeLong (v );
280
283
}
281
284
282
285
@ Override
283
286
public void writeShort (final int v ) throws IOException {
284
- raf ().writeShort (v );
287
+ writer ().writeShort (v );
285
288
}
286
289
287
290
@ Override
288
291
public void writeUTF (final String str ) throws IOException {
289
- raf ().writeUTF (str );
292
+ writer ().writeUTF (str );
290
293
}
291
294
292
295
// -- Closeable methods --
293
296
294
297
@ Override
295
298
public synchronized void close () throws IOException {
296
- if (raf != null ) raf () .close ();
299
+ if (raf != null ) raf .close ();
297
300
closed = true ;
298
301
}
299
302
@@ -306,12 +309,47 @@ public Class<FileLocation> getType() {
306
309
307
310
// -- Helper methods --
308
311
309
- private RandomAccessFile raf () throws IOException {
310
- if (raf == null ) initRAF ();
312
+ /**
313
+ * Access method for the internal {@link RandomAccessFile}, that succeeds
314
+ * independently of the underlying file existing on disk. This allows us to
315
+ * create a new file for writing.
316
+ *
317
+ * @return the internal {@link RandomAccessFile} creating a new file on disk
318
+ * if needed.
319
+ * @throws IOException if the {@link RandomAccessFile} could not be created.
320
+ */
321
+ private RandomAccessFile writer () throws IOException {
322
+ if (raf == null ) initRAF (true );
311
323
return raf ;
312
324
}
313
325
314
- private synchronized void initRAF () throws IOException {
326
+ /**
327
+ * Access method for the internal {@link RandomAccessFile}, that only succeeds
328
+ * if the underlying file exists on disk. This prevents accidental creation of
329
+ * an empty file when calling read operations on a non-existent file.
330
+ *
331
+ * @return the internal {@link RandomAccessFile}.
332
+ * @throws IOException if the {@link RandomAccessFile} could not be created,
333
+ * or the backing file does not exists.
334
+ */
335
+ private RandomAccessFile reader () throws IOException {
336
+ if (raf == null ) initRAF (false );
337
+ return raf ;
338
+ }
339
+
340
+ /**
341
+ * Initializes the {@link RandomAccessFile}.
342
+ *
343
+ * @param create whether to create the {@link RandomAccessFile} if the
344
+ * underlying file does not exist yet.
345
+ * @throws IOException if the {@link RandomAccessFile} could not be created,
346
+ * or the backing file does not exist and the {@code create}
347
+ * parameter was set to {@code false}.
348
+ */
349
+ private synchronized void initRAF (final boolean create ) throws IOException {
350
+ if (!create && !exists ()) {
351
+ throw new IOException ("Trying to read from non-existent file!" );
352
+ }
315
353
if (closed ) throw new IOException ("Handle already closed" );
316
354
if (raf != null ) return ;
317
355
raf = new RandomAccessFile (get ().getFile (), getMode ());
0 commit comments