Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit 0b0db80

Browse files
Larry-NYuri Nesterenko
authored andcommitted
8227080: (fs) Files.newInputStream(...).skip(n) is slow
Backport-of: c6c82dd
1 parent c87d399 commit 0b0db80

File tree

2 files changed

+61
-7
lines changed

2 files changed

+61
-7
lines changed

src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
2929
import java.nio.*;
3030
import java.nio.channels.*;
3131
import java.nio.channels.spi.*;
32-
32+
import java.util.Objects;
3333

3434
/**
3535
* This class is defined here rather than in java.nio.channels.Channels
@@ -87,10 +87,8 @@ public synchronized int read() throws IOException {
8787
public synchronized int read(byte[] bs, int off, int len)
8888
throws IOException
8989
{
90-
if ((off < 0) || (off > bs.length) || (len < 0) ||
91-
((off + len) > bs.length) || ((off + len) < 0)) {
92-
throw new IndexOutOfBoundsException();
93-
} else if (len == 0)
90+
Objects.checkFromIndexSize(off, len, bs.length);
91+
if (len == 0)
9492
return 0;
9593

9694
ByteBuffer bb = ((this.bs == bs)
@@ -119,6 +117,26 @@ public int available() throws IOException {
119117
return 0;
120118
}
121119

120+
public synchronized long skip(long n) throws IOException {
121+
// special case where the channel is to a file
122+
if (ch instanceof SeekableByteChannel && n > 0) {
123+
SeekableByteChannel sbc = (SeekableByteChannel)ch;
124+
try {
125+
long pos = sbc.position();
126+
long size = sbc.size();
127+
if (pos >= size) {
128+
return 0L;
129+
}
130+
n = Math.min(n, size - pos);
131+
sbc.position(pos + n);
132+
return sbc.position() - pos;
133+
} catch (ClosedChannelException cce) {
134+
throw new IOException(cce);
135+
}
136+
}
137+
return super.skip(n);
138+
}
139+
122140
public void close() throws IOException {
123141
ch.close();
124142
}

test/jdk/java/nio/file/Files/Misc.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222
*/
2323

2424
/* @test
25-
* @bug 4313887 6838333 8005566 8032220 8215467
25+
* @bug 4313887 6838333 8005566 8032220 8215467 8227080
2626
* @summary Unit test for miscellenous methods in java.nio.file.Files
2727
* @library ..
2828
*/
2929

30+
import java.io.InputStream;
31+
import java.io.OutputStream;
32+
import java.nio.channels.ClosedChannelException;
3033
import java.nio.file.*;
3134
import static java.nio.file.Files.*;
3235
import static java.nio.file.LinkOption.*;
@@ -44,6 +47,7 @@ public static void main(String[] args) throws IOException {
4447
testIsSameFile(dir);
4548
testFileTypeMethods(dir);
4649
testAccessMethods(dir);
50+
testSkip(dir);
4751
} finally {
4852
TestUtil.removeAll(dir);
4953
}
@@ -372,6 +376,38 @@ static void testAccessMethods(Path tmpdir) throws IOException {
372376
}
373377
}
374378

379+
/**
380+
* Tests Files.newInputStream(Path).skip().
381+
*/
382+
static void testSkip(Path tmpdir) throws IOException {
383+
Path file = createFile(tmpdir.resolve("foo"));
384+
try (OutputStream out = Files.newOutputStream(file)) {
385+
byte[] blah = new byte[8192];
386+
Arrays.fill(blah, (byte)42);
387+
out.write(blah);
388+
out.close();
389+
try (InputStream in = Files.newInputStream(file)) {
390+
assertTrue(in.skip(-1) == 0);
391+
assertTrue(in.skip(0) == 0);
392+
assertTrue(in.skip(blah.length/4) == blah.length/4);
393+
assertTrue(in.skip(blah.length/2) == blah.length/2);
394+
assertTrue(in.skip(Long.MAX_VALUE) == blah.length/4);
395+
in.close();
396+
try {
397+
long n = in.skip(1);
398+
throw new RuntimeException("skip() did not fail");
399+
} catch (IOException ioe) {
400+
if (!(ioe.getCause() instanceof ClosedChannelException)) {
401+
throw new RuntimeException
402+
("IOException not caused by ClosedChannelException");
403+
}
404+
}
405+
}
406+
} finally {
407+
delete(file);
408+
}
409+
}
410+
375411
static void assertTrue(boolean okay) {
376412
if (!okay)
377413
throw new RuntimeException("Assertion Failed");

0 commit comments

Comments
 (0)