//單元測試中的相對路徑,相對於當前module
//main方法中的相對路徑,相對於當前工程
File file = new File("hello.txt");
//絕對路徑
File file1 = new File("d:\\JAVA_WORK\\info");
File file2 = new File("d:" + File.separator + "example" +
File.separator + "info.txt");
File file3 = new File("d:/JAVA_WORK");
File file1 = new File("D:\\JAVA_WORK","info");
File file2 = new File(file1,"hello.txt");
其中,重新命名方法public boolean renameTo(File dest)
,若file1.renameTo(file2)
,要想保證返回 true,需要 file1 在硬碟中是存在的,且 file2 不能在硬碟中存在。
① 將當前Module下的 hello.txt
檔案內容讀入程式中,並輸出到控制檯
read()
的理解:返回讀入的一個字元。如果達到檔案末尾,返回-1try-catch-finally
處理FileNotFoundException
。 @Test
public void testFileReader() throws Exception{
FileReader fr = null;
try {
//1.範例化File類的物件,指明要操作的檔案
File file = new File("hello.txt");
//2.提供具體的流
fr = new FileReader(file);
//3.數據的讀入
int data;
while((data = fr.read()) != -1){
System.out.print((char)data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.流的關閉操作
try {
if(fr != null) fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
②
//對read()操作升級:使用read的過載方法
@Test
public void testFileReader1() {
FileReader fr = null;
try {
//1.File類的範例化
File file = new File("hello.txt");
//2.FileReader流的範例化
fr = new FileReader(file);
//3.讀入的操作
//read(char[] cbuf)
//返回每次讀入cbuf陣列中的字元的個數。如果達到檔案末尾,返回-1
char[] cbuf = new char[5];
int len;
while((len = fr.read(cbuf)) != -1){
//方式一:
//錯誤的寫法
// for(int i = 0;i < cbuf.length;i++){
// System.out.print(cbuf[i]);
// }
//正確的寫法
// for(int i = 0;i < len;i++){
// System.out.print(cbuf[i]);
// }
//方式二:
//錯誤的寫法,對應着方式一的錯誤的寫法
// String str = new String(cbuf);
// System.out.print(str);
//正確的寫法
String str = new String(cbuf,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fr != null){
//4.資源的關閉
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
③ 從記憶體中寫出數據到硬碟的檔案裡
FileWriter(file,false)
/ FileWriter(file)
,則對原有檔案的覆蓋FileWriter(file,true)
,則不會對原有檔案覆蓋,而是在原有檔案基礎上追加內容 @Test
public void testFileWriter() {
FileWriter fw = null;
try {
//1.提供File類的物件,指明寫出到的檔案
File file = new File("hello1.txt");
//2.提供FileWriter的物件,用於數據的寫出
fw = new FileWriter(file,false);
//3.寫出的操作
fw.write("I have a dream!\n");
fw.write("you need to have a dream!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.流資源的關閉
if(fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
實現對圖片的複製操作
*/
@Test
public void testFileInputstream(){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
File srcFile = new File("test.png");
File destFile = new File("test1.png");
fileInputStream = new FileInputStream(srcFile);
fileOutputStream = new FileOutputStream(destFile);
byte[] b = new byte[10];
int len;
while ((len=fileInputStream.read(b))!=-1){
fileOutputStream.write(b,0,len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(fileInputStream!=null) fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fileOutputStream!=null) fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
作用:提供流的讀取、寫入的速度;原理:內部提供了一個緩衝區
/*
實現非文字檔案的複製
*/
@Test
public void BufferedStreamTest() throws FileNotFoundException {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1.造檔案
File srcFile = new File("愛情與友情.jpg");
File destFile = new File("愛情與友情3.jpg");
//2.造流
//2.1 造節點流
FileInputStream fis = new FileInputStream((srcFile));
FileOutputStream fos = new FileOutputStream(destFile);
//2.2 造緩衝流
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//3.複製的細節:讀取、寫入
byte[] buffer = new byte[1024];
int len;
while((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
//重新整理緩衝區
//bos.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.資源關閉
//要求:先關閉外層的流,再關閉內層的流
//說明:關閉外層流的同時,內層流也會自動的進行關閉。
//所以關於內層流的關閉,可省略
if(bos != null){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bis != null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testBufferedReaderBufferedWriter(){
BufferedReader br = null;
BufferedWriter bw = null;
try {
//建立檔案和相應的流
br = new BufferedReader(new FileReader(new File("dbcp.txt")));
bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt")));
//讀寫操作
//方式一:使用char[]陣列
// char[] cbuf = new char[1024];
// int len;
// while((len = br.read(cbuf)) != -1){
// bw.write(cbuf,0,len);
// // bw.flush();
// }
//方式二:使用String
String data;
while((data = br.readLine()) != null){
//換行方法一:
//寫出的data中不包含換行符
//bw.write(data + "\n");
//換行方法二:
bw.write(data);
//提供換行的操作
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//關閉資源
if(bw != null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
抽象基礎類別 | 節點流(或檔案流) | 緩衝流(處理流的一種) |
---|---|---|
InputStream |
FileInputStream ——read(byte[] buffer) |
BufferedInputStream ——read(byte[] buffer) |
OutputStream |
FileOutputStream ——write(byte[] buffer,0,len) |
BufferedOutputStream write(byte[] buffer,0,len) / flush() |
Reader |
FileReader ——read(char[] cbuf) |
BufferedReader ——read(char[] cbuf) / readLine() |
Writer |
FileWriter ——write(char[] cbuf,0,len) |
BufferedWriter ——write(char[] cbuf,0,len) / flush() |
InputStreamReader
:將一個位元組的輸入流 轉換爲字元的輸入流OutputStreamWriter
:將一個字元的輸出流 轉換爲位元組的輸出流 /*
InputStreamReader的使用,實現位元組的輸入流到字元的輸入流的轉換
*/
@Test
public void InputStreamReaderTest(){
InputStreamReader inputStreamReader = null;
OutputStreamWriter outputStreamWriter = null;
try {
//參數2指明瞭字元集
//具體使用哪個字元集,取決於檔案hello.txt儲存時使用的字元集
inputStreamReader = new InputStreamReader(new FileInputStream("hello.txt"), "UTF-8");
outputStreamWriter = new OutputStreamWriter(new FileOutputStream("hello_gbk.txt"),"GBK");
char[] cbuf = new char[1024];
int len;
while ((len = inputStreamReader.read(cbuf))!=-1){
outputStreamWriter.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(inputStreamReader!=null) inputStreamReader.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(outputStreamWriter!=null) outputStreamWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.in
和System.out
分別代表了系統標準的輸入和輸出裝置System.in
的型別是InputStream
System.out
的型別是PrintStream
,其是OutputStream
的子類setIn
, setOut
方法對預設裝置進行改變。
public static void setIn(InputStream in)
public static void setOut(PrintStream out)
FilterOutputStream 的子類
例 題
從鍵盤輸入字串,要求將讀取到的整行字串轉成大寫輸出。然後繼續
進行輸入操作,直至當輸入「e」或者「exit」時,退出程式:
public static void main(String[] args) {
BufferedReader br = null;
try {
InputStreamReader isr = new InputStreamReader(System.in);
br = new BufferedReader(isr);
while (true) {
System.out.println("請輸入字串:");
String data = br.readLine();
if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) {
System.out.println("程式結束");
break;
}
String upperCase = data.toUpperCase();
System.out.println(upperCase);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
實現將 基本數據型別 的數據格式轉化爲 字串 輸出
@Test
public void test2() {
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream(new File("D:\\IO\\text.txt"));
// 建立列印輸出流,設定爲自動重新整理模式(寫入換行符或位元組 '\n' 時都會重新整理輸出緩衝區)
ps = new PrintStream(fos, true);
if (ps != null) {// 把標準輸出流(控制檯輸出)改成檔案
System.setOut(ps);
}
for (int i = 0; i <= 255; i++) { // 輸出ASCII字元
System.out.print((char) i);
if (i % 50 == 0) { // 每50個數據一行
System.out.println(); // 換行
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (ps != null) {
ps.close();
}
}
}
//練習:將記憶體中的字串、基本數據型別的變數寫出到檔案中。
@Test
public void test3() throws IOException {
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeUTF("Tom");
dos.flush();//重新整理操作,將記憶體中的數據寫入檔案
dos.writeInt(23);
dos.flush();
dos.writeBoolean(true);
dos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (dos!= null) {
dos.close();
}
}
}
/*
將檔案中儲存的基本數據型別變數和字串讀取到記憶體中,儲存在變數中。
注意點:讀取不同類型的數據的順序要與當初寫入檔案時,儲存的數據的順序一致!
*/
@Test
public void test4() throws IOException {
DataInputStream dis = null;
try {
dis = new DataInputStream(new FileInputStream("data.txt"));
String name = dis.readUTF();
int age = dis.readInt();
boolean isMale = dis.readBoolean();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (dis!= null) {
dis.close();
}
}
}
① 物件序列化機制 機製允許把記憶體中的Java物件轉換成平臺無關的二進制流,從
而允許把這種二進制流持久地儲存在磁碟上,或通過網路將這種二進制流傳
輸到另一個網路節點。 (當其它程式獲取了這種二進制流,就可以恢復成原
來的Java物件)
② 序列化優點:可將任何實現了Serializable介面的物件轉化爲位元組數據,
使其在儲存和傳輸時可被還原
③ 序列化是 RMI(Remote Method Invoke – 遠端方法呼叫)過程的參數和返
回值都必須實現的機制 機製,而 RMI 是 JavaEE 的基礎。因此序列化機制 機製是
JavaEE 平臺的基礎
④ 如果需要讓某個物件支援序列化機制 機製,則必須讓 物件所屬的類及其屬性 是可
序列化的(預設基本數據型別已是可序列化),爲了讓某個類是可序列化的,該類须實現如下兩個介面之一,否則會拋NotSerializableException
異常:
Serializable
Externalizable
⑤ 凡是實現Serializable
介面的類都有一個表示序列化版本識別符號的靜態變數:
private static final long serialVersionUID;
serialVersionUID
用來表明類的不同版本間的相容性。 簡言之,其目的是以序列化物件進行版本控制,有關各版本反序列化時是否相容。serialVersionUID
可能發生變化,故建議顯式宣告。⑥ 簡單來說, Java的序列化機制 機製是通過在執行時判斷類的serialVersionUID
來驗證版本一致性的。在進行反序列化時, JVM會把傳來的位元組流中的
serialVersionUID
與本地相應實體類的serialVersionUID
進行比較,如果相同就認爲是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異
常。 (InvalidCastException
)
ObjectInputStream
和OjbectOutputSteam
序列化: 用ObjectOutputStream
類儲存基本型別數據或物件的機制 機製(寫出)
反序列化: 用ObjectInputStream
類讀取基本型別數據或物件的機制 機製(寫入)
注:ObjectOutputStream
和ObjectInputStream
不能序列化static
和transient
修飾的成員變數。
/*
序列化過程:將記憶體中的java物件儲存到磁碟中或通過網路傳輸出去
使用ObjectOutputStream實現
*/
@Test
public void testObjectOutputStream(){
ObjectOutputStream oos = null;
try {
//1.
oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
//2.
oos.writeObject(new String("我愛北京天安門"));
oos.flush();//重新整理操作
// Person類已實現Serializable介面
//且宣告瞭serialVersionUID
oos.writeObject(new Person("王銘",23));
oos.flush();
oos.writeObject(new Person("張學良",23,1001,new Account(5000)));
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(oos != null){
//3.
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
反序列化:將磁碟檔案中的物件還原爲記憶體中的一個java物件
使用ObjectInputStream來實現
*/
@Test
public void testObjectInputStream(){
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("object.dat"));
Object obj = ois.readObject();
String str = (String) obj;
Person p = (Person) ois.readObject();
Person p1 = (Person) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(ois != null){
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
RandomAccessFile
宣告在 java.io 包下,但直接繼承於java.lang.Object類。 並且它實現了DataInput
、 DataOutput
這兩個介面,即這個類既作爲輸出流,也可作爲輸入流。