提交 200ad4d3 编写于 作者: D dxu

8011136: FileInputStream.available and skip inconsistencies

Summary: Correct the behavior of available() and update related java specs for available() and skip() in InputStream and FileInputStream classes.
Reviewed-by: alanb
上级 16e18e93
...@@ -240,13 +240,15 @@ class FileInputStream extends InputStream ...@@ -240,13 +240,15 @@ class FileInputStream extends InputStream
* *
* <p>The <code>skip</code> method may, for a variety of * <p>The <code>skip</code> method may, for a variety of
* reasons, end up skipping over some smaller number of bytes, * reasons, end up skipping over some smaller number of bytes,
* possibly <code>0</code>. If <code>n</code> is negative, an * possibly <code>0</code>. If <code>n</code> is negative, the method
* <code>IOException</code> is thrown, even though the <code>skip</code> * will try to skip backwards. In case the backing file does not support
* method of the {@link InputStream} superclass does nothing in this case. * backward skip at its current position, an <code>IOException</code> is
* The actual number of bytes skipped is returned. * thrown. The actual number of bytes skipped is returned. If it skips
* forwards, it returns a positive value. If it skips backwards, it
* returns a negative value.
* *
* <p>This method may skip more bytes than are remaining in the backing * <p>This method may skip more bytes than what are remaining in the
* file. This produces no exception and the number of bytes skipped * backing file. This produces no exception and the number of bytes skipped
* may include some number of bytes that were beyond the EOF of the * may include some number of bytes that were beyond the EOF of the
* backing file. Attempting to read from the stream after skipping past * backing file. Attempting to read from the stream after skipping past
* the end will result in -1 indicating the end of the file. * the end will result in -1 indicating the end of the file.
...@@ -261,9 +263,10 @@ class FileInputStream extends InputStream ...@@ -261,9 +263,10 @@ class FileInputStream extends InputStream
/** /**
* Returns an estimate of the number of remaining bytes that can be read (or * Returns an estimate of the number of remaining bytes that can be read (or
* skipped over) from this input stream without blocking by the next * skipped over) from this input stream without blocking by the next
* invocation of a method for this input stream. The next invocation might be * invocation of a method for this input stream. Returns 0 when the file
* the same thread or another thread. A single read or skip of this * position is beyond EOF. The next invocation might be the same thread
* many bytes will not block, but may read or skip fewer bytes. * or another thread. A single read or skip of this many bytes will not
* block, but may read or skip fewer bytes.
* *
* <p> In some cases, a non-blocking read (or skip) may appear to be * <p> In some cases, a non-blocking read (or skip) may appear to be
* blocked when it is merely slow, for example when reading large * blocked when it is merely slow, for example when reading large
......
/* /*
* Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -193,8 +193,10 @@ public abstract class InputStream implements Closeable { ...@@ -193,8 +193,10 @@ public abstract class InputStream implements Closeable {
* up skipping over some smaller number of bytes, possibly <code>0</code>. * up skipping over some smaller number of bytes, possibly <code>0</code>.
* This may result from any of a number of conditions; reaching end of file * This may result from any of a number of conditions; reaching end of file
* before <code>n</code> bytes have been skipped is only one possibility. * before <code>n</code> bytes have been skipped is only one possibility.
* The actual number of bytes skipped is returned. If <code>n</code> is * The actual number of bytes skipped is returned. If {@code n} is
* negative, no bytes are skipped. * negative, the {@code skip} method for class {@code InputStream} always
* returns 0, and no bytes are skipped. Subclasses may handle the negative
* value differently.
* *
* <p> The <code>skip</code> method of this class creates a * <p> The <code>skip</code> method of this class creates a
* byte array and then repeatedly reads into it until <code>n</code> bytes * byte array and then repeatedly reads into it until <code>n</code> bytes
......
/* /*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -100,6 +100,8 @@ Java_java_io_FileInputStream_available(JNIEnv *env, jobject this) { ...@@ -100,6 +100,8 @@ Java_java_io_FileInputStream_available(JNIEnv *env, jobject this) {
if (IO_Available(fd, &ret)) { if (IO_Available(fd, &ret)) {
if (ret > INT_MAX) { if (ret > INT_MAX) {
ret = (jlong) INT_MAX; ret = (jlong) INT_MAX;
} else if (ret < 0) {
ret = 0;
} }
return jlong_to_jint(ret); return jlong_to_jint(ret);
} }
......
/* /*
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 6402006 7030573 * @bug 6402006 7030573 8011136
* @summary Test if available returns correct value when reading * @summary Test if available returns correct value when reading
* a large file. * a large file.
*/ */
...@@ -61,9 +61,12 @@ public class LargeFileAvailable { ...@@ -61,9 +61,12 @@ public class LargeFileAvailable {
remaining -= skipBytes(fis, bigSkip, remaining); remaining -= skipBytes(fis, bigSkip, remaining);
remaining -= skipBytes(fis, 10L, remaining); remaining -= skipBytes(fis, 10L, remaining);
remaining -= skipBytes(fis, bigSkip, remaining); remaining -= skipBytes(fis, bigSkip, remaining);
if (fis.available() != (int) remaining) { int expected = (remaining >= Integer.MAX_VALUE)
throw new RuntimeException("available() returns " ? Integer.MAX_VALUE
+ fis.available() + " but expected " + remaining); : (remaining > 0 ? (int) remaining : 0);
if (fis.available() != expected) {
throw new RuntimeException("available() returns "
+ fis.available() + " but expected " + expected);
} }
} finally { } finally {
file.delete(); file.delete();
...@@ -77,19 +80,18 @@ public class LargeFileAvailable { ...@@ -77,19 +80,18 @@ public class LargeFileAvailable {
long skip = is.skip(toSkip); long skip = is.skip(toSkip);
if (skip != toSkip) { if (skip != toSkip) {
throw new RuntimeException("skip() returns " + skip throw new RuntimeException("skip() returns " + skip
+ " but expected " + toSkip); + " but expected " + toSkip);
} }
long remaining = avail - skip; long remaining = avail - skip;
int expected = remaining >= Integer.MAX_VALUE int expected = (remaining >= Integer.MAX_VALUE)
? Integer.MAX_VALUE ? Integer.MAX_VALUE
: (int) remaining; : (remaining > 0 ? (int) remaining : 0);
System.out.println("Skipped " + skip + " bytes " System.out.println("Skipped " + skip + " bytes, available() returns "
+ " available() returns " + expected + + expected + ", remaining " + remaining);
" remaining=" + remaining);
if (is.available() != expected) { if (is.available() != expected) {
throw new RuntimeException("available() returns " throw new RuntimeException("available() returns "
+ is.available() + " but expected " + expected); + is.available() + " but expected " + expected);
} }
return skip; return skip;
} }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 8010837 * @bug 8010837 8011136
* @summary Test if available returns correct value when skipping beyond * @summary Test if available returns correct value when skipping beyond
* the end of a file. * the end of a file.
* @author Dan Xu * @author Dan Xu
...@@ -42,6 +42,7 @@ public class NegativeAvailable { ...@@ -42,6 +42,7 @@ public class NegativeAvailable {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
final int SIZE = 10; final int SIZE = 10;
final int SKIP = 5; final int SKIP = 5;
final int NEGATIVE_SKIP = -5;
// Create a temporary file with size of 10 bytes. // Create a temporary file with size of 10 bytes.
Path tmp = Files.createTempFile(null, null); Path tmp = Files.createTempFile(null, null);
...@@ -56,12 +57,15 @@ public class NegativeAvailable { ...@@ -56,12 +57,15 @@ public class NegativeAvailable {
try (FileInputStream fis = new FileInputStream(tempFile)) { try (FileInputStream fis = new FileInputStream(tempFile)) {
if (tempFile.length() != SIZE) { if (tempFile.length() != SIZE) {
throw new RuntimeException("unexpected file size = " throw new RuntimeException("unexpected file size = "
+ tempFile.length()); + tempFile.length());
} }
long space = skipBytes(fis, SKIP, SIZE); long space = skipBytes(fis, SKIP, SIZE);
space = skipBytes(fis, NEGATIVE_SKIP, space);
space = skipBytes(fis, SKIP, space); space = skipBytes(fis, SKIP, space);
space = skipBytes(fis, SKIP, space); space = skipBytes(fis, SKIP, space);
space = skipBytes(fis, SKIP, space); space = skipBytes(fis, SKIP, space);
space = skipBytes(fis, NEGATIVE_SKIP, space);
space = skipBytes(fis, NEGATIVE_SKIP, space);
} }
Files.deleteIfExists(tmp); Files.deleteIfExists(tmp);
} }
...@@ -74,17 +78,18 @@ public class NegativeAvailable { ...@@ -74,17 +78,18 @@ public class NegativeAvailable {
long skip = fis.skip(toSkip); long skip = fis.skip(toSkip);
if (skip != toSkip) { if (skip != toSkip) {
throw new RuntimeException("skip() returns " + skip throw new RuntimeException("skip() returns " + skip
+ " but expected " + toSkip); + " but expected " + toSkip);
} }
long remaining = space - toSkip; long newSpace = space - toSkip;
long remaining = newSpace > 0 ? newSpace : 0;
int avail = fis.available(); int avail = fis.available();
if (avail != remaining) { if (avail != remaining) {
throw new RuntimeException("available() returns " + avail throw new RuntimeException("available() returns " + avail
+ " but expected " + remaining); + " but expected " + remaining);
} }
System.out.println("Skipped " + skip + " bytes " System.out.println("Skipped " + skip + " bytes "
+ " available() returns " + avail); + " available() returns " + avail);
return remaining; return newSpace;
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册