Java中I/O使用入門詳解(1)
本文介紹了 FileInputStream,FileOutputStream等常用輸入輸出流的使用方式,(來自於以前的學習筆記,現整理出來和大家分享).
通俗易懂,老少皆宜O(∩_∩)O~
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* IO的分類:
* 流向:
* 輸入流:讀取數據
* 輸出流:寫入數據
* 數據類型:
* 字節流
* 字節輸入流 讀取數據 InoutStream
* 字節輸出流 寫入數據 OutputStream
* 字符流
* 字符輸入流 讀取數據 Reader
* 字符輸出流 寫入數據 Writer
*
* 注意:一般在探討IO流,不說的話是按數據類型來說的
*
* 需求:往一個文本文件中寫入一句話:"hello,IO".
*
* 分析:
* A:這個最好用字符流實現,這裏用字節流
* B:由於我是想往文件中寫一句話,所以我們用字節輸出流
* 通過上面的分析後我們知道要使用OutputStream
* 但是通過查看API,我們發現該流對象是一個抽象類,不能實例化
* 所以我們要找一個具體的子類,這個時候很簡單,實際上,我們是要往文件中寫東西
* 文件單詞:File
* 然後用的是字節流,連起來就是FileOutputStream
* 注意:每種基類的子類都是以父類名作爲後綴名
*
* 查看FileOutputStream構造方法
* FileOutputStream(File file)
* FileOutputStream(String name)
*/
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//創建字節流輸出對象
//FileOutputStream(File file)
// File file= new File("fos.txt");
// FileOutputStream fos=new FileOutputStream(file);
FileOutputStream fos=new FileOutputStream("fos.txt");
/*
* 創建字節輸出流對象做了幾件事情
* 1:調用系統功能去創建文件
* 2:創建fos對象
* 3:把fos對象指向這個文件
*/
//寫數據
fos.write("hello,IO".getBytes());
//釋放資源
fos.close();
/*
* 爲什麼一定要close呢?
* A:關閉流對象,使流對象變成垃圾,以免後面別人接着寫
* B:通知系統去釋放相關的資源
*/
}
}
1.FileOutputStream
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 字節輸出流操作步驟
* A:創建字節輸出流對象
* B:調用write()方法
* C:釋放資源
*
* public void write(int b);寫一個字節
* public void write(byte[] b);寫一個字節數組
* public void write(byte[] b,int Off,int len);寫一個字節數組的一部分
*/
public class FileOutputStreaDemo2 {
public static void main(String[] args) throws IOException {
//創建字節流輸出流對象
//OutputStream os=new FileOutputStream("fos2.txt);//這是多態
FileOutputStream fos=new FileOutputStream("fox2.txt");
//調用write()方法
fos.write(97);//97----底層是二進制數組----通過記事本打開-----找97對應的字符值----a
//public void write (byte[] b):寫一個字節流數組
byte[] bys={97,98,99,100,101};
fos.write(bys);
//public void write(byte[] b,int Off,int len);寫一個字節數組的一部分
fos.write(bys,1,3);
fos.close();
}
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 如何實現數據的換行?
* 爲什麼沒有換行呢?因爲只寫了字節數據,並沒有寫入換行符號
* 如何實現換行?寫入換行符號即可
* 剛纔用"\n"我們看到有些文本文件打開是可以的,但用Windows自帶卻不行
* 原因:不同的系統對於換行符號識別是不一樣的
* windows:\r\n
* linux:\n
* Mac:\r
*
* 而一些高級寫字本軟件可識別任意的換行符的
* 如何實現數據的追加寫入?
* 用構造方法待第二個參數爲true的情況即可
*/
public class FileOutputStreamDemo3 {
public static void main(String[] args) throws IOException {
//創建字符輸出流
//FileOutputStream fos=new FileOutputStream("fos3.txt");
FileOutputStream fos=new FileOutputStream("fos3.txt",true);
//寫數據
for(int i=0;i<10;i++){
fos.write(("hello"+i).getBytes());
fos.write("\n".getBytes());
}
fos.close();
}
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 加入異常處理的字節輸出流操作
*
*/
public class FileOutputStreamDemo4 {
public static void main(String[] args) {
FileOutputStream fos=null;
try {
fos = new FileOutputStream("fos4.txt");
fos.write("java".getBytes());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}finally{
//如果fos不是null,才需要close()
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.FileInputStream
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
*字節輸入流操作步驟
*A:創建字節輸入流對象
*B:調用read()方法讀取數據,並把它顯示到控制檯
*C:釋放數據
*
* 讀取數據的方式
* A:int read();一次讀取一個字節
* B:int read(byte[] b);一次讀取一個字節數組
*
*/
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
//FileInputStream(String name);
FileInputStream fis=new FileInputStream("fis.txt");
//用int read();
//第一次讀取
// int by=fis.read();
// System.out.println(by);
// System.out.println((char)by);
//
// //第二次讀取
// by=fis.read();
// System.out.println(by);
// System.out.println((char)by);
// //第三次讀取
// by=fis.read();
// System.out.println(by);
// System.out.println((char)by);
//我們發現代碼的重複度很高,應該用循環改進
//而用循環,最麻煩的是如何控制循環的條件
//多測兩次後發現,讀取的結果爲-1,說明已經讀取到文件的末尾了
//循環改進
// int by=fis.read();
// while(by!=-1){
// System.out.print((char)by);
// by=fis.read();
// }
//最終版代碼
int by=0;
//讀取,賦值,判斷
while((by=fis.read())!=-1){
System.out.println((char) by);
}
//釋放資源
fis.close();
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 一次讀取一個字節數組
* 返回值是讀取字節的
*/
public class FileInputStreamDemo2 {
public static void main(String[] args) throws IOException {
//創建字節輸入流對象
FileInputStream fis=new FileInputStream("fis2.txt");
//讀取數據
//定義一個字節數組
//第一次讀取
// byte[] bys=new byte[5];
// int len=fis.read(bys);
// System.out.println(new String(bys,0,len));
//
// byte[] bys =new byte[20];
// int len=0;
// while((len=fis.read(bys))!=-1){
// System.out.println(new String (bys,0,len));
// //System.out.println(new String (bys)此做法有問題,千萬要注意
// }
//最終版
//數組的長度一般是1024或者1024的倍數
byte[] bys=new byte[1024];
int len=0;
while((len=fis.read(bys))!=-1){
System.out.println(new String (bys,0,len));
}
//釋放資源
fis.close();
}
}
3.一些文件複製應用的例子
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
*
* 複製文本文件
*
* 數據源:從哪裏來
* a.txt 讀取數據 FileinputStream
* b.txt 寫數據 FileOutputStream
* 目的地:到哪裏去
* b.txt
*
* 這一次複製中文沒有出現任何問題,爲什麼?
* 上一次我們出現問題是由於我們把每次獲取到一個字節數據,就把該字節數據轉換爲字符數據
* 而這一次,卻是通過IO流讀取數據,你讀取一個字節,我就寫入一個字節,沒有存在任何轉換
* 他會自己轉換
*
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//封裝數據源
FileInputStream fis=new FileInputStream("a.txt");
//封裝目的地
FileOutputStream fos=new FileOutputStream("b.txt");
int by=0;
while((by=fis.read())!=-1){
fos.write(by);
}
//釋放資源(先關誰都行)
fos.close();
fis.close();
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
*
* 複製文本文件
*
* 數據源:從哪裏來
* c:\\a.txt 讀取數據 FileinputStream
* 目的地:到哪裏去
* d:\\b.txt 寫數據 FileOutputStream
*
*/
public class CopyFileDemo2 {
public static void main(String[] args) throws IOException {
//封裝數據源
FileInputStream fis=new FileInputStream("c:\\a.txt");
//封裝目的地
FileOutputStream fos=new FileOutputStream("d:\\b.txt");
//複製數據
int by=0;
while ((by=fis.read())!=-1){
fos.write(by);
}
fis.close();
fos.close();
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 需求:把e:\\a.jpg內容複製到當前項目下的aa.jpg中
*
*/
public class CopyImageDemo {
public static void main(String[] args) throws IOException {
//封裝數據源
FileInputStream fis=new FileInputStream("e:\\a.jpg");
//封裝目的地
FileOutputStream fos =new FileOutputStream("aa.jpg");
//複製數據
int by=0;
while((by=fis.read())!=-1){
fos.write(by);
}
//釋放資源
fos.close();
fis.close();
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 把D:\\a.txt內容複製到E:\\b.txt中
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//封裝數據源
FileInputStream fis=new FileInputStream("d:\\a.txt");
//封裝目的的
FileOutputStream fos=new FileOutputStream("e:\\b.txt");
//複製數據
byte[] bys=new byte[1024];
int len=0;
while((len= fis.read(bys))!=-1){
fos.write(bys,0,len);
}
//釋放資源
fis.close();
fos.close();
}
}
4.BufferedOurtputStream與BufferedInputStream
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 我們通過定義數據的方式的確比以前一個一個讀取有效率得多,看來有一個緩衝區是很好的
* 其實java開始設計時,就考慮了這個問題,就專門提供了緩衝區的字節類
* 這種類被稱爲:緩衝區類(高效類)
* 寫數據:BufferedOutputStream
* 讀數據:BufferedInputStream
*
* 構造方法可以指定緩衝區大小,但我們一般用不上,因爲默認的緩衝區大小就夠了
*
* 爲什麼不傳遞一個具體的文件或文件路徑,而是傳送一個OutputStream對象呢?
* 原因很簡單,字節緩衝區僅僅提供緩衝區,爲高效而設計的,但是呢,真正的讀寫操作還得靠基本的流對象
*
*/
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws IOException {
//BufferedOutputStream(OutputStream out);
// FileOutputStream fos=new FileOutputStream("bos.txt");
// BufferedOutputStream bos=new BufferedOutputStream(fos);
BufferedOutputStream bos=new BufferedOutputStream(
new FileOutputStream("bos.txt"));
//寫數據
bos.write("hello".getBytes());
bos.close();
}
}
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class BufferedInputStreamDemo {
public static void main(String[] args) throws IOException {
//BufferedInputStream(InputDtream in)
BufferedInputStream bis=new BufferedInputStream(
new FileInputStream("bos.txt"));
//讀數據
// int by =0;
// while((by=bis.read())!=-1){
// System.out.println((char) by);
// }
byte[] bys=new byte[1024];
int len =0;
while ((len=bis.read(bys))!=-1){
System.out.println(new String(bys,0,len));
}
bis.close();
}
}
最後,我們來比較一下四種讀寫2方式的速度差異:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 把e:\\下的a.mp4複製到當前目錄下的aa.mp4
*
* 字節流四種方式複製文件
* 基本字節流一次讀寫一個字節
* 基本字節流一次讀寫一個字節數組
* 高效字節流一次讀寫一個字節
* 高效字節流一次讀寫一個字節數組
*
*/
public class CopyMp4Demo {
public static void main(String[] args) throws IOException {
long start=System.currentTimeMillis();
//method1("e:\\a.mp4","copy1.mp4");共耗時: 81700ms
//method2("e:\\a.mp4","copy2.mp4");共耗時: 326ms
//method3("e:\\a.mp4","copy3.mp4");共耗時: 1899ms
//method4("e:\\a.mp4","copy4.mp4");共耗時: 137ms
long end=System.currentTimeMillis();
System.out.println("共耗時: "+(end-start)+"ms");
}
//基本字節流一次讀寫一個字節
private static void method1(String srcString, String destString) throws IOException {
FileInputStream fis=new FileInputStream(srcString);
FileOutputStream fos=new FileOutputStream(destString);
int by=0;
while((by=fis.read())!=-1){
fos.write(by);
}
fos.close();
fis.close();
}
//基本字節流一次讀寫一個字節數組
private static void method2(String srcString, String destString) throws IOException {
FileInputStream fis=new FileInputStream(srcString);
FileOutputStream fos=new FileOutputStream(destString);
byte[] bys=new byte[1024];
int len=0;
while((len=fis.read(bys))!=-1){
fos.write(bys,0,len);
}
fos.close();
fis.close();
}
//高效字節流一次讀寫一個字節
private static void method3(String srcString, String destString) throws IOException {
BufferedInputStream bis=new BufferedInputStream(
new FileInputStream(srcString));
BufferedOutputStream bos=new BufferedOutputStream(
new FileOutputStream(destString));
int by=0;
while((by=bis.read())!=-1){
bos.write(by);
}
bos.close();
bis.close();
}
//高效字節流一次讀寫一個字節數組
private static void method4(String srcString, String destString) throws IOException {
BufferedInputStream bis=new BufferedInputStream(
new FileInputStream(srcString));
BufferedOutputStream bos=new BufferedOutputStream(
new FileOutputStream(destString));
byte[] bys=new byte[1024];
int len=0;
while((len=bis.read(bys))!=-1){
bos.write(bys,0,len);
}
bos.close();
bis.close();
}
}
5.關於I/O使用的小結提綱
(1)用於在設備間數據傳輸的操作
(2)分類:
A:流向
輸入流 --> 讀取數據
輸出流 --> 寫入數據
B:數據類型
字節流
字節輸入流
字節輸出流
字符流
字符輸入流
字符輸出流
a:如果我們沒明確說明按照什麼分,默認按照數據類型分
b:除非文件用Windows自帶記事本打開我們能夠讀懂,才採用字符流,否則採用字節流
(3)FilOutoutStream寫出數據
A:操作步驟
a:創建自己人輸出流操作對象
b:調用Write()方法
c:釋放資源
B:代碼體現:
FileOutputSream fos=new FileOutputStream("fos.txt");
fos.write("hello".getBytes());
fos.close();
C:要注意問題?
a:創建字節輸出流對象做了幾件事情?
b:爲啥要close()?
c:如何實現數據的換行?
d:如何實現數據的追加寫入?
(4)FIleInputStream讀取數據
A:操作步驟
a:創建字節輸入流對象
b:調用read()方法
c:釋放資源
B:代碼實現:
FileInputStream fis =new FileInputStream("fos.txt");
//方式一
int by=0;
while((by=fis.read()!=-1)){
System.out.print((char)by);
}
fis.close;
//方式二
byte[] bys=new byte[1024];
int len=0;
while((len=fis.read(bys))!=-1){
System.out.print(new String(bys,0,len));
}
fis.close;
(5)案例:
A:複製文本文件
B:複製圖片
C:複製視頻
(6)字節緩衝區流
A:BufferedOutputStream
B:BufferedIntputStream
(7)例子:幾種實現
A:複製文本文件
B:複製圖片
C:複製視頻