Java核心---I/O流
阿新 • • 發佈:2019-02-17
流概述:
流是一組有序的資料序列,根據操作的型別,可分為輸入流和輸出流兩種。I/O(Input/Output,輸入/輸出)流提供了一條通道程式,可以使用這條通道把源中的位元組序列送到目的地。
輸入和輸出模式如下圖:
輸入/輸出流 所有輸出流淚都是抽象類InputStream(位元組輸入流)或抽象類Reader(字元輸入流)的子類,所有輸出流都是抽象類OutputStream(位元組輸出流)或抽象類Writer(字元輸出流)的子類。 字元流和位元組流的區別: 因為資料編碼的不同,而有了對字元進行高效操作的流物件。本質其實就是基於位元組流讀取時,去查了指定的碼錶。 1.讀寫單位不同,位元組流以位元組為單位,字元流以字元為單位,根據碼錶對映字元,一次可能讀多個位元組。
2.處理物件不同,位元組流能處理所有的型別的資料,而字元流自能處理字元型別的資料
3.位元組流在操作的時候不會用到緩衝區,是檔案本身的直接操作,而字元流在操作時會用到緩衝區。
總的來說,一般都選擇用位元組流,除了純文字的情況用字元流更加高效。
示例(將一些文字儲存到檔案中):
示例(複製一個文字檔案):
操作文字檔案用字元流更高效。不過位元組流的運用更廣。例如音訊視屏檔案都只能用位元組流來操作。 示例(複製一個map3檔案,運用緩衝區更加高效):
示例(將鍵盤輸入的資料儲存到檔案中): 分析: 源:鍵盤 System.in 目的:檔案 FIle 是否純文字: 是 是否要使用緩衝區:是 另外:將讀取的位元組流資料轉換成字元流操作更高效,所以要用到轉換流
FileWriter其實就是轉換流指定了本機預設碼錶的體現,而且這個轉換流的子類物件,可以方便操作文字檔案。
簡單說:操作檔案的位元組流+本機預設的編碼表。
這是按照預設碼錶來操作檔案的便捷類
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"GBK");
如果操作文字檔案需要明確具體的碼錶,FileWriter就不行了,必須用轉換流。 示例:
示例(獲取D盤下java資料夾中.java結尾的檔案):
示例(將指定目錄下所有.java檔案拷貝到另一個目的中,並改為.txt格式):
輸入/輸出流 所有輸出流淚都是抽象類InputStream(位元組輸入流)或抽象類Reader(字元輸入流)的子類,所有輸出流都是抽象類OutputStream(位元組輸出流)或抽象類Writer(字元輸出流)的子類。 字元流和位元組流的區別: 因為資料編碼的不同,而有了對字元進行高效操作的流物件。本質其實就是基於位元組流讀取時,去查了指定的碼錶。 1.讀寫單位不同,位元組流以位元組為單位,字元流以字元為單位,根據碼錶對映字元,一次可能讀多個位元組。
如果建立檔案物件時,使用FileWriter fw = new FileWriter("FileDemo.txt",true) 那麼目的中的檔案就不會被覆蓋,而是會續寫。 示例(將一個檔案中的資料在控制檯顯示):/* 思路:因為是純文字的,所以使用字元流 因為是寫入到檔案中,所以要建立一個輸出流物件,並且要明確一個目的地,如果目的地沒有 檔案那麼就自動建立一個,如果存在就覆蓋 */ import java.io.*; class FileWriterDemo { public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("FileDemo.txt");//建立目的檔案 fw.write("abc");//用write方法寫入資料 fw.flush();//重新整理流資料,將資料寫入到目的地中 fw.close();//關閉流 } }
執行結果:import java.io.*; class FileReaderDemo { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("FileDemo.txt");//選擇原始檔 int i = 0; while((i=fr.read())!=-1) { System.out.println((char)i); //強轉之後輸出到控制檯 } fr.close();//關閉流 } }
示例(複製一個文字檔案):
import java.io.*;
class CopyDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("FileDemo.txt"); //讀取一個已有的本文檔案並用字元流關聯
FileWriter fw = new FileWriter("FileDemoCopy.txt");//建立一個目的檔案用來儲存資料
int i = 0;
while((i=fr.read())!=-1)//迴圈讀寫
{
fw.write(i);
}
fw.close();
fr.close();
}
}
可以使用緩衝區提高讀寫效率。 緩衝區:就像是喝水,一滴一滴的喝想要解渴太久了,用水杯將水裝滿之後再喝就快多了。
import java.io.*;
public class BufferedWriterDemo{
public static void main(String[] args) throws IOException{
FileWriter fw = new FileWriter("buf.txt" );
//建立一個字元寫入流的緩衝區物件,並且指定與要被緩衝的流物件相關聯
BufferedWriter bufw = new BufferedWriter(fw);
for(int x = 1; x <= 4; x++){
//將資料先寫入到緩衝區中
bufw.write( "abcdef" + x);
//換行方法:newLine();
bufw.newLine();
bufw.flush();
}
//將資料刷目的地中
bufw.flush();
//關閉緩衝區
fw.close();
}
}
操作文字檔案用字元流更高效。不過位元組流的運用更廣。例如音訊視屏檔案都只能用位元組流來操作。 示例(複製一個map3檔案,運用緩衝區更加高效):
import java.io.*;
class CopyMp3Demo
{
public static void main(String[] args) throws IOException
{
FileInputStream fis = new FileInputStream("1.map3"); //讀取已有檔案並用位元組流關聯
FileOutputStream fos = new FileOutputStream("2.mp3"); //建立一個目的儲存資料
byte[] buf = new byte[1024]; //建立緩衝區
int len = 0;
while((len=fis.read(buf))!=-1) //位元組不斷的寫入資料
{
fos.write(buf,0,len);
}
fis.close(); //關閉流
fos.close();
}
}
寫IO流的程式。首先應該明確幾點
1源和目的
源 InputStream 或者 Reader
目的 OutputStream 或者 Writer
2是否是純文字
純文字就用字元流 Reader 或者 Writer
不是純文字就用位元組流 InputStream 或者 OutputStream
另外還有: 判斷是否要加入緩衝區功能
關於轉換流:
InputStreamReader 位元組到字元,解碼 OutputStreamWriter 字元到位元組,編碼 為了方便字元流和位元組流之間的操作 當位元組流中的資料都是字元時,將位元組轉換成字元操作更高效 示例(將輸入的字母轉換成小寫的,並在控制檯顯示):import java.io.*;
class TranDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while((line=bufr.readLine())!=null)
{
if("886".equals(line))
break;
bufw.write(line.toLowerCase());
bufw.newLine();
bufw.flush();
}
}
}
執行結果:
示例(將鍵盤輸入的資料儲存到檔案中): 分析: 源:鍵盤 System.in 目的:檔案 FIle 是否純文字: 是 是否要使用緩衝區:是 另外:將讀取的位元組流資料轉換成字元流操作更高效,所以要用到轉換流
import java.io.*;
class TranDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("TranDemo.txt")));
String line = null;
while((line=bufr.readLine())!=null)
{
if("886".equals(line))
break;
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
}
FileWriter其實就是轉換流指定了本機預設碼錶的體現,而且這個轉換流的子類物件,可以方便操作文字檔案。
簡單說:操作檔案的位元組流+本機預設的編碼表。
這是按照預設碼錶來操作檔案的便捷類
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"GBK");
如果操作文字檔案需要明確具體的碼錶,FileWriter就不行了,必須用轉換流。 示例:
import java.io.*;
public class TransStreamDemo {
public static void main(String[] args) throws IOException {
writeText();
}
public static void writeText() throws IOException {
//下面這句程式碼等同於FileWriter fw = new FileWriter("b.txt");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt" ),"UTF-8" );
osw.write( "您好");
osw.close();
}
}
示例(將一個指定的txt檔案中的內容在控制檯顯示):
import java.io.Exception
class TransStreamDemo {
public static void main(String[] args) throws IOException {
writeText();//呼叫方法
}
public static void writeText() throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("demo.txt" ),"UTF-8" );//確定一個源並用流聯立
char[] buf = new char[10];//建立一個緩衝區
int len = isr.read(buf); //讀取文件中的內容
String str = new String(buf,0,len); //將資料封裝到字串
System.out.println(str);
isr.close(); //流關閉
}
}
示例(獲取目錄下的檔案和檔案的名稱):
import java.io.*;
class FileListDemo{
public static void main(String[] args) throws IOException {
listDemo();
}
public static void listDemo() throws IOException {
File file = new File("c:\\" );
//獲取目錄下的檔案以及資料夾的名稱,包含隱藏檔案
//呼叫list方法的File物件中封裝的必須是目錄,否則會產生NullPointerException
//如果訪問的是系統級目錄也會發生空指標異常
//如果目錄存在但是沒有內容,會返回一個數組,但是長度為0
String[] names = file.list();
for(String name : names){
System.out.println(name);
}
}
}
示例(獲取D盤下java資料夾中.java結尾的檔案):
import java.io.*;
class FileListDemo{
public static void main(String[] args){
listDemo(); //呼叫listDemo()方法
}
public static void listDemo(){
File dir = new File("d:\\java" ); //讀取指定目錄
String[] names = dir.list( new FilterByJava()); //獲取文件名稱
for(String name : names){ //高階的for迴圈遞迴
System.out.println(name);
}
}
}
class FilterByJava implements FilenameFilter{
public boolean accept(File dir,String name){//判斷檔名稱是否符合
return name.endsWith(".java" );
}
}
示例(將指定目錄下所有.java檔案拷貝到另一個目的中,並改為.txt格式):
import java.io.*;
import java.util.*;
class JavaDocDemo
/*
要求:編寫程式,將指定目錄下所有.java檔案拷貝到另一個目的中,並將副檔名改為.txt
思路 1.用遞迴的方法遍歷指定目錄下的檔案
2.將以.java結尾的檔名存入集合
3.將以.java結尾的檔案複製到指定目的並改名
*/
{
public static void main(String[] args) throws Exception
{
ArrayList<String> list = new ArrayList<String>();//定義集合用來儲存java檔案的名字
File src = new File("C:\\Users\\zlf\\Desktop\\java");//原始檔的路徑
File des = new File("C:\\Users");//目的檔案路徑
if(!des.exists())//判斷目的檔案是否存在,不存在建立
des.mkdirs();
fileTolist(src,list);//將原始檔中的Java檔案的名字存入到集合中
for(String fileName:list)
writeTofile(src,des,fileName);//將原始檔中的Java檔案存入到目的資料夾中
}
//將原始檔中的Java檔案的名字存入到集合中
public static void fileTolist(File file,List<String>list)
{
File[] files = file.listFiles();//獲取原始檔夾中的檔案
for(File f:files)//遍歷檔案並將Java檔案的名字存到集合中
{
list.add(f.getName());
}
}
//將原始檔中的Java檔案存入到目的資料夾中
public static void writeTofile(File src,File des,String fileName)throws Exception
{
BufferedReader bufr = new BufferedReader(new FileReader(new File(src,fileName)));
BufferedWriter bufw = new BufferedWriter(new FileWriter(new File(des,fileName.replace(".java",".txt"))));
String line = null;
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
}
bufw.close();
bufr.close();
}
}