提交 d6fde63a 编写于 作者: A alanb

8019526: (fs) Files.lines, etc without Charset parameter

Reviewed-by: psandoz, henryjen
上级 84621ebc
...@@ -43,9 +43,10 @@ import java.nio.channels.SeekableByteChannel; ...@@ -43,9 +43,10 @@ import java.nio.channels.SeekableByteChannel;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder; import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes; 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.FileAttribute;
import java.nio.file.attribute.FileAttributeView; import java.nio.file.attribute.FileAttributeView;
import java.nio.file.attribute.FileOwnerAttributeView; import java.nio.file.attribute.FileOwnerAttributeView;
...@@ -104,8 +105,7 @@ public final class Files { ...@@ -104,8 +105,7 @@ public final class Files {
return () -> { return () -> {
try { try {
c.close(); c.close();
} } catch (IOException e) {
catch (IOException e) {
throw new UncheckedIOException(e); throw new UncheckedIOException(e);
} }
}; };
...@@ -2782,6 +2782,37 @@ public final class Files { ...@@ -2782,6 +2782,37 @@ public final class Files {
return new BufferedReader(reader); return new BufferedReader(reader);
} }
/**
* 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} * 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. * that may be used to write text to the file in an efficient manner.
...@@ -2827,6 +2858,41 @@ public final class Files { ...@@ -2827,6 +2858,41 @@ public final class Files {
return new BufferedWriter(writer); return new BufferedWriter(writer);
} }
/**
* 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. * Reads all bytes from an input stream and writes them to an output stream.
*/ */
...@@ -3025,9 +3091,7 @@ public final class Files { ...@@ -3025,9 +3091,7 @@ public final class Files {
* @throws OutOfMemoryError * @throws OutOfMemoryError
* if an array of the required size cannot be allocated * if an array of the required size cannot be allocated
*/ */
private static byte[] read(InputStream source, int initialSize) private static byte[] read(InputStream source, int initialSize) throws IOException {
throws IOException
{
int capacity = initialSize; int capacity = initialSize;
byte[] buf = new byte[capacity]; byte[] buf = new byte[capacity];
int nread = 0; int nread = 0;
...@@ -3131,9 +3195,7 @@ public final class Files { ...@@ -3131,9 +3195,7 @@ public final class Files {
* *
* @see #newBufferedReader * @see #newBufferedReader
*/ */
public static List<String> readAllLines(Path path, Charset cs) public static List<String> readAllLines(Path path, Charset cs) throws IOException {
throws IOException
{
try (BufferedReader reader = newBufferedReader(path, cs)) { try (BufferedReader reader = newBufferedReader(path, cs)) {
List<String> result = new ArrayList<>(); List<String> result = new ArrayList<>();
for (;;) { for (;;) {
...@@ -3146,6 +3208,37 @@ public final class Files { ...@@ -3146,6 +3208,37 @@ public final class Files {
} }
} }
/**
* 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 * 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 * the file is created or opened. If no options are present then this method
...@@ -3262,6 +3355,45 @@ public final class Files { ...@@ -3262,6 +3355,45 @@ public final class Files {
return path; 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 -- // -- Stream APIs --
/** /**
...@@ -3431,9 +3563,11 @@ public final class Files { ...@@ -3431,9 +3563,11 @@ public final class Files {
* if an I/O error is thrown when accessing the starting file. * if an I/O error is thrown when accessing the starting file.
* @since 1.8 * @since 1.8
*/ */
public static Stream<Path> walk(Path start, int maxDepth, public static Stream<Path> walk(Path start,
int maxDepth,
FileVisitOption... options) FileVisitOption... options)
throws IOException { throws IOException
{
FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options); FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
try { try {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false) return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
...@@ -3484,9 +3618,7 @@ public final class Files { ...@@ -3484,9 +3618,7 @@ public final class Files {
* @see #walk(Path, int, FileVisitOption...) * @see #walk(Path, int, FileVisitOption...)
* @since 1.8 * @since 1.8
*/ */
public static Stream<Path> walk(Path start, public static Stream<Path> walk(Path start, FileVisitOption... options) throws IOException {
FileVisitOption... options)
throws IOException {
return walk(start, Integer.MAX_VALUE, options); return walk(start, Integer.MAX_VALUE, options);
} }
...@@ -3547,7 +3679,8 @@ public final class Files { ...@@ -3547,7 +3679,8 @@ public final class Files {
int maxDepth, int maxDepth,
BiPredicate<Path, BasicFileAttributes> matcher, BiPredicate<Path, BasicFileAttributes> matcher,
FileVisitOption... options) FileVisitOption... options)
throws IOException { throws IOException
{
FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options); FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
try { try {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false) return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
...@@ -3619,4 +3752,33 @@ public final class Files { ...@@ -3619,4 +3752,33 @@ public final class Files {
throw e; 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);
}
} }
/* /*
* 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. * 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
...@@ -22,262 +22,318 @@ ...@@ -22,262 +22,318 @@
*/ */
/* @test /* @test
* @bug 7006126 8020669 8024788 * @bug 7006126 8020669 8024788 8019526
* @build BytesAndLines PassThroughFileSystem * @build BytesAndLines PassThroughFileSystem
* @run main BytesAndLines * @run testng BytesAndLines
* @summary Unit test for methods for Files readAllBytes, readAllLines and * @summary Unit test for methods for Files readAllBytes, readAllLines and
* and write methods. * and write methods.
*/ */
import java.nio.file.*; import java.nio.ByteBuffer;
import static java.nio.file.Files.*; import java.nio.CharBuffer;
import java.io.*; import java.nio.file.Files;
import java.util.*; import java.nio.file.Path;
import java.nio.charset.*; 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 { public class BytesAndLines {
static final Random rand = new Random();
static final Charset US_ASCII = Charset.forName("US-ASCII"); // 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";
// 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 { @BeforeClass
testReadAndWriteBytes(); void setup() throws IOException {
testReadLines(); tmpfile = Files.createTempFile("blah", null);
testWriteLines(); }
@AfterClass
void cleanup() throws IOException {
Files.deleteIfExists(tmpfile);
} }
/** /**
* Test readAllBytes(Path) and write(Path, byte[], OpenOption...) * Returns a byte[] of the given size with random content
*/ */
static void testReadAndWriteBytes() throws IOException { private byte[] genBytes(int size) {
// exercise methods with various sizes byte[] arr = new byte[size];
testReadAndWriteBytes(0); RAND.nextBytes(arr);
for (int i=0; i<100; i++) { return arr;
testReadAndWriteBytes(rand.nextInt(32000));
} }
// NullPointerException /**
* Exercise NullPointerException
*/
public void testNulls() {
Path file = Paths.get("foo"); Path file = Paths.get("foo");
byte[] bytes = new byte[100];
List<String> lines = Collections.emptyList(); List<String> lines = Collections.emptyList();
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 { try {
readAllBytes(null); c.call();
throw new RuntimeException("NullPointerException expected"); fail("NullPointerException expected");
} catch (NullPointerException ignore) { } } catch (NullPointerException ignore) {
try { } catch (Exception e) {
write(null, lines, Charset.defaultCharset()); fail(e + " not expected");
throw new RuntimeException("NullPointerException expected"); }
} catch (NullPointerException ignore) { } }
try {
write(file, null, Charset.defaultCharset());
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException ignore) { }
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) { }
/**
* Exercise Files.readAllBytes(Path) on varied file sizes
*/
public void testReadAllBytes() throws IOException {
int size = 0;
while (size <= 16*1024) {
testReadAllBytes(size);
size += 512;
}
}
private void testReadAllBytes(int size) throws IOException {
// write bytes to file (random content)
byte[] expected = genBytes(size);
Files.write(tmpfile, expected);
// check expected bytes are read
byte[] read = Files.readAllBytes(tmpfile);
assertTrue(Arrays.equals(read, expected), "Bytes read not the same as written");
}
/**
* 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 // read from procfs
if (System.getProperty("os.name").equals("Linux")) { if (System.getProperty("os.name").equals("Linux")) {
// Refer to the Linux proc(5) man page for details about /proc/self/stat file Path statFile = Paths.get("/proc/self/stat");
// procfs reports it to be zero sized, even though data can be read from it byte[] data = Files.readAllBytes(statFile);
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"); assertTrue(data.length > 0, "Files.readAllBytes('" + statFile + "') failed to read");
} }
}
// test readAllBytes on custom file system /**
Path myfile = PassThroughFileSystem.create().getPath(file.toString()); * Exercise Files.readAllBytes(Path) on custom file system. This is special
for (int size=0; size<=1024; size+=512) { * because readAllBytes was originally implemented to use FileChannel
byte[] b1 = new byte[size]; * and so may not be supported by custom file system providers.
rand.nextBytes(b1); */
public void testReadAllBytesOnCustomFS() throws IOException {
Path myfile = PassThroughFileSystem.create().getPath("myfile");
try {
int size = 0;
while (size <= 1024) {
byte[] b1 = genBytes(size);
Files.write(myfile, b1); Files.write(myfile, b1);
byte[] b2 = Files.readAllBytes(myfile); byte[] b2 = Files.readAllBytes(myfile);
assertTrue(Arrays.equals(b1, b2), "bytes not equal"); assertTrue(Arrays.equals(b1, b2), "bytes not equal");
size += 512;
}
} finally {
Files.deleteIfExists(myfile);
} }
} }
/**
* Exercise Files.write(Path, byte[], OpenOption...) on various sizes
*/
public void testWriteBytes() throws IOException {
int size = 0;
while (size < 16*1024) {
testWriteBytes(size, false);
testWriteBytes(size, true);
size += 512;
}
}
static void testReadAndWriteBytes(int size) throws IOException { private void testWriteBytes(int size, boolean append) throws IOException {
Path path = createTempFile("blah", null); byte[] bytes = genBytes(size);
try { Path result = Files.write(tmpfile, bytes);
boolean append = rand.nextBoolean(); assertTrue(result == tmpfile);
if (append) {
byte[] b1 = new byte[size]; Files.write(tmpfile, bytes, APPEND);
rand.nextBytes(b1); assertTrue(Files.size(tmpfile) == size*2);
}
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");
// 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 bytes are correct
byte[] expected; byte[] expected;
if (append) { if (append) {
expected = new byte[b1.length + b2.length]; expected = new byte[size << 1];
System.arraycopy(b1, 0, expected, 0, b1.length); System.arraycopy(bytes, 0, expected, 0, bytes.length);
System.arraycopy(b2, 0, expected, b1.length, b2.length); System.arraycopy(bytes, 0, expected, bytes.length, bytes.length);
} else { } else {
expected = b1; expected = bytes;
}
assertTrue(Arrays.equals(read, expected),
"Bytes read not the same as bytes written");
} finally {
deleteIfExists(path);
} }
byte[] read = Files.readAllBytes(tmpfile);
assertTrue(Arrays.equals(read, expected), "Bytes read not the same as written");
} }
/** /**
* Test readAllLines(Path,Charset) * Exercise Files.readAllLines(Path, Charset)
*/ */
static void testReadLines() throws IOException { public void testReadAllLines() throws IOException {
Path tmpfile = createTempFile("blah", "txt");
try {
List<String> lines;
// zero lines // zero lines
assertTrue(size(tmpfile) == 0, "File should be empty"); Files.write(tmpfile, new byte[0]);
lines = readAllLines(tmpfile, US_ASCII); List<String> lines = Files.readAllLines(tmpfile, US_ASCII);
assertTrue(lines.isEmpty(), "No line expected"); assertTrue(lines.isEmpty(), "No line expected");
// one line // one line
byte[] hi = { (byte)'h', (byte)'i' }; byte[] hi = { (byte)'h', (byte)'i' };
write(tmpfile, hi); Files.write(tmpfile, hi);
lines = readAllLines(tmpfile, US_ASCII); lines = Files.readAllLines(tmpfile, US_ASCII);
assertTrue(lines.size() == 1, "One line expected"); assertTrue(lines.size() == 1, "One line expected");
assertTrue(lines.get(0).equals("hi"), "'Hi' expected"); assertTrue(lines.get(0).equals("hi"), "'Hi' expected");
// two lines using platform's line separator // two lines using platform's line separator
List<String> expected = Arrays.asList("hi", "there"); List<String> expected = Arrays.asList("hi", "there");
write(tmpfile, expected, US_ASCII); Files.write(tmpfile, expected, US_ASCII);
assertTrue(size(tmpfile) > 0, "File is empty"); assertTrue(Files.size(tmpfile) > 0, "File is empty");
lines = readAllLines(tmpfile, US_ASCII); lines = Files.readAllLines(tmpfile, US_ASCII);
assertTrue(lines.equals(expected), "Unexpected lines"); assertTrue(lines.equals(expected), "Unexpected lines");
// MalformedInputException // MalformedInputException
byte[] bad = { (byte)0xff, (byte)0xff }; byte[] bad = { (byte)0xff, (byte)0xff };
write(tmpfile, bad); Files.write(tmpfile, bad);
try { try {
readAllLines(tmpfile, US_ASCII); Files.readAllLines(tmpfile, US_ASCII);
throw new RuntimeException("MalformedInputException expected"); fail("MalformedInputException expected");
} catch (MalformedInputException ignore) { } } 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");
} }
} finally { /**
delete(tmpfile); * 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");
} }
} }
/** /**
* Test write(Path,Iterable<? extends CharSequence>,Charset,OpenOption...) * Exercise Files.readAllLines(Path)
*/ */
static void testWriteLines() throws IOException { public void testReadAllLinesUTF8() throws IOException {
Path tmpfile = createTempFile("blah", "txt"); 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 { try {
// write method should create file if it doesn't exist Files.readAllLines(tmpfile);
if (rand.nextBoolean()) fail("MalformedInputException expected");
delete(tmpfile); } catch (MalformedInputException ignore) { }
}
/**
* Exercise Files.write(Path, Iterable<? extends CharSequence>, Charset, OpenOption...)
*/
public void testWriteLines() throws IOException {
// zero lines // zero lines
Path result = write(tmpfile, Collections.<String>emptyList(), US_ASCII); Path result = Files.write(tmpfile, Collections.<String>emptyList(), US_ASCII);
assert(size(tmpfile) == 0); assert(Files.size(tmpfile) == 0);
assert(result == tmpfile); assert(result == tmpfile);
// two lines // two lines
List<String> lines = Arrays.asList("hi", "there"); List<String> lines = Arrays.asList("hi", "there");
write(tmpfile, lines, US_ASCII); Files.write(tmpfile, lines, US_ASCII);
List<String> actual = readAllLines(tmpfile, US_ASCII); List<String> actual = Files.readAllLines(tmpfile, US_ASCII);
assertTrue(actual.equals(lines), "Unexpected lines"); assertTrue(actual.equals(lines), "Unexpected lines");
// append two lines // append two lines
write(tmpfile, lines, US_ASCII, StandardOpenOption.APPEND); Files.write(tmpfile, lines, US_ASCII, APPEND);
List<String> expected = new ArrayList<String>(); List<String> expected = new ArrayList<>();
expected.addAll(lines); expected.addAll(lines);
expected.addAll(lines); expected.addAll(lines);
assertTrue(expected.size() == 4, "List should have 4 elements"); assertTrue(expected.size() == 4, "List should have 4 elements");
actual = readAllLines(tmpfile, US_ASCII); actual = Files.readAllLines(tmpfile, US_ASCII);
assertTrue(actual.equals(expected), "Unexpected lines"); assertTrue(actual.equals(expected), "Unexpected lines");
// UnmappableCharacterException // UnmappableCharacterException
try { try {
String s = "\u00A0\u00A1"; String s = "\u00A0\u00A1";
write(tmpfile, Arrays.asList(s), US_ASCII); Files.write(tmpfile, Arrays.asList(s), US_ASCII);
throw new RuntimeException("UnmappableCharacterException expected"); fail("UnmappableCharacterException expected");
} catch (UnmappableCharacterException ignore) { } } 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);
}
} }
static void assertTrue(boolean expr, String errmsg) { /**
if (!expr) * Exercise Files.write(Path, Iterable<? extends CharSequence>, OpenOption...)
throw new RuntimeException(errmsg); */
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");
} }
} }
...@@ -22,11 +22,10 @@ ...@@ -22,11 +22,10 @@
*/ */
/* @test /* @test
* @bug 8006884 * @bug 8006884 8019526
* @summary Unit test for java.nio.file.Files
* @library ..
* @build PassThroughFileSystem FaultyFileSystem * @build PassThroughFileSystem FaultyFileSystem
* @run testng StreamTest * @run testng StreamTest
* @summary Unit test for java.nio.file.Files methods that return a Stream
*/ */
import java.io.IOException; import java.io.IOException;
...@@ -43,11 +42,13 @@ import java.nio.file.Path; ...@@ -43,11 +42,13 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -316,53 +317,77 @@ public class StreamTest { ...@@ -316,53 +317,77 @@ public class StreamTest {
try { try {
// zero lines // zero lines
assertTrue(Files.size(tmpfile) == 0, "File should be empty"); 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)) { 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 // one line
byte[] hi = { (byte)'h', (byte)'i' }; List<String> oneLine = Arrays.asList("hi");
Files.write(tmpfile, 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)) { try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
List<String> lines = s.collect(Collectors.toList()); checkLines(s, oneLine);
assertTrue(lines.size() == 1, "One line expected");
assertTrue(lines.get(0).equals("hi"), "'Hi' expected");
} }
// two lines using platform's line separator // two lines using platform's line separator
List<String> expected = Arrays.asList("hi", "there"); List<String> twoLines = Arrays.asList("hi", "there");
Files.write(tmpfile, expected, US_ASCII); Files.write(tmpfile, twoLines, US_ASCII);
assertTrue(Files.size(tmpfile) > 0, "File is empty"); try (Stream<String> s = Files.lines(tmpfile)) {
checkLines(s, twoLines);
}
try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) { try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
List<String> lines = s.collect(Collectors.toList()); checkLines(s, twoLines);
assertTrue(lines.equals(expected), "Unexpected lines");
} }
// MalformedInputException // MalformedInputException
byte[] bad = { (byte)0xff, (byte)0xff }; byte[] bad = { (byte)0xff, (byte)0xff };
Files.write(tmpfile, bad); Files.write(tmpfile, bad);
try (Stream<String> s = Files.lines(tmpfile)) {
checkMalformedInputException(s);
}
try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) { try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
checkMalformedInputException(s);
}
// NullPointerException
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 { try {
List<String> lines = s.collect(Collectors.toList()); List<String> lines = s.collect(Collectors.toList());
throw new RuntimeException("UncheckedIOException expected"); fail("UncheckedIOException expected");
} catch (UncheckedIOException ex) { } catch (UncheckedIOException ex) {
assertTrue(ex.getCause() instanceof MalformedInputException, IOException cause = ex.getCause();
assertTrue(cause instanceof MalformedInputException,
"MalformedInputException expected"); "MalformedInputException expected");
} }
} }
// NullPointerException private void checkNullPointerException(Callable<?> c) {
try {
Files.lines(null, US_ASCII);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException ignore) { }
try { try {
Files.lines(tmpfile, null); c.call();
throw new RuntimeException("NullPointerException expected"); fail("NullPointerException expected");
} catch (NullPointerException ignore) { } } catch (NullPointerException ignore) {
} catch (Exception e) {
} finally { fail(e + " not expected");
Files.delete(tmpfile);
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册