目錄
IO 簡介
在馮諾依曼體系結構我見到了各種各樣的輸入設備(鼠標、鍵盤、硬盤、網卡等等)和輸出設備(音響、屏幕、硬盤、、網卡等等)。其實,IO(Input/Output)其實解決的就是一個輸入輸出的問題。
Input:數據從各種輸入設備以二進制流輸入到內存中
Output:數據從內存以二進制流輸出到各種輸出設備
因爲有各種不同的輸入輸出設備,纔會出現不同的輸入輸出流。而且,數據天生的格式都是字節流(二進制流)。通過上面的分析,我們會發現硬盤既是一種輸入設備 又是一種輸出設備。那麼如何通過java提供的API把內存中的數據保存到硬盤中,又如何把硬盤中的數據讀入到內存中呢?我們必須要瞭解到下面的File類。
瞭解File類
1. File類基本介紹
File類其實就是描述文件源信息(屬性)的一組類。那麼文件是什麼呢?
書上是這麼描述的:文件是相關記錄或者放在一起的數據的集合。其實文件就是OS對硬盤空間一塊一塊的抽象。在windows操作中,經常在硬盤上創建的各種.txt, .doc, .exe, .java, .lib, .mp3等等,都可以稱之爲文件。文件簡單的可以理解成,在外設硬盤上面保存數據的一種方式。
文件一共可以由兩部分構成:屬性(文件大小,文件名,文件類型等)+內容(就是文件裏面放的是什麼) 。 File文件操作類在 java.io 包之中,用 File 類來對文件進行操作(創建、刪除、取得信息等)
2. File類常見操作
1. 獲取文件基本信息
public static void main(String[] args) throws IOException {
{
// File 對象的實際文件不存在
String path = "D:\\文檔\\File類練習\\test.txt";
File file = new File(path);
System.out.println(file);
}
// 傳入一個父路徑
{
String parent = "D:\\文檔\\File類練習";
String path = "test.txt";
File file = new File(parent, path);
System.out.println(file);
// 獲取常見的屬性
System.out.println(file.exists()); //文件是否存在
System.out.println(file.getAbsolutePath()); //返回絕對路徑
System.out.println(file.getName()); //返回文件名
System.out.println(file.getParent()); //返回父路徑
System.out.println(file.isAbsolute()); //是否爲絕對路徑
System.out.println(file.isDirectory()); //是否是目錄
System.out.println(file.isFile()); //是否是文件
System.out.println(file.isHidden()); //是否是隱藏的
System.out.println(file.canRead()); //是否可讀
System.out.println(file.canWrite()); //是否可寫
System.out.println(file.canExecute()); //是否可執行
}
}
2. 文件的創建
//普通文件的創建
String parent = "D:\\文檔\\File類練習"; //路徑
String fileName = "文件1.txt"; //文件名
File file = new File(parent, fileName);
3. 文件夾的創建
// 文件夾的創建過程
String parent = "D:\\文檔\\File類練習"; //父路徑
String filename = "文件夾的創建"; //文件夾名稱
File file = new File(parent, filename);
4. 文件的刪除
file.deleteOnExit(); //請求在虛擬機終止時刪除由此抽象路徑名錶示的文件或目錄。
boolean delete = file.delete();// 只能刪除一個空的文件夾
5. 文件夾文件的操作
獲取文件夾下面的文件
String path = "D:\\文檔";
File dir = new File(path);
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
System.out.println(file.getName());
}
}
流
1. 流的基本概念
在Java中所有數據都是使用流讀寫的。流是一組有順序的,有起點和終點的字節集合,是對數據傳輸的總稱或抽象。即數據在兩設備間的傳輸稱爲流,流的本質是數據傳輸,根據數據傳輸特性將流抽象爲各種類,方便更直觀的進行數據操作。
2. 輸入輸出流
3. 字節流
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("輸入文件.txt")) {
byte[] buf = new byte[8192];
int len;
while ((len = is.read(buf)) != -1) {
// 有效數據是 buf[0, len)
for (int i = 0; i < len; i++) {
// 如果直接按照數字打印出來,就是打印 ASCII
// System.out.println(buf[i]);
char c = (char)buf[i];
System.out.print(c);
}
}
}
}
文件輸出字節流(寫):
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("輸出內容.txt")) {
// Second 一次寫一個字節的方式
//寫法1
os.write('S');
os.write('e');
os.write('c');
os.write('o');
os.write('n');
os.write('d');
os.write('\r');
os.write('\n');
// 寫法2
byte[] buf = new byte[1024];
buf[0] = (byte)'T';
buf[1] = (byte)'h';
buf[2] = (byte)'i';
buf[3] = (byte)'r';
buf[4] = (byte)'d';
buf[5] = (byte)'\r';
buf[6] = (byte)'\n';
os.write(buf, 0, 7);
//寫法3
String s = "Hello World\r\n";
byte[] bytes = s.getBytes(); //string內部可以把它轉爲byte類型數組
os.write(bytes);
os.flush(); // 保證把所有緩衝的數據全部寫入硬盤中
}
}
}
4. 字符流
字符流:數據流中最小的數據單元是字節, Java中的字符是Unicode編碼,一個字符佔用兩個字節:Reader、Writer
文件輸入字節流(讀):
private static void read() throws IOException {
try (InputStream is = new FileInputStream("某篇文章.txt")) {
try (InputStreamReader isReader = new InputStreamReader(is, "UTF-8")) {
try (Scanner scanner = new Scanner(isReader)) {
// 按行讀
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
}
}
}
}
}
文件輸出字節流(寫):
private static void write() throws IOException {
try (OutputStream os = new FileOutputStream("某篇文章.txt")) {
try (OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-8")) {
try (PrintWriter printWriter = new PrintWriter(osWriter)) {
printWriter.println("");
printWriter.printf("");
printWriter.print("");
printWriter.format("");
printWriter.flush();
}
}
}
}
那麼字符流和字節流有什麼區別呢?
序列化與反序列化
1. 什麼是序列化
序列化:把對象轉換爲字節序列的過程稱爲對象的序列化。
2. 序列化使用場景
3. 如何序列化
實現序列化其實有很多方式:Java對象序列化、JSON序列化、XML等等。如果Java對象進行序列化需要實現Serializable接口即可。
用一組例子來說明序列化和反序列化:
package uesFile.com;
import java.io.*;
public class SerializeDemo {
// 聲明實現 Serializable 接口
// 聲明之後,就擁有了可以序列號和反序列化的功能了
static class Person implements Serializable {
String name;
int age;
}
//讀
public static void main(String[] args) throws IOException, ClassNotFoundException {
try (InputStream is = new FileInputStream("名單.binary")) {
try (ObjectInputStream ois = new ObjectInputStream(is)) {
Person p = (Person) ois.readObject();
System.out.println(p.name);
System.out.println(p.age);
Person q = (Person) ois.readObject();
System.out.println(q.name);
System.out.println(q.age);
}
}
}
//寫
public static void main(String[] args) throws IOException {
Person p = new Person();
p.name = "人員1"; p.age = 34;
Person q = new Person();
q.name = "人員2"; q.age = 18;
try (OutputStream os = new FileOutputStream("名單.binary")) {
try (ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(p);
oos.writeObject(q);
oos.flush();
}
}
}
}
就算程序關閉,文件中的內容也不會消失。實現了先寫,再進行讀的序列化。這就實現了Java對象的實例化。