JAVA的I/O介紹


<<瘋狂JAVA編程>>第15章有詳細介紹,講的還是相當不錯的,我們可以好好看下

IO流分為輸入流(InputStream)輸出流(OutputStream)兩類
按流所處理的數據類型又可以分為字節流字符流(用於處理Unicode字符數據)兩類

字節流主要是由 InputStream和OutputStream作為基類,而字符流主要是由 Reader和Writer作為基類的

節點流(低級流) 和 處理流(高級流):
JAVA使用處理流來包裝節點流式一種典型的裝飾器設計模式,通過使用處理流來包裝不同的節點流,既可以消除不同節點流的實現差異,也可以提供更方便的方法來完成輸入輸出功能,這就允許Java應用程序采用相同的代碼,透明的方式來訪問不同輸入\輸出設備的數據流。所以處理流也叫做包裝流

下圖說明相關體系:

 

文件類:(File):
提供文件操作功能(File可以創建,刪除等操作對文件或目錄,但是要訪問文件內容,就必須用到輸入/輸出流)

1.創建File類對象:
File f;
f = new File("Test.java");
f = new File("E:\\ex\\","Test.java");

2.將目錄也當作文件處理File類中提供了實現目錄管理功能的方法:
File path = new File("E:\\ex\\");
File f = new File(path, "Test.java");

方法:
f.getName():返回文件名 temp.dat
f.getParent():返回文件所在目錄名 data
f.getPath():返回文件路徑 data\temp.dat
f.getAbsolutePath():返回絕對路徑 …\data\temp.dat
f.exists():文件是否存在
f.canWrite(), f.canRead():文件是否可寫、讀
f.isFile(), f.isDirectory():是否為文件或目錄
f.lastModified(), f.length(), f.delete():文件的最后修改日期、長度;刪除文件
f.mkdir(), f.list():創建一個目錄;列出目錄下所有的文件

幾個例子說明:

