8019526: (fs) Files.lines, etc without Charset parameter
authoralanb
Fri, 11 Oct 2013 20:47:15 +0100
changeset 20779 483371f41926
parent 20778 26af21e74a8d
child 20780 d4ead406572e
8019526: (fs) Files.lines, etc without Charset parameter Reviewed-by: psandoz, henryjen
jdk/src/share/classes/java/nio/file/Files.java
jdk/test/java/nio/file/Files/BytesAndLines.java
jdk/test/java/nio/file/Files/StreamTest.java
--- a/jdk/src/share/classes/java/nio/file/Files.java	Fri Oct 11 20:47:16 2013 +0100
+++ b/jdk/src/share/classes/java/nio/file/Files.java	Fri Oct 11 20:47:15 2013 +0100
@@ -43,9 +43,10 @@
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CharsetEncoder;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.attribute.BasicFileAttributeView;
 import java.nio.file.attribute.BasicFileAttributes;
-import java.nio.file.attribute.DosFileAttributes;
+import java.nio.file.attribute.DosFileAttributes;   // javadoc
 import java.nio.file.attribute.FileAttribute;
 import java.nio.file.attribute.FileAttributeView;
 import java.nio.file.attribute.FileOwnerAttributeView;
@@ -104,8 +105,7 @@
         return () -> {
             try {
                 c.close();
-            }
-            catch (IOException e) {
+            } catch (IOException e) {
                 throw new UncheckedIOException(e);
             }
         };
@@ -2550,7 +2550,7 @@
      *          checkExec} is invoked to check execute access to the file.
      */
     public static boolean isExecutable(Path path) {
-       return isAccessible(path, AccessMode.EXECUTE);
+        return isAccessible(path, AccessMode.EXECUTE);
     }
 
     // -- Recursive operations --
@@ -2783,6 +2783,37 @@
     }
 
     /**
+     * Opens a file for reading, returning a {@code BufferedReader} to read text
+     * from the file in an efficient manner. Bytes from the file are decoded into
+     * characters using the {@link StandardCharsets#UTF_8 UTF-8} {@link Charset
+     * charset}.
+     *
+     * <p> This method works as if invoking it were equivalent to evaluating the
+     * expression:
+     * <pre>{@code
+     * Files.newBufferedReader(path, StandardCharsets.UTF_8)
+     * }</pre>
+     *
+     * @param   path
+     *          the path to the file
+     *
+     * @return  a new buffered reader, with default buffer size, to read text
+     *          from the file
+     *
+     * @throws  IOException
+     *          if an I/O error occurs opening the file
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to the file.
+     *
+     * @since 1.8
+     */
+    public static BufferedReader newBufferedReader(Path path) throws IOException {
+        return newBufferedReader(path, StandardCharsets.UTF_8);
+    }
+
+    /**
      * Opens or creates a file for writing, returning a {@code BufferedWriter}
      * that may be used to write text to the file in an efficient manner.
      * The {@code options} parameter specifies how the the file is created or
@@ -2828,6 +2859,41 @@
     }
 
     /**
+     * Opens or creates a file for writing, returning a {@code BufferedWriter}
+     * to write text to the file in an efficient manner. The text is encoded
+     * into bytes for writing using the {@link StandardCharsets#UTF_8 UTF-8}
+     * {@link Charset charset}.
+     *
+     * <p> This method works as if invoking it were equivalent to evaluating the
+     * expression:
+     * <pre>{@code
+     * Files.newBufferedWriter(path, StandardCharsets.UTF_8, options)
+     * }</pre>
+     *
+     * @param   path
+     *          the path to the file
+     * @param   options
+     *          options specifying how the file is opened
+     *
+     * @return  a new buffered writer, with default buffer size, to write text
+     *          to the file
+     *
+     * @throws  IOException
+     *          if an I/O error occurs opening or creating the file
+     * @throws  UnsupportedOperationException
+     *          if an unsupported option is specified
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method is invoked to check write access to the file.
+     *
+     * @since 1.8
+     */
+    public static BufferedWriter newBufferedWriter(Path path, OpenOption... options) throws IOException {
+        return newBufferedWriter(path, StandardCharsets.UTF_8, options);
+    }
+
+    /**
      * Reads all bytes from an input stream and writes them to an output stream.
      */
     private static long copy(InputStream source, OutputStream sink)
@@ -3025,9 +3091,7 @@
      * @throws  OutOfMemoryError
      *          if an array of the required size cannot be allocated
      */
