Java文件內容和讀寫
文件的內容類型
Files.probeContentType(Path path)
方法探測文件的內容類型。該方法以多用途互聯網郵件擴展(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();
}
}
}
上面的代碼生成以下結果。
Content type of C:\Java_Dev\test1.txt is text/plain
讀取文件的內容
Files
類包含以下方法來讀取文件的內容作爲字節和文本行:
- static byte[] readAllBytes(Path path) - reads all bytes from a file.
- static List readAllLines(Path path) - reads the entire contents of a file lines of text.
- 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
選項打開文件。
如果正在向文件寫入文本,它會寫一個平臺相關的行分隔符。如果在寫入文本行時未指定字符集,則默認使用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 line - 1");
texts.add("test line - 2");
Path dest = Paths.get("C:\\Java_Dev\\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... options)
方法爲指定的路徑返回BufferedWriter
。
執行上面代碼,得到以下結果 -
Text was written to C:\Java_Dev\twinkle.txt
隨機訪問文件
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();
}
}
}
上面的代碼生成以下結果。
Before writing data: Size = 0, Position = 0
After writing data: Size = 13, Position = 13
After resetting position to 0: Size = 13, Position = 0
test
test2