import java.io.*;
class FileTest{
    public static void main(String[] str){
        File f = new File("E:\\Workspace\\aaa.txt");
        //判斷是否存在該文件
        if (!f.exists()){
            System.out.println("file is not exist");
            try {
                f.createNewFile();//不存在就創建新的文件
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        File f1 = new File("E:\\Workspace\\aaa1\\sdfsdf\\asdf");
        if (f1.mkdir()){ //創建目錄
            System.out.println("yes");
        }
        else{
            System.out.println("errors ");
        }
    }
}
import java.io.*;

//瀏覽當前目錄下的所有文件和目錄
class FileDirectory{
     public static void main( String[] args ) {
          try {
             File f1 = new File("");
             String ss = f1.getAbsolutePath();
             System.out.println("ss= " + ss);
             File f = new File(ss);

             if( f.isDirectory() ) {
                //獲取目錄下所有的文件列表
                File[] files = f.listFiles();
                for( int i=0; i<files.length; i++ ) {
                   if( files[ i ].isDirectory() ) {
                      System.out.println( "<dir> " + files[ i ].getName() );
                   }
                   else {
                      System.out.println( files[ i ].getName() );
                   }
                }
             }
          }
          catch( Exception e ) {
             e.printStackTrace();
          }       
      }    
}
import java.io.*;

class SuperTest{
    public static void main(String args[]) {
        File dir = new File("E:\\Workspace\\Java\\test20111108"); // 用File 對象表示一個目錄
        Filter filter = new Filter("txt"); // 生成一個名為java的過濾器
        System.out.println("list java files in directory " + dir);
        
        String[] files = dir.list(filter); // 列出目錄dir下,文件后綴名為txt的所有文件
                            
        for (int i = 0; i < files.length; i++) {
            File f = new File(dir, files[i]); // 為目錄dir 下的文件或目錄創建一個File 對象
            if (f.isFile()) // 如果該對象為后綴為java的文件,則打印文件名
                System.out.println("file: " + f);
            else
                System.out.println("sub directory " + f); // 如果是目錄則打印目錄名
        }        
    }
}

class Filter implements FilenameFilter {
    String extent;
    Filter(String extent) {
        this.extent = extent;
    }
    
    public boolean accept(File dir, String name) {        
        return name.endsWith("." + extent); //返回文件的后綴名
    }
}

 

字節文件流:FileInputStream和FileOutputStream

import java.io.*;

/**
*把一個文件的所有內容寫到另外一個文件中
*/
class FileStreamTest{
    public static void main(String args[]) {
        try {
            File inFile=new File("test1.txt");
            File outFile=new File("test2.txt");
            FileInputStream fis=new FileInputStream(inFile);
            FileOutputStream fos=new  FileOutputStream(outFile);
            
            int c;
            while((c=fis.read())!=-1) //讀取一個字節
            {
                    fos.write(c);
            }
            
            fis.close();
            fos.close();
        }catch(FileNotFoundException e) {
              System.out.println("FileStreamsTest: "+e);
        }catch(IOException e) {
           System.err.println("FileStreamsTest: "+e);
        }
    }
}
import java.io.*;

class CopyFileTest{
    public static void main(String args[]) {
        CopyFileTest cf = new CopyFileTest ();
        cf.copyFile("test1.txt","test3.txt");
    }
    
    public boolean copyFile(String src,String des){    
        File srcFile,desFile;
        srcFile = new File(src);
        desFile = new File(des);
        FileInputStream fis = null;
        FileOutputStream fos = null;
    
        try{
              desFile.createNewFile();
              fis = new FileInputStream(srcFile);
              fos = new FileOutputStream(desFile);//覆蓋
            //  fos = new FileOutputStream(desFile,true);//追加

              int bytesRead;
              byte[] buf = new byte[4 * 1024];  // 4K buffer
              while((bytesRead=fis.read(buf))!=-1){
                fos.write(buf,0,bytesRead);
              }
              fos.flush();
              fos.close();
              fis.close();
        }catch(IOException e){
          System.out.println(e);
          return false;
        }
          return true;    
    } 
}

如果只是在尾部追加,而不是覆蓋需要調用FileOutputStream(“file”,true)就Ok了,對於字符流文件就是FileWriter(“file”,true)就OK樂。

 

父類過濾流:
FilterInputStream(InputStream in);
FilterOutputStream(OutputStream out);

 

過濾流—緩沖流

BufferedInputStream和BufferedOutputStream繼承FilterInputStream和FilterOutputStream,實現了帶緩沖的過濾流,它提供了緩沖機制,把任意的I/O流“捆綁”到緩沖流上,可以提高該I/O流的讀取效率,在初始化時,除了要指定所連接的I/O流之外,還可以指定緩沖區的大小。
在讀寫的同時對數據緩存,這樣避免每次讀寫數據都要進行實際的物理讀寫操作,在用BufferdOutputStream輸出時,數據先輸入緩沖區,當緩沖區滿的時再寫入連接的輸出流,可以調用flush()來清空緩沖區。

import java.io.*;

class SuperTest{
    public static void main(String args[]) {
        try {
            File inFile = new File("test1.txt");
            File outFile = new File("test4.txt");
            
            BufferedInputStream bufFis=new BufferedInputStream(new FileInputStream(inFile),256);            
            BufferedOutputStream bufFos=new BufferedOutputStream(new FileOutputStream(outFile),256);            
            
            int len;
            byte bArray[]=new byte[256];
            
            do{
                System.out.println("while");
                len = bufFis.read(bArray);
                bufFos.write(bArray,0,len);
                System.out.println("len: " +len);
            }while (len==256);    
                        
            bufFis.close();
            bufFos.close();
        } catch (FileNotFoundException e) {
            System.out.println("FileStreamsTest: " + e);
        } catch (IOException e) {
            System.err.println("FileStreamsTest: " + e);
        }
    }
}

 

過濾流—數據流

DataInputStream和DataOutputStream, 繼承FilterInputStream和FilterOutputStream,可以用來與計算機無關的格式讀寫JAVA的基本數據類型以及String對象。
readBoolean() 讀一字節,非零為真
readByte() 以8位讀字節
readChar() 讀Unicode字符
readInt() 讀整數值
writeChar(int v) 把字符寫進輸出流
writeLong(long v) 把長整寫進輸出流
writeInt(int v) 把整數寫進輸出流


數據輸出流可以是一個已經建立好的輸入數據流對象,例如網絡的連結,文件等。數據流可通過如下方式建立。
FileInputStream fis = new FileInputStream("file1.txt");
FileOutputStream fos = new FileOutputStream("file2.txt");
DataInputStream dis = new DataInputStream(fis);
DataOutputStream dos = new DataOutputStream(fos);

import java.io.*;

class DataStreamIOTest{
    public static void main(String args[]) throws IOException 
    {
        FileOutputStream fos = new FileOutputStream("a.txt");
        DataOutputStream dos = new DataOutputStream(fos);
        try {
            dos.writeBoolean(true);
            dos.writeByte((byte) 123);
            dos.writeChar('J');
            dos.writeDouble(3.141592654);
            dos.writeFloat(2.7182f);
            dos.writeInt(1234567890);
            dos.writeLong(998877665544332211L);
            dos.writeShort((short) 11223);
        } finally {
            dos.close();
        }
        
        FileInputStream fis = new FileInputStream("a.txt");
        DataInputStream dis = new DataInputStream(fis);
        try {
            System.out.println("\t " + dis.readBoolean());
            System.out.println("\t " + dis.readByte());
            System.out.println("\t " + dis.readChar());
            System.out.println("\t " + dis.readDouble());
            System.out.println("\t " + dis.readFloat());
            System.out.println("\t " + dis.readInt());
            System.out.println("\t " + dis.readLong());
            System.out.println("\t " + dis.readShort());
        } finally {
            dis.close();
        }
    }
}//需要注意的是必須throws IOException才可以編譯通過。

 

 

字符流

例子:利用FileWriter來寫文件
    try
        {
            FileWriter fw = new FileWriter("mydata.txt");             
            PrintWriter out = new PrintWriter(fw); 
            out.print("面朝大海,");
            out.println("春暖花開!");
            out.println("環境美好!!");
            out.close();
            fw.close();
        }catch(IOException e)
        {
            e.printStackTrace();
        }
例子:字符緩沖流BufferedReader
import java.io.*;
class SuperTest{
    public static void main(String args[]) throws IOException
    {
        File file = new File("mydata.txt");
        
        try {
            BufferedReader in = new BufferedReader(new FileReader(file));
            String s;
            s = in.readLine();
            while ( s != null ) {
                System.out.println("Read: " + s);
                s = in.readLine();
            }
            in.close();
        } catch (FileNotFoundException e1) {
            System.err.println("File not found: " + file);
        } catch (IOException e2) {
            e2.printStackTrace();
        }
    }
}
例子:拷貝(FileReader和FileWriter)
            try {
                    FileReader input = new FileReader(args[0]);
                    FileWriter output = new FileWriter(args[1]);
                    
                    char[] buffer = new char[128];
                    int charsRead;
                    charsRead = input.read(buffer);
                    
                    while ( charsRead != -1 ) 
                    {
                        output.write(buffer, 0, charsRead);
                        charsRead = input.read(buffer);
                    }
                    
                    input.close();
                    output.close();
                } catch (IOException e) 
                {
                    e.printStackTrace();            
                }
            }
例子:拷貝(BufferedWriter)
try {
        FileReader input = new FileReader(args[0]);
        BufferedReader bufInput = new BufferedReader(input);
        FileWriter output = new FileWriter(args[1]);
        BufferedWriter bufOutput = new BufferedWriter(output);
        String line;
        
        line = bufInput.readLine();
        while ( line != null ) 
        {
            bufOutput.write(line, 0, line.length());
            bufOutput.newLine();
            line = bufInput.readLine();
        }
        
        bufInput.close();
        bufOutput.close();
    } 
    catch (IOException e) 
    {
        e.printStackTrace();
    }

 

隨機存取文件流--RandomAccessFile
1 RandomAccessFile是一種特殊的文件流,可以用它在文件的任何地方查找或者插入數據
2 RandomAccessFile同時實現了DataInput和DataOutput接口,所以可以用它來讀/寫文件
3構造器:
RandomAccessFile(java.io.File f,String mode)
RandomAccessFile(String file,String mode)
4 mode可以為”r”或”rw”

方法:
1 readXXX()或writeXXX():
如ReadInt(), ReadLine(), WriteChar(), WriteDouble()等
2 int skipBytes(int n):將指針向下移動若干字節
3 length():返回文件長度
4 long getFilePointer():返回指針當前位置
5 void seek(long pos):將指針調到所需位置

import java.io.*;
import java.util.*;

class RandomAccessFileTest{
    public static void main(String args[])
    {
        try{
              File logfile=new File("mydata.txt");
              
              if(logfile.exists())
              {
    RandomAccessFile raf=new RandomAccessFile(logfile,"rw");
                  System.out.println("leghth = " + raf.length());
                  raf.seek(raf.length());
                  
                  for(int i=0;i<5;i++)
                  {
                      raf.writeBytes("Write "+new Date()+ "\r\n");
                  }
                    
                  raf.seek(0);
                  String x=raf.readLine();
                  
                  while(x!=null)
                  {
                    System.out.println(x);
                    x=raf.readLine();
                  }
                  
                  raf.close();
              }
           }catch(IOException e){
              e.printStackTrace();
            }
    }
}

 

JAVA流總結:
1 在Java中有數據傳輸的地方都用到I/O流(通常是文件,網絡,內存和標准輸入輸出等)。
2 InputStream 和OutputStream是所有字節流的祖先(只有RandomAccessFile類是一個例外),read和write是它們最基本的方法,讀寫單位是字節
3 Reader 和Writer是所有字符流的祖先,read和write是它們最基本的方法,讀寫單位是字符。
4 在眾多的流對象中,並不是每一種都單獨使用,其中過濾流的子類在數據送出去之前做必要的處理
5 File, File(Input/Output)Stream, RandomAccessFile是處理本地文件的類。
6 Data(Input/Output)Stream是一個過濾流的子類,借此可以讀寫各種基本數據,在文件和網絡中經常使用。如: readByte, writeBoolean等。
7 Buffered(Input/Output)Stream的作用是在數據送到目的之前先緩存,達到一定數量時再送到目的,已減少阻塞次。
8 Piped(Input/Output)Stream適合與一個處理的輸出作為另一個處理的輸入的情況

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM