Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.
Permalink
Browse files
8227080: (fs) Files.newInputStream(...).skip(n) is slow
Backport-of: c6c82dd
  • Loading branch information
Larry-N authored and Yuri Nesterenko committed May 14, 2021
1 parent c87d399 commit 0b0db80
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 7 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
import java.nio.*;
import java.nio.channels.*;
import java.nio.channels.spi.*;

import java.util.Objects;

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

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

public synchronized long skip(long n) throws IOException {
// special case where the channel is to a file
if (ch instanceof SeekableByteChannel && n > 0) {
SeekableByteChannel sbc = (SeekableByteChannel)ch;
try {
long pos = sbc.position();
long size = sbc.size();
if (pos >= size) {
return 0L;
}
n = Math.min(n, size - pos);
sbc.position(pos + n);
return sbc.position() - pos;
} catch (ClosedChannelException cce) {
throw new IOException(cce);
}
}
return super.skip(n);
}

public void close() throws IOException {
ch.close();
}
@@ -22,11 +22,14 @@
*/

/* @test
* @bug 4313887 6838333 8005566 8032220 8215467
* @bug 4313887 6838333 8005566 8032220 8215467 8227080
* @summary Unit test for miscellenous methods in java.nio.file.Files
* @library ..
*/

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.ClosedChannelException;
import java.nio.file.*;
import static java.nio.file.Files.*;
import static java.nio.file.LinkOption.*;
@@ -44,6 +47,7 @@ public static void main(String[] args) throws IOException {
testIsSameFile(dir);
testFileTypeMethods(dir);
testAccessMethods(dir);
testSkip(dir);
} finally {
TestUtil.removeAll(dir);
}
@@ -372,6 +376,38 @@ static void testAccessMethods(Path tmpdir) throws IOException {
}
}

/**
* Tests Files.newInputStream(Path).skip().
*/
static void testSkip(Path tmpdir) throws IOException {
Path file = createFile(tmpdir.resolve("foo"));
try (OutputStream out = Files.newOutputStream(file)) {
byte[] blah = new byte[8192];
Arrays.fill(blah, (byte)42);
out.write(blah);
out.close();
try (InputStream in = Files.newInputStream(file)) {
assertTrue(in.skip(-1) == 0);
assertTrue(in.skip(0) == 0);
assertTrue(in.skip(blah.length/4) == blah.length/4);
assertTrue(in.skip(blah.length/2) == blah.length/2);
assertTrue(in.skip(Long.MAX_VALUE) == blah.length/4);
in.close();
try {
long n = in.skip(1);
throw new RuntimeException("skip() did not fail");
} catch (IOException ioe) {
if (!(ioe.getCause() instanceof ClosedChannelException)) {
throw new RuntimeException
("IOException not caused by ClosedChannelException");
}
}
}
} finally {
delete(file);
}
}

static void assertTrue(boolean okay) {
if (!okay)
throw new RuntimeException("Assertion Failed");

1 comment on commit 0b0db80

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.