package com.zb.io.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
public class IO {
public static final String PATH1 = "temp/1.txt";
public static final String PATH2 = "temp/2.txt";
public static final String PATH3 = "temp/3.txt";
public static final String PATH4 = "temp/4.txt";
public static final String PATH5 = "temp/5.txt";
public static void main(String[] args) {
try {
// 創建文件夾和文件
File file = createDirAndFile(PATH1);
// 使用字節流OutPutStream寫入文件信息
setFileByByteIoOutPutStream(file);
// 使用字節流InPutStream讀取文件信息
getFileByByteIoInPutStream(file);
file = createDirAndFile(PATH2);
//使用Writer寫入文件信息
setFileByCharIoWriter(file);
//使用Reader讀取文件信息
getFileByCharIoReader(file);
file = createDirAndFile(PATH3);
//使用OutputStreamWriter寫入文件信息
setFileByCharIoOutputStreamWriter(file);
//使用InputStreamReader讀取文件信息
getFileByCharIoInputStreamReader(file);
file = createDirAndFile(PATH4);
//使用BufferedWriter寫入文件信息
setFileByCharIoBufferedWriter(file);
//使用BufferedReader讀取文件信息
getFileByCharIoBufferedReader(file);
file = createDirAndFile(PATH5);
//使用BufferedOutputStream寫入文件信息
setFileByBufferedOutputStream(file);
//使用BufferedInputStream讀取文件信息
getFileByBufferedInputStream(file);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 在指定的目錄創建文件夾和文件
* @param path
*
* @throws IOException
*/
public static File createDirAndFile(String path) throws IOException {
File fileDir = new File("temp");
if (!fileDir.exists() && !fileDir.isDirectory()) {
System.out.println("開始創建新的文件夾!");
fileDir.mkdir();
} else {
System.out.println("文件夾已存在,無需創建!");
}
System.out.println("當前文件夾的路徑是:" + fileDir.getAbsolutePath());
File file = new File(path);
if (!file.exists()) {
System.out.println("開始創建新的文件!");
file.createNewFile();
} else {
System.out.println("文件已存在,無需創建!");
}
System.out.println("當前文件的路徑是:" + file.getAbsolutePath());
return file;
}
/**
* 使用OutPutStream寫入文件
*
* @throws IOException
*/
public static void setFileByByteIoOutPutStream(File file) throws IOException {
StringBuffer sb = new StringBuffer("使用字節流OutPutStream寫入文件信息!");
sb.append("\r\n在java中,可以使用InputStream對文件進行讀取,就是字節流的輸入。!");
sb.append("\r\n當讀取文件內容進程序時,需要使用一個byte數組來進行存儲,如此會有如下兩個問題:");
sb.append("\r\n1.如何建立合適大小的byte數組,如果已知輸入流的大小。");
sb.append("\r\n2.如果不知輸入流的大小,則肯定需要建立一個很大的byte數組,那麼byte中很可能有空的內容,那麼如何正確合適的將byte數組的中的內容輸出?");
sb.append("\r\n先看第一個問題:解決之道就是獲取輸入流的大小,創建此大小的byte數組。代碼如下:view plaincopy to clipboardprint?\r\n//使用InputStream從文件中讀取數據,在已知文件大小的情況下,建立合適的存儲字節數組 ");
sb.append("\r\n第二個問題:問題的解決之道就是獲得輸入流何時結束,它在byte中的尾索引位置。可以通過read()方法實現,read()返回讀取的字節內容,當內容爲空時返回-1。利用此特徵可以解決第二個問題。");
OutputStream out = new FileOutputStream(file);
out.write(sb.toString().getBytes());
// 刷新此輸出流並強制寫出所有緩衝的輸出字節
out.flush();
out.close();
System.out.println("字節流寫入文件完成!!!");
}
/**
* 使用InputStream讀取文件
*
* @throws IOException
*/
public static void getFileByByteIoInPutStream(File file) throws IOException {
InputStream in = new FileInputStream(file);
System.out.println("===============字節流開始讀取文件===================");
//創建合適文件大小的數組
byte b[]=new byte[(int)file.length()];
//讀取文件中的內容到b[]數組
in.read(b);
//關閉流
in.close();
System.out.println(new String(b));
in.close();
System.out.println("\n===============文件流讀取完成===================");
}
/**
* 使用Writer寫入文件
* @param file
* @throws IOException
*/
private static void setFileByCharIoWriter(File file) throws IOException {
Writer wr = new FileWriter(file);
StringBuffer sb = new StringBuffer("使用字符流Writer寫入文件信息!");
sb.append("\r\n java中的字符是Unicode編碼的, InputStream和OutputStream都是用來處理字節的,在處理字符時需要用getBytes()轉換成字節,這就需要編寫字節、字符之間的轉換代碼java中提供了單獨的類對IO設備進行字符輸入與輸出!");
sb.append("\r\n Reader和Writer是所有字符流類的的抽象基類,用於簡化對字符串的輸入輸出編程,即用於讀寫文本數據");
sb.append("\r\n 二進制文件和文本文件的區別。");
sb.append("\r\n 如果一個文件專用於存儲文本字符,而又沒有包含文本之外的字符,就可稱之爲文本文件。除此之外的文件就是二進制文件");
sb.append("\r\n Reader和Writer兩個類主要用於操作文本數據的內容,而InputStream和OutputStream主要操作二進制格式的內容 ");
sb.append("\r\n 使用FileWriter寫入字符數據比FileOutputStream要簡便很多,但是FileReader並不比FileInputStream讀取字符數據要簡便多少,都是要先讀取到一個字符數組或者字節數組中,然後把數組轉換成字符串。");
wr.write(sb.toString());
wr.flush();
wr.close();
System.out.println("字符流寫入文件完成!!!");
}
/**
* 使用Reader讀取文件
* @throws IOException
*/
public static void getFileByCharIoReader(File file) throws IOException{
Reader reader = new FileReader(file);
char[] buffer = new char[1024];
int length = reader.read(buffer);
System.out.println("===============字符流開始讀取文件===================");
String text = new String(buffer,0,length);
System.out.println(text);
reader.close();
System.out.println("\n===============文件流讀取完成===================");
}
/**
* 使用OutputStreamWriter寫入文件
* @param file
* @throws IOException
*/
private static void setFileByCharIoOutputStreamWriter(File file) throws IOException {
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file));
StringBuffer sb = new StringBuffer("使用OutputStreamWriter寫入文件信息!");
sb.append("\r\n 讀取文件流時,經常會遇到亂碼的現象,造成亂碼的原因當然不可能是一個,這裏主要介紹因爲文件編碼格式而導致的亂碼的問題。首先,明確一點,文本文件與二進制文件的概念與差異。");
sb.append("\r\n 文本文件是基於字符編碼的文件,常見的編碼有ASCII編碼,UNICODE編碼、ANSI編碼等等。二進制文件是基於值編碼的文件,你可以根據具體應用,指定某個值是什麼意思(這樣一個過程,可以看作是自定義編碼。)");
sb.append("\r\n 因此可以看出文本文件基本上是定長編碼的(也有非定長的編碼如UTF-8)。而二進制文件可看成是變長編碼的,因爲是值編碼嘛,多少個比特代表一個值,完全由你決定。");
sb.append("\r\n 對於二進制文件,是千萬不能使用字符串的,因爲字符串默認初始化時會使用系統默認編碼,然而,二進制文件因爲自定義編碼自然與固定格式的編碼會有所衝突,所以對於二進制的文件只能採用字節流讀取、操作、寫入。");
sb.append("\r\n 對於文本文件,因爲編碼固定,所以只要在讀取文件之前,採用文件自身的編碼格式解析文件,然後獲取字節,再然後,通過指定格式初始化字符串,那麼得到的文本是不會亂碼的。 ");
sb.append("\r\n 雖然,二進制文件也可以獲取到它的文本編碼格式,但是那是不準確的,所以不能同日而語。");
out.write(sb.toString());
out.flush();
out.close();
}
/**
* 使用InputStreamReader讀取文件
* @param file
* @throws IOException
*/
private static void getFileByCharIoInputStreamReader(File file) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream(file),"UTF-8");
int length = -1;
char[] buffer = new char[1024];
StringBuffer sb = new StringBuffer(0);
System.out.println("===============InputStreamReader開始讀取文件===================");
while((length=isr.read(buffer,0,1024))!=-1){
sb.append(buffer,0,length);
}
isr.close();
System.out.println(sb.toString());
System.out.println("===============InputStreamReader讀取完成===================");
}
/**
* 使用BufferedWriter寫入文件
* @param file
* @throws IOException
*/
private static void setFileByCharIoBufferedWriter(File file) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
StringBuffer sb = new StringBuffer("使用BufferedWriter寫入文件信息!");
sb.append("\r\n java.io.BufferedReader和java.io.BufferedWriter類各擁有8192字符的緩衝區。");
sb.append("\r\n 當BufferedReader在讀取文本文件時,會先儘量從文件中讀入字符數據並置入緩衝區,而之後若使用read()方法,會先從緩衝區中進行讀取。");
sb.append("\r\n 如果緩衝區數據不足,纔會再從文件中讀取,使用BufferedWriter時,寫入的數據並不會先輸出到目的地,而是先存儲至緩衝區中。 ");
sb.append("\r\n 如果緩衝區中的數據滿了,纔會一次對目的地進行寫出。");
sb.append("\r\n 從標準輸入流System.in中直接讀取使用者輸入時,使用者每輸入一個字符,System.in就讀取一個字符。爲了能一次讀取一行使用者的輸入,使用了BufferedReader來對使用者輸入的字符進行緩衝。 ");
sb.append("\r\n readLine()方法會在讀取到使用者的換行字符時,再一次將整行字符串傳入。");
bw.write(sb.toString());
//BufferedWriter換行的方法
bw.newLine();
bw.flush();
bw.close();
}
/**
* 使用BufferedReader讀取文件
* @param file
* @throws IOException
*/
private static void getFileByCharIoBufferedReader(File file) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(file));
System.out.println("===============BufferedReader開始讀取文件===================");
int length = -1;
String text = br.readLine();
while((text=br.readLine())!=null){
System.out.println(text);
}
System.out.println("===============BufferedReader讀取文件完成===================");
}
/**
*
*使用BufferedOutputStream寫入文件
* @throws IOException
*/
private static void setFileByBufferedOutputStream(File file) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
StringBuffer sb = new StringBuffer("使用BufferedWriter寫入文件信息!");
sb.append("\r\n 在創建BufferedInputStream 實例時(BufferedOutputStream同上),需要先給定一個InputStream類型的實例(如:FileInputStream)。");
sb.append("\r\n 解釋BufferedInputStream實現流程:其實質是實現了一個緩存裝置,在讀取源數據的時候其實還是用的InputStream來實現的。只是在讀取之前給他們加了一個緩存區而已。");
sb.append("\r\n 注意這個緩存區默認是位數組,大小2048,當讀文件的時候,BufferedInputStream會首先填滿緩存區,然後在使用InputStream的read()方法的時候,把緩存數組中的數據在讀到目的地");
sb.append("\r\n 對BufferedOutputStream,有一個默認512字節的緩存數組,當使用write()方法寫數據時,實質上是先將數據寫至緩存中,當緩存滿時,在用write()方法把數據寫入");
byte[] bytes = sb.toString().getBytes();
bos.write(bytes);
bos.flush();
bos.close();
}
/**
*
* 使用BufferedInputStream
* @throws IOException
*/
private static void getFileByBufferedInputStream(File file) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[bis.available()];
int length = 0;
StringBuffer sb = new StringBuffer(0);
System.out.println("===============BufferedInputStream開始讀取文件===================");
while((length=bis.read(buffer,0,buffer.length))!=-1){
System.out.println(new String(buffer));
}
System.out.println("===============BufferedInputStream讀取文件結束===================");
}
}