需求,java程序與外屆交流數據。
實際上是OS與JVM內存交互數據。
那么針對程序,有輸出流,也有輸入流。
java.io包下,File類,它表示文件系統上的一個文件或者目錄。
方法,總體來說是對磁盤文件的磁盤操作,不能看內容,主要是為了獲得文件和文件屬性。
File dir = new File("d:\");
File f = new File(dir,"11.txt");// -->創建文件對象,只是一個對象,沒有反映到磁盤上。
f.createNewFile();//-->創建文件
f.mkdir();//創建目錄
delete();調用完馬上就刪除了
deleteOnExit();程序退出時,可以作為臨時文件。
new File("d:\\....\\11.txt");
File.separator
file.list() 所有文件名 String[]
file.listFiles() File[]數組
注意如何實現 dir *.java的效果呢,需要一個過濾器
public
File[]
listFiles(
FilenameFilter filter)
public
File[]
listFiles(
FileFilter filter)
FilenameFilter需要實現
boolean
accept(
File dir,
String name)
返回true,表示要包含在結果中的
new FilenameFilter(){
public boolean acccept(File dir,String name)
{
if(name.indexOf(".java") == -1) return false;
else return true;
}
}
===================================
File類不能讀取文件內容。
所以真正讀取文件內容,需要在虛擬機中的對象和DS數據源之間建立一個數據輸入輸出流。
按照以JVM為方向,數據流向分為輸入流,輸出流。
按照傳輸數據單元:又有字節流和字符流。8位為一字節。
按功能又叫做節點流,比如專門以文件為數據源與程序建立的數據流,通道,就是FileInputStream。
給節點流,添加輔助功能的流,也就是構造方法的參數為其他流的流,一定是過濾流。(裝飾模式應用)
所有字節輸入流的父類,都是InputStream。比如有子類,FileInputStream,還有javax.sound.sampled.AudioInputStream
它有一個
read()方法,一次讀入一個字節,由于是跨出JVM的操作,因此極其消耗資源。
所以一般用
read(byte[] b),給一個字節數組,方法返回,字節數據會讀滿,返回值為實際,讀入的字節數,用于處理,最后一次時,可能并沒有裝滿,要保證文件一個字節都不差,必須爭取取出相應個數的字節內容。返回-1,表示沒有可以讀的了。
read(byte[] b, int off, int len),從數組off起始位置讀入,len試圖讀入的個數。可控的。
read(b) <==> read(b,0,b.length);
OutputStream
write(int b) -> 寫一個字節
由于輸入、輸出流是跨出虛擬機邊界的資源,虛擬機很難回收,這時對于資源的占用,是一種極大的浪費。
就好像,你能讓你媽幫你收拾屋子,洗衣服,但是你打開水龍口,打完水不管水龍頭,試一試。
或者你在麥當勞吃完飯,盤子放那,有服務生來幫你收走,但你試試把盤子拿到大街上,放在外面,服務生是不能回收的。
雖然Java幫你回收不使用的對象,但對于關閉輸入輸出流的工作,程序員是要自己負責!因為跨出虛擬機邊界,虛擬機不管。
============================
節點流,FileInputStream,當然也是字節流。有Stream,只是記憶方便。
構造器參數,文件名,文件對象File
FileInputStream fi = new FileInputStream("1.txt");
byte b[] = new byte[100];
int length;
while((length = (fi.read(b))!=-1){
String s = new String(b);
System.out.println(s);
}
fi.close();
FileOutputSteam(File file,boolean append)//第二個選項,為true,表示要追加文件內容。
構造器一個FileOutputStream對象時,磁盤會同時生成一個文件(如果已存在同名文件,會先刪除)FileOutputSteam fo = new FileOutputStream("1.txt",true);
String s = new String("hi my girl");
byte[] b = s.getBytes();
while(fo.write(b)!= -1){};
fo.close();
為了能夠輕松的將簡單數據類型的數據,直接輸出到流中,需要對已存在字節輸出流添加功能。
所以這種流叫做過濾流,例如java.io.DataOutputStream。它的構造函數參數為OutputStream對象。
FileOutputStream file = new FileOutputStream("DST1.txt");
DataOutputStream out = new DataOutputStream(file);
out.writeUTF(str);
注意使用這個過濾流,輸出和輸入的順序要一致。
輸出:
_byte_ _short_ _ _ _int
輸入:
不能夠
_ _short_ byte_ _ _ _
這樣讀,會將byte和short的前一個字節一起讀為short類型,顯然是錯誤的。
=================================
給輸入輸出流添加緩沖功能的過濾流,叫做BufferedOutputStream out = new BufferedOutputStream(other outputstream);
虛擬機中拿出一個塊區域當作緩沖區,把數據先寫入緩沖區,如果緩沖區滿了,再一次性將內容寫到磁盤。
大大的減少了虛擬機快越邊界的操作,效率大幅度提高。是犧牲空間換時間的典型做法。
任何帶緩沖的流,都會有一個flush()的方法,可以不管緩沖區滿不滿,都情空緩沖區。
還有直接調用.close,也會自動調用.flush()方法。
對于過濾流,只關閉最外層的流,即可。
===============================
管道,節點流
PipedOutputStream / PipedInputStream
pos.connect(pis);
用于給兩個線程交換數據。
import java.io.*;
public class PipedStreamTest


{
public static void main(String[] args)

{
PipedOutputStream pos=new PipedOutputStream();
PipedInputStream pis=new PipedInputStream();
try

{
pos.connect(pis);
new Producer(pos).start();
new Consumer(pis).start();
}
catch(Exception e)

{
e.printStackTrace();
}
}
}

class Producer extends Thread


{
private PipedOutputStream pos;
public Producer(PipedOutputStream pos)

{
this.pos=pos;
}
public void run()

{
try

{
pos.write("Hello,welcome you!".getBytes());
pos.close();
}
catch(Exception e)

{
e.printStackTrace();
}
}
}

class Consumer extends Thread


{
private PipedInputStream pis;
public Consumer(PipedInputStream pis)

{
this.pis=pis;
}
public void run()

{
try

{
byte[] buf=new byte[100];
int len=pis.read(buf);
System.out.println(new String(buf,0,len));
pis.close();
}
catch(Exception e)

{
e.printStackTrace();
}
}
}練習實現,文件拷貝功能,條件一個字節都能看,比如PDF,備份文件可以看,電影圖片都可以正常讀取。
import java.io.*;

public class TestFileCopy
{

public static void main(String[] args)
{
BufferedInputStream in=null;
BufferedOutputStream out=null;

try
{
in=new BufferedInputStream(new FileInputStream(args[0]));
out=new BufferedOutputStream(new FileOutputStream(args[1]));
byte[] b=new byte[1024];
int len;

while((len=in.read(b))!=-1)
{
out.write(b,0,len);
}
out.flush();
}

catch(Exception e)
{
e.printStackTrace();
}

finally
{

if (in!=null)
{

try
{
in.close();
}

catch(Exception e)
{}
}

if (out!=null)
{

try
{
out.close();
}

catch(Exception e)
{}
}
}
}
}注意,out.write(b,0,len);保證了最后一次,b沒有裝滿時,可以只寫裝入的數據。
==============================
字符流
java.io.Reader
java.io.Writer
單位為字符,一次一個字符,主要對于純文本。
read(char[] cbuf)
基本方法,參數為字符數組,而不是字節數組。一個字符2字節。
FileReader,字符文件輸入流。
那么一個字符有什么存在意義呢,
'A'影射編碼成為整數65,而反過來,整數解碼成為'A'。如果編解碼不統一就會出現亂碼。
ASCii,包括數字和字符,一個字節,256個字符
這是最早的編碼,所以以后的任何編碼都兼容ASCii,所以英文總沒有問題。
ISO-8859-1,一個字節 1B
GB2312,國標,2B,65535,‘喆’就不這個字符集中,只有常用漢字。
GBK,2B。包含所有漢字。
UNICODE 2B
UTF-8,不一定占用幾個字節。
解決亂碼問題的宗旨,就是保證編碼解碼方式一致。
---------------------------
java.io.InputStreamReader
InputStreamReader(InputStream in)
這是一個字符流,而構造函數參數是一個字節流。
通常稱之為從字節六到字符流的橋轉換。
InputStreamReader(InputStream in, String charsetName)
第二個參數就是編碼方式參數,指對字節流按照什么解碼方式將文件讀入。
OutputStreamWriter(OutputStream out, String charsetName)
輸出是指按什么編碼方式輸出字節流。
import java.io.*;


public class TestReaderWriter
{

static void write() throws Exception

{
FileOutputStream fos = new FileOutputStream("test.dat");
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
BufferedWriter out = new BufferedWriter(osw);
out.write("慢慢爐火純青了!");
out.newLine();
out.write("學完C++,Java確實很簡單,但很棒!");
out.flush();
}

static void read() throws Exception

{
FileInputStream fis = new FileInputStream("test.dat");
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
BufferedReader in = new BufferedReader(isr);
String line;
while((line = in.readLine())!=null)

{
System.out.println(line);
}
}

public static void main(String[] args) throws Exception

{
write();
read();
System.out.println(System.getProperty("file.encoding"));
}

}PrintWriter,也是一個帶緩沖的字符輸出流,可以直接由一個OutputStream或者Writer構造,但功能更強大,也就是方法更多。
PrintWriter(OutputStream out, boolean autoFlush)
PrintWriter(Writer out, boolean autoFlush)println(String x)
PrintStream,也是同理,帶緩沖的字節輸出流,功能比BufferedOutputStream更強。
==========================================
java.io.ObjectOutputStream 過濾流
輸出一個對象,是對DataOutputStream的增強。
writeObject(Object obj)
對象序列化,對象需要實現Serializable接口,這個接口是一個標記接口。
由于對象有價值的東西就是屬性,所以只關系對象的屬性文件,如果某個屬性沒有序列化的意義,那么就用transient修飾,表示不持久化該屬性。
恢復時,為默認屬性。
要求屬性也是Serializable的。
用命令serialver判斷一個類是否可以序列化。
=====================================
早期持久化,就是通過文件存儲信息,通過定義特定分割符分開信息。
StringTokenizer st = new StringTokenizer(s,"t");
while(st.hasMoreTokens()){
System.out.println();
}
======================================
void open{
BufferedReader in = null;
try{
FileInputStream fis = new FileInputStream("data");
InputStreamReader ir = new InputStreamReader(fis);
in = new BufferedReader(ir);
}catch(Exception e)
{
}
finally{
if(in!=null)
try{
in.close();
}catch(Exception){}
}
}
posted on 2005-12-25 00:08
北國狼人的BloG 閱讀(429)
評論(0) 編輯 收藏 所屬分類:
達內學習總結