本文主要借鑑以下博客和網站:
how2j.cn
深入理解java中的I/O
JAVA文件操作
JAVA描述和管理文件的類是java.io.File類,通過File生成的對象file,可以通過以下指令對文件進行操作:
- file.exists() – 判斷文件是否存在
- file.isDirectory() – 判斷文件是否爲文件夾
- file.isFile() – 判斷是否是普通文件(不是文件夾)
- file.length() – 獲取文件的長度
- file.lastModified() – 獲取文件最後修改的時間
- file.getAbsolutePath() – 獲取文件的絕對路徑
- file.list() – 返回當前文件夾的所有子文件的文件名(深度爲1),返回類型爲字符串數組
- file.listFiles() – 返回當前文件夾的所有子文件(深度爲1),返回類型爲文件數組
- file.getParent() – 返回當前文件的父文件夾的名字
- file.getParentFile() – 返回當前文件的父文件夾
- file.mkdir() – 創建文件夾(如果父類文件夾不存在,則創建無效)
- file.mkdirs() – 創建文件夾(如果父類文件夾不存在,則連同父文件夾一同創建)
- file.getParentFile().mkdirs() – 常用,創建一個文件前,常把父類目錄都創好
- file.delete() – 刪除文件
以下將展示幾種流的使用方法(只展示讀,寫文件類似)
JAVA字節流
操作數據類型是字節,也就是JAVA數據類型中的byte,所有字節流的父類是InputStream和OutputStream(兩個都是的抽象類)在這裏插入代碼片
直接上代碼:
import java.io.*;
public class Main {
public static void main(String[] args) {
//文件中內容是 aAbB
File file = new File("src/blog/test.txt");
//對於文件操作,採用字節輸入流子類FileInputStream
//建議採用在try括號內使用流的聲明,即使在異常時也能關閉流,減少資源損耗
try(InputStream fi = new FileInputStream(file)){
byte[] bytes = new byte[(int) file.length()];
//將文件中的數據以字節流形式讀入到bytes中
fi.read(bytes);
for(byte b : bytes) {
System.out.println(b);//打印ASCII碼的十進制形式
}
}catch (FileNotFoundException fe) {
fe.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
結果爲(“aAbB”的ASCII碼的十進制):
97
65
98
66
JAVA字符流
與字節流不同,字符流操作的數據對象的最小單元是字符,比較符合我們的日常讀文本的習慣,所以在讀文本時用的很多,具體的字符輸入流和字符輸出流爲Reader和Writer,專門用於字符的形式讀取和寫入數據。
具體代碼如下:
import java.io.*;
public class Main {
public static void main(String[] args) {
//文件中內容是 aAbB
// cCdD
File file = new File("src/blog/test.txt");
//對於文件操作,採用字符輸入流FileReader
//建議採用在try括號內使用流的聲明,即使在異常時也能關閉流,減少資源損耗
try(Reader fr = new FileReader(file)){
char[] chs = new char[(int) file.length()];
fr.read(chs);
for(char c : chs) {
System.out.print(c);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
運行結果如下(輸出文本內容aAbBcCdD):
aAbB
cCdD
有時我們要對文本進行逐行處理,但以上的方法都是“一口將文件喫掉“,一次性讀完所有的內容,這時我們需要一個新的流來幫我們一步步做,這時緩存流就登上了舞臺。
JAVA緩存流
JAVA緩存流讀取數據用的是BufferedReader,寫入數據用的是BufferedWriter。這裏用到了設計模式中的裝飾者模式,在此不過多贅述,我們直接看緩存流是如何”裝飾“字符流來實現逐行讀取的。
代碼如下:
import java.io.*;
public class Main {
public static void main(String[] args) {
//文件中內容是 aAbB
// cCdD
File file = new File("src/blog/test.txt");
//逐行讀取,採用緩存流BufferedReader
//建議採用在try括號內使用流的聲明,即使在異常時也能關閉流,減少資源損耗
try(
Reader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
)
{
String line = "";
while((line = br.readLine()) != null) {//讀取一行
System.out.println(line.toUpperCase());//全部轉化爲大寫
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
輸出處理後的結果:
AABB
CCDD
JAVA對象流
對象流指的是可以直接把一個對象以流的形式傳輸給其他的介質,但是,把一個對象序列化有一個前提是:這個對象的類,必須實現了Serializable接口。
注意,寫入到文本時,對象以序列化後的二進制形式存放,用文本查看時會亂碼
代碼如下:
import java.io.*;
class Student implements Serializable{
//表示這個類當前的版本,如果有了變化,比如新設計了屬性,就應該修改這個版本號
private static final long serialVersionUID = 1L;
String name;
int id;
public Student(String name, int id) {
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "Student [name=" + name + ", id=" + id + "]";
}
}
public class Main {
public static void main(String[] args) {
File file = new File("src/blog/test.txt");
write(file);
read(file);
}
//寫入對象
static void write(File file) {
try(
OutputStream out = new FileOutputStream(file);
ObjectOutputStream objout = new ObjectOutputStream(out);//對象輸出流
)
{
Student[] students = new Student[2];
students[0]= new Student("xsy", 123456);
students[1] = new Student("theory", 654321);
objout.writeObject(students);//只能寫一次
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//讀取對象
static void read(File file) {
try(
InputStream in = new FileInputStream(file);
ObjectInputStream objin = new ObjectInputStream(in);//對象輸入流
)
{
Student[] students = (Student[]) objin.readObject(); // 讀取文件中的所有對象
for (Student s : students) {
System.out.println(s);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
對象讀取的運行結果爲:
Student [name=xsy, id=123456]
Student [name=theory, id=654321]
JAVA數據流
數據流的目的在於對文本數據進行格式化讀寫,以下代碼先寫入一個整型int和字符串String,然後按順序readInt和readUTF讀取。
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
write();
read();
}
private static void read() {
File f =new File("src\\blog\\test.txt");
try (
FileInputStream fis = new FileInputStream(f);
DataInputStream dis =new DataInputStream(fis);
){
int i = dis.readInt();
String str = dis.readUTF();
System.out.println(i);
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void write() {
File f =new File("src\\blog\\test.txt");
try (
FileOutputStream fos = new FileOutputStream(f);
DataOutputStream dos =new DataOutputStream(fos);
){
dos.writeInt(1);
dos.writeUTF("xsy");
} catch (IOException e) {
e.printStackTrace();
}
}
}
運行結果如下:
1
xsy