
命裡有時終須有,命裡無時莫強求。
簡介
- IO操作是指Input、Output,資料的輸入與輸出,主要是操作資料:
- Input指的是從資料源讀取資料到記憶體,例如:把資料從磁盤上讀取到記憶體中,從網絡讀取資料到記憶體中等等。
- Output值得是把資料輸出到其他地方,例如:把資料寫入到檔案,把資料輸出到網絡等等。
- Java中把檔案中的内容讀取到記憶體叫做輸入流InputStream,而把資料寫入到檔案中叫做輸出OutputStream,這是最基本的兩種IO流
同步和異步
- 同步是指讀寫IO的操作完成以後才能完成其他任務,優點是編寫簡單,缺點是執行效率低
- 異步是指讀寫IO的操作的同僚可以完成其他任務,優點是執行效率高,缺點是編寫複雜
-
提供同步IOjava.io
-
提供異步IOjava.nio
File對象
-
中提供了檔案操作類File,使用構造方法建立一個File對象,即使檔案或者目錄不存在也不會報錯,因為這個時候并不會操作磁盤,隻有調用File對象的具體方法時候才會進行磁盤操作java.io
public class DemoController {
public static void main(String[] args){
File f = new File("C:javahello.java");
System.out.println(f); // C:javahello.java
}
}
- getPath(),該方法傳回構造方法傳入的路徑,原封不動的傳回
public class DemoController {
public static void main(String[] args){
File f = new File(".javahello.java");
System.out.println(f.getPath()); // .javahello.java
}
}
- getAbsolutePath(),該方法傳回的是絕對路徑,拼接上完整的路徑但是不幫着處理. ..符号(.表示目前目錄 ..表示上級目錄)
public class DemoController {
public static void main(String[] args){
File f = new File(".javahello.java");
System.out.println(f.getAbsolutePath()); // E:javaProjectstudy.javahello.java
}
}
- getCanonicalPath(),該方法傳回的是處理好的規範路徑
public class DemoController {
public static void main(String[] args) throws IOException {
File f = new File(".javahello.java");
System.out.println(f.getCanonicalPath()); // E:javaProjectstudyjavahello.java
}
}
- separator 可以列印對應系統下的路徑分隔符
public class DemoController {
public static void main(String[] args) {
System.out.println(File.separator); // windows linux /
}
}
- isFile() 判斷檔案是否存在
- isDirectory() 判斷檔案目錄是否存在
- canRead() 是否可讀
- canWrite() 是否可寫
- canExecute() 是否可執行 如果是目錄則表示能否顯示所有的檔案和子目錄
- length() 檔案位元組大小
- createNewFile() 建立一個新檔案
- delete() 删除檔案
- createTempFile() 建立臨時檔案,與deleteOnExit()在JVM退出時删除改檔案,兩者關聯使用
- list()和listFiles() 列出目錄下面所有檔案和子目錄名,listFiles提供了很多重載方法,可以過濾檔案和目錄
- mkdir() 建立目錄
- mkdirs() 建立目錄,如果父目錄不存在也會建立
- delete() 删除目錄,目錄必須為空才能删除成功
Path對象
- Path位于Java.nio.file包。Path對象和File對象差不多
- Paths.get(".","father","children"...) 建立一個Path對象
- toAbsolutePath() 轉化為絕對路徑
- normalize() 轉化為規範路徑
- toFile() 轉化為File對象
InputStream
- InputSteam是一個抽象類,FileInputStream是InputSteam的子類
public static void readFile() throws IOException {
InputStream inputStream = null;
try{
inputStream = new FileInputStream("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt"); // 檔案裡面寫Hello World!, 檔案可以儲存任意地方
int n;
while((n = inputStream.read()) != -1){
System.out.println((char) n);
}
} finally {
inputStream.close(); // 關閉流,必須用完就關閉流
}
}
緩沖
- 上面的read雖然可疑讀取檔案内容,但是一次隻能讀取一個位元組,并不是很高效,可以通過InputSteam中的重載方法來讀取多個位元組
public static void readMoreFile() throws IOException {
InputStream inputStream = null;
byte[] bytes = new byte[1000];
try{
inputStream = new FileInputStream("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt");
int n;
while((n = inputStream.read(bytes)) != -1){
System.out.println(n);
}
} finally {
inputStream.close(); // 關閉流
}
}
阻塞
- 阻塞的意思就是有任務在執行,卡在那不往後面執行,比如在執行read()方法的時候就需要等待read()方法傳回後才能執行下面的代碼
模拟InputStream
- 可以使用
僞造一個資料流ByteArrayInputStream
public static void makeSteam () throws IOException {
byte[] data = { 72, 101, 108, 108, 111, 33 };
try (InputStream inputStream = new ByteArrayInputStream(data)) {
int n;
while ((n = inputStream.read()) != -1) {
System.out.println((char) n);
}
}
}
OutputStream
- 與InputStream相反,OutputStream是輸出流的超類,也是抽象類。
- OutputSteam也提供了
方法關閉輸出流,還提供了一個close()
方法,作用是将内容真正輸出到目的地,通常情況不需要調用這個人方法,因為OutputStream會自動調用,如果需要在某些特定情況主動推送緩存發送就需要主動觸發flushflush()
public static void fileOutput() throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt");
// 寫入 wirte方法也是阻塞的
fileOutputStream.write(72); // H
fileOutputStream.write(101); // e
fileOutputStream.write(108); // l
fileOutputStream.write(108); // l
fileOutputStream.write(111); // o
fileOutputStream.close();
// 或者通過write的重載方法 與InputStream一樣,為了避免IO錯誤導緻資源沒有關閉,通常需要用try...finally
try (OutputStream fileOutputStream2 = new FileOutputStream("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt")){
fileOutputStream.write("Hello".getBytes("UTF-8")); // Hello
} finally {
fileOutputStream.close();
}
}
- FileOutputStream是OutputStream的一個實作類,可以從檔案中擷取輸出流。與InputStream一樣,ByteArrayOutputStream可以再記憶體中模拟一個OutputStream輸出流
public static void makeOutput () throws IOException {
byte[] data;
ByteArrayOutputStream outputStream = null;
try {
outputStream = new ByteArrayOutputStream();
outputStream.write("Hello".getBytes());
data = outputStream.toByteArray();
} finally {
outputStream.close();
}
System.out.println(new String(data, "UTF-8"));
}
操作zip
- 讀取zip使用ZipInputStream
public static void getZip() throws IOException {
ZipInputStream zipInputStream = null;
try{
zipInputStream = new ZipInputStream(new FileInputStream("E:javaProjectstudystudy-20-8-30srcDemo05Demo05.zip"));
ZipEntry entry = null;
// 判斷是否還有檔案
while ((entry = zipInputStream.getNextEntry()) != null){
String name = entry.getName(); // 擷取檔案名字
System.out.println(name);
if (!entry.isDirectory()){
int n;
while ((n = zipInputStream.read()) != -1){
System.out.println((char) n);
}
}
}
}finally {
zipInputStream.close();
}
}
- 寫入zip包時使用的是ZipOutputStream
public static void setZip() throws IOException {
ZipOutputStream zipOutputStream = null;
try {
zipOutputStream = new ZipOutputStream(new FileOutputStream("E:javaProjectstudystudy-20-8-30srcDemo05Demo05.zip"));
ArrayList<File> files = new ArrayList<>();
files.add(new File("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt"));
files.add(new File("E:javaProjectstudystudy-20-8-30srcDemo05readme - 副本.txt"));
for (File file : files) {
zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
zipOutputStream.write(getFileToByte(file));
zipOutputStream.closeEntry();
}
}finally {
zipOutputStream.close();
}
}
public static byte[] getFileToByte(File file) {
byte[] by;
try {
InputStream inputStream = new FileInputStream(file);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bb = new byte[2048];
int ch;
ch = inputStream.read(bb);
while (ch != -1) {
byteArrayOutputStream.write(bb, 0, ch);
ch = inputStream.read(bb);
}
by = byteArrayOutputStream.toByteArray();
} catch (Exception ex) {
throw new RuntimeException("transform file into bin Array 出錯",ex);
}
return by;
}
Reader與Writer
- 如果是讀寫字元,比如純文字的資料源,可以使用Reader和Writer進行讀和寫的操作,這種流成為字元流,資料源雖然是位元組的,但是Reader和Writer内部進行了處理,将byte做了解碼轉化為char
- FileReader是Reader的一個子類,FileReader可以打開一個檔案并讀取
public static void readerReadFile() throws IOException {
Reader reader = null;
try{
reader = new FileReader("E:javaProjectstudystudy-20-8-30srcDemo05readme.txt");
int n;
while((n = reader.read()) != -1){
System.out.println((char) n);
}
}finally {
reader.close();
}
}
- CharArrayReader可以通過傳入一個char[]模拟一個Reader
Reader reader = new CharArrayReader("Hello".toCharArray);
- StringReader 可以通過傳入一個String 模拟一個StringReader
Reader reader = new StringReader("Hello")
- InputStreamReader可以通過傳入一個InputStream轉為一個Reader
Reader reader = new InputStreamReader(new FileInputStream("XXX"),"UTF-8");
- FileWriter可以項檔案中寫入字元流
Writer writer = new FileWriter("XXX");
wirter.wirter("asdas");
- CharArrayWriter可以在記憶體中建立一個Writer,作用就是狗在一個一個緩沖區
public static void wirterFile() {
try (CharArrayWriter writer = new CharArrayWriter()) {
writer.write(72); // H
writer.write(101); // e
writer.write(108); // l
writer.write(108); // l
writer.write(111); // o
char[] data = writer.toCharArray();
System.out.println(new String(data));
}
}
- StringWriter也是一個機遇記憶體的writer和CharArrayWriter類似
- OutPutStreamWriter可以講一個FileOutputStream流轉化為Writer
本文作者《猿氏·凱》,如果雷同,純屬抄襲····