Java IO教程 - Java文件内容
文件的内容类型
Files.probeContentType(Path path)方法探测文件的内容类型。
该方法以多用途Internet邮件扩展(MIME)内容类型的值的字符串形式返回内容类型。
如果一个文件的内容类型不能确定,则返回null。
以下代码显示如何探测文件的内容类型。
import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.io.IOException; public class Main { public static void main(String[] args) { Path p = Paths.get("C:\\Java_Dev\\test1.txt"); try { String contentType = Files.probeContentType(p); System.out.format("Content type of %s is %s%n", p, contentType); } catch (IOException e) { e.printStackTrace(); } } }
上面的代码生成以下结果。
读取文件的内容
Files类包含以下方法来读取文件的内容作为字节和文本行:
- static byte[] readAllBytes(Path path) - 读取文件中的所有字节。
- static List readAllLines(Path path) - 读取文本文本行的整个内容。
- static List readAllLines(Path path, Charset cs)
Files类可以从Path对象获取InputStream和BufferedReader对象。
newInputStream(Path path,OpenOption ... options)方法返回指定路径的InputStream对象。它假定文件的内容是UTF-8字符集。
newBufferedReader(Path path)和newBufferedReader(Path path,Charset cs)方法返回一个BufferedReader。我们可以指定字符集。
Files类提供了使用其newByteChannel(Path path,OpenOption ... options)方法从Path对象中获取SeekableByteChannel对象的方法。
OpenOption类型配置正在打开的文件。下表列出了OpenOption类型的值及其描述。OpenOption是java.nio.file包中的一个接口。
java.nio.file包中的StandardOpenOption枚举实现了OpenOption接口。
标准打开选项 | 描述 |
---|---|
APPEND | 将写入的数据附加到现有文件,如果文件被打开写入。 |
CREATE | 创建一个新文件,如果它不存在。 |
CREATE_NEW | 创建一个新文件,如果它不存在。如果文件已存在,则操作失败。 |
DELETE_ON_CLOSE | 关闭流时删除文件。 在与临时文件一起使用时非常有用。 |
DSYNC | 保持文件的内容与底层存储同步。 |
READ | 打开具有读访问权限的文件。 |
SPARSE | 如果它与CREATE_NEW选项一起使用,它对文件系统提示新文件应该是稀疏文件。 |
SYNC | 保持文件的内容和元数据与底层存储同步。 |
TRUNCATE_EXISTING | 如果打开文件以进行写访问,则将现有文件的长度截断为零。 |
WRITE | 打开文件以进行写访问。 |
以下代码在默认目录中为test2.txt文件获取一个SeekableByteChannel对象。
它打开文件以进行读取和写入访问。它使用CREATE选项,因此如果文件不存在,则创建该文件。
import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.READ; import static java.nio.file.StandardOpenOption.WRITE; import java.nio.channels.SeekableByteChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { Path src = Paths.get("test2.txt"); SeekableByteChannel sbc = Files.newByteChannel(src, READ, WRITE, CREATE); } }
以下代码演示了如何读取和显示我们默认目录中test1.txt文件的内容。 如果文件不存在,程序将显示一条错误消息。
import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; public class Main { public static void main(String[] args) throws Exception{ Charset cs = Charset.forName("US-ASCII"); Path source = Paths.get("test1.txt"); List<String> lines = Files.readAllLines(source, cs); for (String line : lines) { System.out.println(line); } } }
写入文件
我们可以使用Files类的以下write()方法将内容写入文件。
static Path write(Path path, byte[] bytes, OpenOption... options) static Path write(Path path, Iterable lines, OpenOption... options) static Path write(Path path, Iterable lines, Charset cs, OpenOption... options)
write()方法打开文件,将传递的内容写入文件,并关闭它。
如果没有打开选项,它将使用CREATE,TRUNCATE_EXISTING和WRITE选项打开文件。
如果我们正在向文件写入文本,它会写一个平台相关的行分隔符。
如果在写入文本行时未指定charset,则假定使用UTF-8字符集。
以下代码演示如何使用write()方法将文本行写入文件。
import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.WRITE; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<String> texts = new ArrayList<>(); texts.add("test"); texts.add("test"); Path dest = Paths.get("twinkle.txt"); Charset cs = Charset.forName("US-ASCII"); try { Path p = Files.write(dest, texts, cs, WRITE, CREATE); System.out.println("Text was written to " + p.toAbsolutePath()); } catch (IOException e) { e.printStackTrace(); } } }
Files.newOutputStream(Path path,OpenOption ... options)返回指定路径的OutputStream。
Files.newBufferedWriter(Path path,Charset cs,OpenOption ...选项)方法为指定的路径返回BufferedWriter。
上面的代码生成以下结果。
随机访问文件
SeekableByteChannel对象提供对文件的随机访问。
我们可以使用Files类的newByteChannel()方法为Path获取一个SeekableByteChannel对象,如下所示:
Path src = Paths.get("test.txt"); SeekableByteChannel seekableChannel = Files.newByteChannel(src, READ, WRITE, CREATE, TRUNCATE_EXISTING);
我们可以使用size()方法以字节为单位获取SeekableByteChannel实体的大小。
由于数据被截断或写入通道,因此更新了大小。
import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.READ; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; import static java.nio.file.StandardOpenOption.WRITE; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.SeekableByteChannel; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path src = Paths.get("test.txt"); String encoding = System.getProperty("file.encoding"); Charset cs = Charset.forName(encoding); try (SeekableByteChannel seekableChannel = Files.newByteChannel(src, READ, WRITE, CREATE, TRUNCATE_EXISTING)) { printDetails(seekableChannel, "Before writing data"); writeData(seekableChannel, cs); printDetails(seekableChannel, "After writing data"); seekableChannel.position(0); printDetails(seekableChannel, "After resetting position to 0"); readData(seekableChannel, cs); printDetails(seekableChannel, "After reading data"); } catch (IOException e) { e.printStackTrace(); } } public static void writeData(SeekableByteChannel seekableChannel, Charset cs) throws IOException { String separator = System.getProperty("line.separator"); StringBuilder sb = new StringBuilder(); sb.append("test"); sb.append(separator); sb.append("test2"); sb.append(separator); CharBuffer charBuffer = CharBuffer.wrap(sb); ByteBuffer byteBuffer = cs.encode(charBuffer); seekableChannel.write(byteBuffer); } public static void readData(SeekableByteChannel seekableChannel, Charset cs) throws IOException { ByteBuffer byteBuffer = ByteBuffer.allocate(128); String encoding = System.getProperty("file.encoding"); while (seekableChannel.read(byteBuffer) > 0) { byteBuffer.rewind(); CharBuffer charBuffer = cs.decode(byteBuffer); System.out.print(charBuffer); byteBuffer.flip(); } } public static void printDetails(SeekableByteChannel seekableChannel, String msg) { try { System.out.println(msg + ": Size = " + seekableChannel.size() + ", Position = " + seekableChannel.position()); } catch (IOException e) { e.printStackTrace(); } } }
上面的代码生成以下结果。