-    private static byte[] read(InputStream source, int initialSize)
-            throws IOException
-    {
+    private static byte[] read(InputStream source, int initialSize) throws IOException {
         int capacity = initialSize;
         byte[] buf = new byte[capacity];
         int nread = 0;
@@ -3131,9 +3195,7 @@
      *
      * @see #newBufferedReader
      */
-    public static List<String> readAllLines(Path path, Charset cs)
-        throws IOException
-    {
+    public static List<String> readAllLines(Path path, Charset cs) throws IOException {
         try (BufferedReader reader = newBufferedReader(path, cs)) {
             List<String> result = new ArrayList<>();
             for (;;) {
@@ -3147,6 +3209,37 @@
     }
 
     /**
+     * Read all lines from a file. Bytes from the file are decoded into characters
+     * using the {@link StandardCharsets#UTF_8 UTF-8} {@link Charset charset}.
+     *
+     * <p> This method works as if invoking it were equivalent to evaluating the
+     * expression:
+     * <pre>{@code
+     * Files.readAllLines(path, StandardCharsets.UTF_8)
+     * }</pre>
+     *
+     * @param   path
+     *          the path to the file
+     *
+     * @return  the lines from the file as a {@code List}; whether the {@code
+     *          List} is modifiable or not is implementation dependent and
+     *          therefore not specified
+     *
+     * @throws  IOException
+     *          if an I/O error occurs reading from the file or a malformed or
+     *          unmappable byte sequence is read
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to the file.
+     *
+     * @since 1.8
+     */
+    public static List<String> readAllLines(Path path) throws IOException {
+        return readAllLines(path, StandardCharsets.UTF_8);
+    }
+
+    /**
      * Writes bytes to a file. The {@code options} parameter specifies how the
      * the file is created or opened. If no options are present then this method
      * works as if the {@link StandardOpenOption#CREATE CREATE}, {@link
@@ -3262,6 +3355,45 @@
         return path;
     }
 
+    /**
+     * Write lines of text to a file. Characters are encoded into bytes using
+     * the {@link StandardCharsets#UTF_8 UTF-8} {@link Charset charset}.
+     *
+     * <p> This method works as if invoking it were equivalent to evaluating the
+     * expression:
+     * <pre>{@code
+     * Files.write(path, lines, StandardCharsets.UTF_8, options);
+     * }</pre>
+     *
+     * @param   path
+     *          the path to the file
+     * @param   lines
+     *          an object to iterate over the char sequences
+     * @param   options
+     *          options specifying how the file is opened
+     *
+     * @return  the path
+     *
+     * @throws  IOException
+     *          if an I/O error occurs writing to or creating the file, or the
+     *          text cannot be encoded as {@code UTF-8}
+     * @throws  UnsupportedOperationException
+     *          if an unsupported option is specified
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkWrite(String) checkWrite}
+     *          method is invoked to check write access to the file.
+     *
+     * @since 1.8
+     */
+    public static Path write(Path path,
+                             Iterable<? extends CharSequence> lines,
+                             OpenOption... options)
+        throws IOException
+    {
+        return write(path, lines, StandardCharsets.UTF_8, options);
+    }
+
     // -- Stream APIs --
 
     /**
@@ -3431,9 +3563,11 @@
      *          if an I/O error is thrown when accessing the starting file.
      * @since   1.8
      */
-    public static Stream<Path> walk(Path start, int maxDepth,
+    public static Stream<Path> walk(Path start,
+                                    int maxDepth,
                                     FileVisitOption... options)
-            throws IOException {
+        throws IOException
+    {
         FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
         try {
             return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
@@ -3484,9 +3618,7 @@
      * @see     #walk(Path, int, FileVisitOption...)
      * @since   1.8
      */
-    public static Stream<Path> walk(Path start,
-                                    FileVisitOption... options)
-            throws IOException {
+    public static Stream<Path> walk(Path start, FileVisitOption... options) throws IOException {
         return walk(start, Integer.MAX_VALUE, options);
     }
 
@@ -3547,7 +3679,8 @@
                                     int maxDepth,
                                     BiPredicate<Path, BasicFileAttributes> matcher,
                                     FileVisitOption... options)
-            throws IOException {
+        throws IOException
+    {
         FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
         try {
             return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
@@ -3561,7 +3694,7 @@
     }
 
     /**
-     * Read all lines from a file as a {@code Stream}.  Unlike {@link
+     * Read all lines from a file as a {@code Stream}. Unlike {@link
      * #readAllLines(Path, Charset) readAllLines}, this method does not read
      * all lines into a {@code List}, but instead populates lazily as the stream
      * is consumed.
@@ -3619,4 +3752,33 @@
             throw e;
         }
     }
+
+    /**
+     * Read all lines from a file as a {@code Stream}. Bytes from the file are
+     * decoded into characters using the {@link StandardCharsets#UTF_8 UTF-8}
+     * {@link Charset charset}.
+     *
+     * <p> This method works as if invoking it were equivalent to evaluating the
+     * expression:
+     * <pre>{@code
+     * Files.lines(path, StandardCharsets.UTF_8)
+     * }</pre>
+     *
+     * @param   path
+     *          the path to the file
+     *
+     * @return  the lines from the file as a {@code Stream}
+     *
+     * @throws  IOException
+     *          if an I/O error occurs opening the file
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to the file.
+     *
+     * @since 1.8
+     */
+    public static Stream<String> lines(Path path) throws IOException {
+        return lines(path, StandardCharsets.UTF_8);
+    }
 }
--- a/jdk/test/java/nio/file/Files/BytesAndLines.java	Fri Oct 11 20:47:16 2013 +0100
+++ b/jdk/test/java/nio/file/Files/BytesAndLines.java	Fri Oct 11 20:47:15 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, 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
@@ -22,262 +22,318 @@
  */
 
 /* @test
- * @bug 7006126 8020669 8024788
+ * @bug 7006126 8020669 8024788 8019526
  * @build BytesAndLines PassThroughFileSystem
- * @run main BytesAndLines
+ * @run testng BytesAndLines
  * @summary Unit test for methods for Files readAllBytes, readAllLines and
  *     and write methods.
  */
 
-import java.nio.file.*;
-import static java.nio.file.Files.*;
-import java.io.*;
-import java.util.*;
-import java.nio.charset.*;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.OpenOption;
+import static java.nio.file.StandardOpenOption.*;
+import java.nio.charset.Charset;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+import static java.nio.charset.StandardCharsets.*;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.Callable;
+import java.io.IOException;
 
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test(groups = "unit")
 public class BytesAndLines {
-    static final Random rand = new Random();
+
+    // data for text files
+    private static final String EN_STRING = "The quick brown fox jumps over the lazy dog";
+    private static final String JA_STRING = "\u65e5\u672c\u8a9e\u6587\u5b57\u5217";
 
-    static final Charset US_ASCII = Charset.forName("US-ASCII");
+    // used for random byte content
+    private static Random RAND = new Random();
+
+    // file used by most tests
+    private Path tmpfile;
 
-    public static void main(String[] args) throws IOException {
-        testReadAndWriteBytes();
-        testReadLines();
-        testWriteLines();
+    @BeforeClass
+    void setup() throws IOException {
+        tmpfile = Files.createTempFile("blah", null);
+    }
+
+    @AfterClass
+    void cleanup() throws IOException {
+        Files.deleteIfExists(tmpfile);
+    }
+
+    /**
+     * Returns a byte[] of the given size with random content
+     */
+    private byte[] genBytes(int size) {
+        byte[] arr = new byte[size];
+        RAND.nextBytes(arr);
+        return arr;
     }
 
     /**
-     * Test readAllBytes(Path) and write(Path, byte[], OpenOption...)
+     * Exercise NullPointerException
      */
-    static void testReadAndWriteBytes() throws IOException {
-        // exercise methods with various sizes
-        testReadAndWriteBytes(0);
-        for (int i=0; i<100; i++) {
-            testReadAndWriteBytes(rand.nextInt(32000));
-        }
-
-        // NullPointerException
+    public void testNulls() {
         Path file = Paths.get("foo");
+        byte[] bytes = new byte[100];
         List<String> lines = Collections.emptyList();
-        try {
-            readAllBytes(null);
-            throw new RuntimeException("NullPointerException expected");
-        } catch (NullPointerException ignore) { }
-        try {
-            write(null, lines, Charset.defaultCharset());
-            throw new RuntimeException("NullPointerException expected");
-        } catch (NullPointerException ignore) { }
-        try {
-            write(file, null, Charset.defaultCharset());
-            throw new RuntimeException("NullPointerException expected");
-        } catch (NullPointerException ignore) { }
+
+        checkNullPointerException(() -> Files.readAllBytes(null));
+
+        checkNullPointerException(() -> Files.write(null, bytes));
+        checkNullPointerException(() -> Files.write(file, (byte[])null));
+        checkNullPointerException(() -> Files.write(file, bytes, (OpenOption[])null));
+        checkNullPointerException(() -> Files.write(file, bytes, new OpenOption[] { null } ));
+
+        checkNullPointerException(() -> Files.readAllLines(null));
+        checkNullPointerException(() -> Files.readAllLines(file, (Charset)null));
+        checkNullPointerException(() -> Files.readAllLines(null, Charset.defaultCharset()));
+
+        checkNullPointerException(() -> Files.write(null, lines));
+        checkNullPointerException(() -> Files.write(file, (List<String>)null));
+        checkNullPointerException(() -> Files.write(file, lines, (OpenOption[])null));
+        checkNullPointerException(() -> Files.write(file, lines, new OpenOption[] { null } ));
+        checkNullPointerException(() -> Files.write(null, lines, Charset.defaultCharset()));
+        checkNullPointerException(() -> Files.write(file, null, Charset.defaultCharset()));
+        checkNullPointerException(() -> Files.write(file, lines, (Charset)null));
+        checkNullPointerException(() -> Files.write(file, lines, Charset.defaultCharset(), (OpenOption[])null));
+        checkNullPointerException(() -> Files.write(file, lines, Charset.defaultCharset(), new OpenOption[] { null } ));
+    }
+
+    private void checkNullPointerException(Callable<?> c) {
         try {
-            write(file, lines, null);
-            throw new RuntimeException("NullPointerException expected");
-        } catch (NullPointerException ignore) { }
-        try {
-            write(file, lines, Charset.defaultCharset(), (OpenOption[])null);
-            throw new RuntimeException("NullPointerException expected");
-        } catch (NullPointerException ignore) { }
-        try {
-            OpenOption[] opts = { null };
-            write(file, lines, Charset.defaultCharset(), opts);
-            throw new RuntimeException("NullPointerException expected");
-        } catch (NullPointerException ignore) { }
-
-        // read from procfs
-        if (System.getProperty("os.name").equals("Linux")) {
-            // Refer to the Linux proc(5) man page for details about /proc/self/stat file
-            // procfs reports it to be zero sized, even though data can be read from it
-            String statFile = "/proc/self/stat";
-            Path pathStat = Paths.get(statFile);
-            byte[] data = Files.readAllBytes(pathStat);
-            assertTrue(data.length > 0, "Files.readAllBytes('" + statFile + "') failed to read");
-        }
-
-        // test readAllBytes on custom file system
-        Path myfile = PassThroughFileSystem.create().getPath(file.toString());
-        for (int size=0; size<=1024; size+=512) {
-            byte[] b1 = new byte[size];
-            rand.nextBytes(b1);
-            Files.write(myfile, b1);
-            byte[] b2 = Files.readAllBytes(myfile);
-            assertTrue(Arrays.equals(b1, b2), "bytes not equal");
+            c.call();
+            fail("NullPointerException expected");
+        } catch (NullPointerException ignore) {
+        } catch (Exception e) {
+            fail(e + " not expected");
         }
     }
 
-
-    static void testReadAndWriteBytes(int size) throws IOException {
-        Path path = createTempFile("blah", null);
-        try {
-            boolean append = rand.nextBoolean();
-
-            byte[] b1 = new byte[size];
-            rand.nextBytes(b1);
+    /**
+     * Exercise Files.readAllBytes(Path) on varied file sizes
+     */
+    public void testReadAllBytes() throws IOException {
+        int size = 0;
+        while (size <= 16*1024) {
+            testReadAllBytes(size);
+            size += 512;
+        }
+    }
 
-            byte[] b2 = (append) ? new byte[size] : new byte[0];
-            rand.nextBytes(b2);
-
-            // write method should create file if it doesn't exist
-            if (rand.nextBoolean())
-                delete(path);
-
-            // write bytes to file
-            Path target = write(path, b1);
-            assertTrue(target==path, "Unexpected path");
-            assertTrue(size(path) == b1.length, "Unexpected file size");
+    private void testReadAllBytes(int size) throws IOException {
+        // write bytes to file (random content)
+        byte[] expected = genBytes(size);
+        Files.write(tmpfile, expected);
 
-            // append bytes to file (might be 0 bytes)
-            write(path, b2, StandardOpenOption.APPEND);
-            assertTrue(size(path) == b1.length + b2.length, "Unexpected file size");
-
-            // read entire file
-            byte[] read = readAllBytes(path);
+        // check expected bytes are read
+        byte[] read = Files.readAllBytes(tmpfile);
+        assertTrue(Arrays.equals(read, expected), "Bytes read not the same as written");
+    }
 
-            // check bytes are correct
-            byte[] expected;
-            if (append) {
-                expected = new byte[b1.length + b2.length];
-                System.arraycopy(b1, 0, expected, 0, b1.length);
-                System.arraycopy(b2, 0, expected, b1.length, b2.length);
-            } else {
-                expected = b1;
-            }
-            assertTrue(Arrays.equals(read, expected),
-                       "Bytes read not the same as bytes written");
-        } finally {
-            deleteIfExists(path);
+    /**
+     * Linux specific test to exercise Files.readAllBytes on /proc. This is
+     * special because file sizes are reported as 0 even though the file
+     * has content.
+     */
+    public void testReadAllBytesOnProcFS() throws IOException {
+        // read from procfs
+        if (System.getProperty("os.name").equals("Linux")) {
+            Path statFile = Paths.get("/proc/self/stat");
+            byte[] data = Files.readAllBytes(statFile);
+            assertTrue(data.length > 0, "Files.readAllBytes('" + statFile + "') failed to read");
         }
     }
 
     /**
-     * Test readAllLines(Path,Charset)
+     * Exercise Files.readAllBytes(Path) on custom file system. This is special
+     * because readAllBytes was originally implemented to use FileChannel
+     * and so may not be supported by custom file system providers.
      */
-    static void testReadLines() throws IOException {
-        Path tmpfile = createTempFile("blah", "txt");
+    public void testReadAllBytesOnCustomFS() throws IOException {
+        Path myfile = PassThroughFileSystem.create().getPath("myfile");
         try {
-            List<String> lines;
-
-            // zero lines
-            assertTrue(size(tmpfile) == 0, "File should be empty");
-            lines = readAllLines(tmpfile, US_ASCII);
-            assertTrue(lines.isEmpty(), "No line expected");
-
-            // one line
-            byte[] hi = { (byte)'h', (byte)'i' };
-            write(tmpfile, hi);
-            lines = readAllLines(tmpfile, US_ASCII);
-            assertTrue(lines.size() == 1, "One line expected");
-            assertTrue(lines.get(0).equals("hi"), "'Hi' expected");
-
-            // two lines using platform's line separator
-            List<String> expected = Arrays.asList("hi", "there");
-            write(tmpfile, expected, US_ASCII);
-            assertTrue(size(tmpfile) > 0, "File is empty");
-            lines = readAllLines(tmpfile, US_ASCII);
-            assertTrue(lines.equals(expected), "Unexpected lines");
-
-            // MalformedInputException
-            byte[] bad = { (byte)0xff, (byte)0xff };
-            write(tmpfile, bad);
-            try {
-                readAllLines(tmpfile, US_ASCII);
-                throw new RuntimeException("MalformedInputException expected");
-            } catch (MalformedInputException ignore) { }
-
-
-            // NullPointerException
-            try {
-                readAllLines(null, US_ASCII);
-                throw new RuntimeException("NullPointerException expected");
-            } catch (NullPointerException ignore) { }
-            try {
-                readAllLines(tmpfile, null);
-                throw new RuntimeException("NullPointerException expected");
-            } catch (NullPointerException ignore) { }
-
-            // read from procfs
-            if (System.getProperty("os.name").equals("Linux")) {
-                // Refer to the Linux proc(5) man page for details about /proc/self/status file
-                // procfs reports this file to be zero sized, even though data can be read from it
-                String statusFile = "/proc/self/status";
-                Path pathStatus = Paths.get(statusFile);
-                lines = Files.readAllLines(pathStatus, US_ASCII);
-                assertTrue(lines.size() > 0, "Files.readAllLines('" + pathStatus + "') failed to read");
+            int size = 0;
+            while (size <= 1024) {
+                byte[] b1 = genBytes(size);
+                Files.write(myfile, b1);
+                byte[] b2 = Files.readAllBytes(myfile);
+                assertTrue(Arrays.equals(b1, b2), "bytes not equal");
+                size += 512;
             }
-
         } finally {
-            delete(tmpfile);
+            Files.deleteIfExists(myfile);
         }
     }
 
     /**
-     * Test write(Path,Iterable<? extends CharSequence>,Charset,OpenOption...)
+     * Exercise Files.write(Path, byte[], OpenOption...) on various sizes
      */
-    static void testWriteLines() throws IOException {
-        Path tmpfile = createTempFile("blah", "txt");
-        try {
-            // write method should create file if it doesn't exist
-            if (rand.nextBoolean())
-                delete(tmpfile);
-
-            // zero lines
-            Path result = write(tmpfile, Collections.<String>emptyList(), US_ASCII);
-            assert(size(tmpfile) == 0);
-            assert(result == tmpfile);
-
-            // two lines
-            List<String> lines = Arrays.asList("hi", "there");
-            write(tmpfile, lines, US_ASCII);
-            List<String> actual = readAllLines(tmpfile, US_ASCII);
-            assertTrue(actual.equals(lines), "Unexpected lines");
-
-            // append two lines
-            write(tmpfile, lines, US_ASCII, StandardOpenOption.APPEND);
-            List<String> expected = new ArrayList<String>();
-            expected.addAll(lines);
-            expected.addAll(lines);
-            assertTrue(expected.size() == 4, "List should have 4 elements");
-            actual = readAllLines(tmpfile, US_ASCII);
-            assertTrue(actual.equals(expected), "Unexpected lines");
-
-            // UnmappableCharacterException
-            try {
-                String s = "\u00A0\u00A1";
-                write(tmpfile, Arrays.asList(s), US_ASCII);
-                throw new RuntimeException("UnmappableCharacterException expected");
-            } catch (UnmappableCharacterException ignore) { }
-
-            // NullPointerException
-            try {
-                write(null, lines, US_ASCII);
-                throw new RuntimeException("NullPointerException expected");
-            } catch (NullPointerException ignore) { }
-            try {
-                write(tmpfile, null, US_ASCII);
-                throw new RuntimeException("NullPointerException expected");
-            } catch (NullPointerException ignore) { }
-            try {
-                write(tmpfile, lines, null);
-                throw new RuntimeException("NullPointerException expected");
-            } catch (NullPointerException ignore) { }
-            try {
-                write(tmpfile, lines, US_ASCII, (OpenOption[])null);
-                throw new RuntimeException("NullPointerException expected");
-            } catch (NullPointerException ignore) { }
-            try {
-                OpenOption[] opts = { (OpenOption)null };
-                write(tmpfile, lines, US_ASCII, opts);
-                throw new RuntimeException("NullPointerException expected");
-            } catch (NullPointerException ignore) { }
-
-        } finally {
-            delete(tmpfile);
+    public void testWriteBytes() throws IOException {
+        int size = 0;
+        while (size < 16*1024) {
+            testWriteBytes(size, false);
+            testWriteBytes(size, true);
+            size += 512;
         }
     }
 
-    static void assertTrue(boolean expr, String errmsg) {
-        if (!expr)
-            throw new RuntimeException(errmsg);
+    private void testWriteBytes(int size, boolean append) throws IOException {
+        byte[] bytes = genBytes(size);
+        Path result = Files.write(tmpfile, bytes);
+        assertTrue(result == tmpfile);
+        if (append) {
+            Files.write(tmpfile, bytes, APPEND);
+            assertTrue(Files.size(tmpfile) == size*2);
+        }
+
+        byte[] expected;
+        if (append) {
+            expected = new byte[size << 1];
+            System.arraycopy(bytes, 0, expected, 0, bytes.length);
+            System.arraycopy(bytes, 0, expected, bytes.length, bytes.length);
+        } else {
+            expected = bytes;
+        }
+
+        byte[] read = Files.readAllBytes(tmpfile);
+        assertTrue(Arrays.equals(read, expected), "Bytes read not the same as written");
+    }
+
+    /**
+     * Exercise Files.readAllLines(Path, Charset)
+     */
+    public void testReadAllLines() throws IOException {
+        // zero lines
+        Files.write(tmpfile, new byte[0]);
+        List<String> lines = Files.readAllLines(tmpfile, US_ASCII);
+            assertTrue(lines.isEmpty(), "No line expected");
+
+        // one line
+        byte[] hi = { (byte)'h', (byte)'i' };
+        Files.write(tmpfile, hi);
+        lines = Files.readAllLines(tmpfile, US_ASCII);
+        assertTrue(lines.size() == 1, "One line expected");
+        assertTrue(lines.get(0).equals("hi"), "'Hi' expected");
+
+        // two lines using platform's line separator
+        List<String> expected = Arrays.asList("hi", "there");
+        Files.write(tmpfile, expected, US_ASCII);
+        assertTrue(Files.size(tmpfile) > 0, "File is empty");
+        lines = Files.readAllLines(tmpfile, US_ASCII);
+        assertTrue(lines.equals(expected), "Unexpected lines");
+
+        // MalformedInputException
+        byte[] bad = { (byte)0xff, (byte)0xff };
+        Files.write(tmpfile, bad);
+        try {
+            Files.readAllLines(tmpfile, US_ASCII);
+            fail("MalformedInputException expected");
+        } catch (MalformedInputException ignore) { }
+    }
+
+    /**
+     * Linux specific test to exercise Files.readAllLines(Path) on /proc. This
+     * is special because file sizes are reported as 0 even though the file
+     * has content.
+     */
+    public void testReadAllLinesOnProcFS() throws IOException {
+        if (System.getProperty("os.name").equals("Linux")) {
+            Path statFile = Paths.get("/proc/self/stat");
+            List<String> lines = Files.readAllLines(statFile);
+            assertTrue(lines.size() > 0, "Files.readAllLines('" + statFile + "') failed to read");
+        }
+    }
+
+    /**
+     * Exercise Files.readAllLines(Path)
+     */
+    public void testReadAllLinesUTF8() throws IOException {
+        Files.write(tmpfile, encodeAsUTF8(EN_STRING + "\n" + JA_STRING));
+
+        List<String> lines = Files.readAllLines(tmpfile);
+        assertTrue(lines.size() == 2, "Read " + lines.size() + " lines instead of 2");
+        assertTrue(lines.get(0).equals(EN_STRING));
+        assertTrue(lines.get(1).equals(JA_STRING));
+
+        // a sample of malformed sequences
+        testReadAllLinesMalformedUTF8((byte)0xFF); // one-byte sequence
+        testReadAllLinesMalformedUTF8((byte)0xC0, (byte)0x80);  // invalid first byte
+        testReadAllLinesMalformedUTF8((byte)0xC2, (byte)0x00); // invalid second byte
+    }
+
+    private byte[] encodeAsUTF8(String s) throws CharacterCodingException {
+        // not using s.getBytes here so as to catch unmappable characters
+        ByteBuffer bb = UTF_8.newEncoder().encode(CharBuffer.wrap(s));
+        byte[] result = new byte[bb.limit()];
+        bb.get(result);
+        assertTrue(bb.remaining() == 0);
+        return result;
+    }
+
+    private void testReadAllLinesMalformedUTF8(byte... bytes) throws IOException {
+        Files.write(tmpfile, bytes);
+        try {
+            Files.readAllLines(tmpfile);
+            fail("MalformedInputException expected");
+        } catch (MalformedInputException ignore) { }
+    }
+
+    /**
+     * Exercise Files.write(Path, Iterable<? extends CharSequence>, Charset, OpenOption...)
+     */
+    public void testWriteLines() throws IOException {
+        // zero lines
+        Path result = Files.write(tmpfile, Collections.<String>emptyList(), US_ASCII);
+        assert(Files.size(tmpfile) == 0);
+        assert(result == tmpfile);
+
+        // two lines
+        List<String> lines = Arrays.asList("hi", "there");
+        Files.write(tmpfile, lines, US_ASCII);
+        List<String> actual = Files.readAllLines(tmpfile, US_ASCII);
+        assertTrue(actual.equals(lines), "Unexpected lines");
+
+        // append two lines
+        Files.write(tmpfile, lines, US_ASCII, APPEND);
+        List<String> expected = new ArrayList<>();
+        expected.addAll(lines);
+        expected.addAll(lines);
+        assertTrue(expected.size() == 4, "List should have 4 elements");
+        actual = Files.readAllLines(tmpfile, US_ASCII);
+        assertTrue(actual.equals(expected), "Unexpected lines");
+
+        // UnmappableCharacterException
+        try {
+            String s = "\u00A0\u00A1";
+            Files.write(tmpfile, Arrays.asList(s), US_ASCII);
+            fail("UnmappableCharacterException expected");
+        } catch (UnmappableCharacterException ignore) { }
+    }
+
+    /**
+     * Exercise Files.write(Path, Iterable<? extends CharSequence>, OpenOption...)
+     */
+    public void testWriteLinesUTF8() throws IOException {
+        List<String> lines = Arrays.asList(EN_STRING, JA_STRING);
+        Files.write(tmpfile, lines);
+        List<String> actual = Files.readAllLines(tmpfile, UTF_8);
+        assertTrue(actual.equals(lines), "Unexpected lines");
     }
 }
--- a/jdk/test/java/nio/file/Files/StreamTest.java	Fri Oct 11 20:47:16 2013 +0100
+++ b/jdk/test/java/nio/file/Files/StreamTest.java	Fri Oct 11 20:47:15 2013 +0100
@@ -22,11 +22,10 @@
  */
 
 /* @test
- * @bug 8006884
- * @summary Unit test for java.nio.file.Files
- * @library ..
+ * @bug 8006884 8019526
  * @build PassThroughFileSystem FaultyFileSystem
  * @run testng StreamTest
+ * @summary Unit test for java.nio.file.Files methods that return a Stream
  */
 
 import java.io.IOException;
@@ -43,11 +42,13 @@
 import java.nio.file.Paths;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.concurrent.Callable;
 import java.util.function.BiPredicate;
 import java.util.stream.Stream;
 import java.util.stream.Collectors;
@@ -316,56 +317,80 @@
         try {
             // zero lines
             assertTrue(Files.size(tmpfile) == 0, "File should be empty");
+            try (Stream<String> s = Files.lines(tmpfile)) {
+                checkLines(s, Collections.emptyList());
+            }
             try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
-                assertEquals(s.mapToInt(l -> 1).reduce(0, Integer::sum), 0, "No line expected");
+                checkLines(s, Collections.emptyList());
             }
 
             // one line
-            byte[] hi = { (byte)'h', (byte)'i' };
-            Files.write(tmpfile, hi);
+            List<String> oneLine = Arrays.asList("hi");
+            Files.write(tmpfile, oneLine, US_ASCII);
+            try (Stream<String> s = Files.lines(tmpfile)) {
+                checkLines(s, oneLine);
+            }
             try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
-                List<String> lines = s.collect(Collectors.toList());
-                assertTrue(lines.size() == 1, "One line expected");
-                assertTrue(lines.get(0).equals("hi"), "'Hi' expected");
+                checkLines(s, oneLine);
             }
 
             // two lines using platform's line separator
-            List<String> expected = Arrays.asList("hi", "there");
-            Files.write(tmpfile, expected, US_ASCII);
-            assertTrue(Files.size(tmpfile) > 0, "File is empty");
+            List<String> twoLines = Arrays.asList("hi", "there");
+            Files.write(tmpfile, twoLines, US_ASCII);
+            try (Stream<String> s = Files.lines(tmpfile)) {
+                checkLines(s, twoLines);
+            }
             try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
-                List<String> lines = s.collect(Collectors.toList());
-                assertTrue(lines.equals(expected), "Unexpected lines");
+                checkLines(s, twoLines);
             }
 
             // MalformedInputException
             byte[] bad = { (byte)0xff, (byte)0xff };
             Files.write(tmpfile, bad);
+            try (Stream<String> s = Files.lines(tmpfile)) {
+                checkMalformedInputException(s);
+            }
             try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
-                try {
-                    List<String> lines = s.collect(Collectors.toList());
-                    throw new RuntimeException("UncheckedIOException expected");
-                } catch (UncheckedIOException ex) {
-                    assertTrue(ex.getCause() instanceof MalformedInputException,
-                               "MalformedInputException expected");
-                }
+                checkMalformedInputException(s);
             }
 
             // NullPointerException
-            try {
-                Files.lines(null, US_ASCII);
-                throw new RuntimeException("NullPointerException expected");
-            } catch (NullPointerException ignore) { }
-            try {
-                Files.lines(tmpfile, null);
-                throw new RuntimeException("NullPointerException expected");
-            } catch (NullPointerException ignore) { }
+            checkNullPointerException(() -> Files.lines(null));
+            checkNullPointerException(() -> Files.lines(null, US_ASCII));
+            checkNullPointerException(() -> Files.lines(tmpfile, null));
 
         } finally {
             Files.delete(tmpfile);
         }
     }
 
+    private void checkLines(Stream<String> s, List<String> expected) {
+        List<String> lines = s.collect(Collectors.toList());
+        assertTrue(lines.size() == expected.size(), "Unexpected number of lines");
+        assertTrue(lines.equals(expected), "Unexpected content");
+    }
+
+    private void checkMalformedInputException(Stream<String> s) {
+        try {
+            List<String> lines = s.collect(Collectors.toList());
+            fail("UncheckedIOException expected");
+        } catch (UncheckedIOException ex) {
+            IOException cause = ex.getCause();
+            assertTrue(cause instanceof MalformedInputException,
+                "MalformedInputException expected");
+        }
+    }
+
+    private void checkNullPointerException(Callable<?> c) {
+        try {
+            c.call();
+            fail("NullPointerException expected");
+        } catch (NullPointerException ignore) {
+        } catch (Exception e) {
+            fail(e + " not expected");
+        }
+    }
+
     public void testDirectoryIteratorException() throws IOException {
         Path dir = testFolder.resolve("dir2");
         Path trigger = dir.resolve("DirectoryIteratorException");