Skip to content

Commit 1b236d8

Browse files
committed
Add from() constructor reading file with offset and length parameter
fixes #25
1 parent c3f7239 commit 1b236d8

File tree

4 files changed

+80
-4
lines changed

4 files changed

+80
-4
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* add constructor for `IntBuffer` and `CharBuffer`
88
* `parse()` methods now expect more flexible `CharSequence` instead of `String` #23
99
* `from()` constructor reading from `char[]` has new version that accepts offset and length #24
10+
* add `from()` constructor reading file with offset and length parameter #25
1011

1112
### Breaking
1213

src/main/java/at/favre/lib/bytes/Bytes.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,21 @@ public static Bytes from(File file) {
470470
return wrap(Util.readFromFile(file));
471471
}
472472

473+
/**
474+
* Reads given file and returns the byte content. Be aware that the whole defined file content will be loaded to
475+
* memory, so be careful what to read in. This uses {@link java.io.RandomAccessFile} under the hood.
476+
*
477+
* @param file to read from
478+
* @param offset byte offset from zero position of the file
479+
* @param length to read from offset
480+
* @return new instance
481+
* @throws IllegalArgumentException if file does not exist
482+
* @throws IllegalStateException if file could not be read
483+
*/
484+
public static Bytes from(File file, int offset, int length) {
485+
return wrap(Util.readFromFile(file, offset, length));
486+
}
487+
473488
/**
474489
* Creates a new instance from given utf-8 encoded string
475490
*

src/main/java/at/favre/lib/bytes/Util.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.io.File;
2727
import java.io.IOException;
2828
import java.io.InputStream;
29+
import java.io.RandomAccessFile;
2930
import java.nio.ByteBuffer;
3031
import java.nio.ByteOrder;
3132
import java.nio.CharBuffer;
@@ -378,9 +379,7 @@ static byte[] concatVararg(byte firstByte, byte[] moreBytes) {
378379
* @return byte content
379380
*/
380381
static byte[] readFromFile(File file) {
381-
if (file == null || !file.exists() || !file.isFile()) {
382-
throw new IllegalArgumentException("file must not be null, has to exist and must be a file (not a directory) " + file);
383-
}
382+
checkFile(file);
384383

385384
try {
386385
return Files.readAllBytes(file.toPath());
@@ -389,6 +388,30 @@ static byte[] readFromFile(File file) {
389388
}
390389
}
391390

391+
/**
392+
* Reads bytes from file with given offset and max length
393+
*
394+
* @param file to read bytes from
395+
* @param offset to read
396+
* @param length from offset
397+
* @return byte array with length length
398+
*/
399+
static byte[] readFromFile(File file, int offset, int length) {
400+
checkFile(file);
401+
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
402+
raf.seek(offset);
403+
return readFromDataInput(raf, length);
404+
} catch (Exception e) {
405+
throw new IllegalStateException("could not read from random access file", e);
406+
}
407+
}
408+
409+
private static void checkFile(File file) {
410+
if (file == null || !file.exists() || !file.isFile()) {
411+
throw new IllegalArgumentException("file must not be null, has to exist and must be a file (not a directory) " + file);
412+
}
413+
}
414+
392415
/**
393416
* Converts a char array to a byte array with given charset and range
394417
*

src/test/java/at/favre/lib/bytes/BytesConstructorTests.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,44 @@ public void fromFileCannotRead() throws Exception {
456456
try {
457457
Bytes.from(tempFile);
458458
fail();
459-
} catch (IllegalStateException e) {
459+
} catch (IllegalStateException ignored) {
460+
}
461+
}
462+
463+
@Test
464+
public void fromFileOffset() throws Exception {
465+
File tempFile = testFolder.newFile("out-test2.txt");
466+
Bytes bytes = Bytes.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18});
467+
try (FileOutputStream stream = new FileOutputStream(tempFile)) {
468+
stream.write(bytes.array());
469+
}
470+
471+
for (int lenI = 1; lenI < bytes.length() + 1; lenI++) {
472+
for (int offsetI = 0; offsetI < bytes.length(); offsetI++) {
473+
if (offsetI + lenI > bytes.length()) break;
474+
assertEquals(bytes.copy(offsetI, lenI), Bytes.from(tempFile, offsetI, lenI));
475+
}
476+
}
477+
assertEquals(Bytes.from(tempFile), Bytes.from(tempFile, 0, (int) tempFile.length()));
478+
}
479+
480+
@Test
481+
public void fromFileOffsetWithIllegalOffsetOrLength() throws Exception {
482+
File tempFile = testFolder.newFile("fromFileOffsetWithIllegalOffsetOrLength.txt");
483+
try (FileOutputStream stream = new FileOutputStream(tempFile)) {
484+
stream.write(new byte[]{0, 1, 2, 3});
485+
}
486+
487+
try {
488+
Bytes.from(tempFile, 0, 5);
489+
fail();
490+
} catch (IllegalStateException ignored) {
491+
}
492+
493+
try {
494+
Bytes.from(tempFile, 5, 1);
495+
fail();
496+
} catch (IllegalStateException ignored) {
460497
}
461498
}
462499

0 commit comments

Comments
 (0)