天天看點

java知識點拾遺(IO流-1)

  1. 主要類
  2. java知識點拾遺(IO流-1)
  3. File類
  • 名稱分隔符
path1="d:/temp/test.txt";
path2="d:"+File.separator+"temp"+File.separator+"test.txt";

//1、建構File對象
File src = new File(path);
System.out.println(src.length());

//2、建構File對象
src = new File("D:/java300/IO_study01","IO.png");
src = new File("D:/java300/","IO_study01/IO.png");
System.out.println(src.length());

//3、建構File對象
src = new File(new File("D:/java300/IO_study01"),"IO.png");
System.out.println(src.length());      
  • 路徑基本資訊
//使用者目錄
System.out.println(System.getProperty("user.dir"));
//取得絕對路徑
src = new File("IO.png");
System.out.println(src.getAbsolutePath());

File src = new File("IO_study01/IO.png");
    
//基本資訊
System.out.println("名稱:"+src.getName());
System.out.println("路徑:"+src.getPath());
System.out.println("絕對路徑:"+src.getAbsolutePath());
System.out.println("父路徑:"+src.getParent());
System.out.println("父對象:"+src.getParentFile().getName());

//檔案狀态
src = new File("xxx");
if(null == src || !src.exists()) {
  System.out.println("檔案不存在");
}else {
  if(src.isFile()) {
    System.out.println("檔案操作");
  }else { //src.isDirectory()
    System.out.println("檔案夾操作");
  }
}

//擷取檔案的長度位元組數(檔案夾傳回0)
File src = new File("D:/java300/IO_study01/IO.png");
System.out.println("長度:"+ src.length());

//檔案操作
//createNewFile()  : 不存在才建立,存在建立失敗,隻能建立檔案
//delete():删除已經存在的檔案
//作業系統的裝置名不能作為檔案名建立
File src = new File("D:/java300/IO_study01/io.txt");
boolean flag =src.createNewFile();
System.out.println(flag);
flag = src.delete();
System.out.println(flag);      
  • 建立目錄
//1、mkdir() : 確定上級目錄存在,不存在建立失敗
//2、mkdirs(): 上級目錄可以不存在,不存在一同來建立

File dir = new File("D:/java300/IO_study01/dir/test");
//建立目錄 mkdirs()
boolean flag = dir.mkdirs();
System.out.println(flag);
//建立目錄 mkdir()
dir = new File("D:/java300/IO_study01/dir/test2");
flag = dir.mkdirs();
System.out.println(flag);      
  • 列出目錄資訊
File dir = new File("D:/java300/IO_study01");
    
//下級名稱  list
String[] subNames = dir.list();
for(String s:subNames) {
  System.out.println(s);
}

//下級對象  listFiles()
File[] subFiles = dir.listFiles();
for(File s:subFiles) {
  System.out.println(s.getAbsolutePath());
}

//所有盤符
File[] roots = dir.listRoots();
for(File r:roots) {
  System.out.println(r.getAbsolutePath());
}      
  • 統計目錄的大小(Byte)
public class Test {
  public static void main(String[] args) {
    File src =  new File("D:\\java300\\IO_study01");
    count(src);
    System.out.println(len);
  }
  private static long len =0;
  public static void count(File src) {  
    //擷取大小
    if(null!=src && src.exists()) {
      if(src.isFile()) {  //大小
        len+=src.length();
      }else { //子孫級
        for(File s:src.listFiles()) {
            count(s);
        }
      }
    }
  }
}      
  1. 字元編碼

    Java字元使用16位的雙位元組存儲。

字元集 說明
US-ASCII ASCII編碼
ISO-8859-1 Latin-1 拉丁字元,包含中文,日文等
UTF-8 變長Unicode字元(1-3位元組),英文字元占1個位元組,中文字元占3個位元組。
UTF-16BE 定長Unicode字元(2位元組),Gig-Ending編碼:高位元組低位址
UTF-16LE 定長Unicode字元(2位元組),Little-Ending編碼:低位元組低位址
UTF_16 檔案的開頭指明BE/LE編碼方式,即BOM(Byte Order Mark):“FE FF”表示BE編碼,“FF FE”表示LE編碼

這裡ANSI指系統預設的字元集——windows中文環境下預設字元集是GBK。

  • 字元編碼
String english = "abc";
String chinese = "将進酒";

byte[] data1 = english.getBytes();
System.out.println("英文\"" + english + "\"的長度:" + data1.length);
byte[] data2 = english.getBytes("GBK");
System.out.println("英文\"" + english + "\"的長度:" + data2.length);

byte[] data3 = chinese.getBytes(); // 預設getBytes("UTF8"),工程字元集,字元集名稱大小寫均可
System.out.println("中文\"" + chinese + "\"的長度:" + data3.length);
byte[] data4 = chinese.getBytes("GBK");
System.out.println("中文\"" + chinese + "\"的長度:" + data4.length);      
  • 字元解碼

    String–>byte[]:編碼

    byte[] -->String:解碼

String str1 = "米國USA";
byte[] data = str1.getBytes();

String str2 = new String(data, 0, data.length, "gbk");
System.out.println(str2);
String str3 = new String(data, "utf8");
System.out.println(str3);      
  • 亂碼的原因
  • 位元組數不夠
  • 編碼字元集不比對
  • 中文字元集

    cp936<gb2312<bgk

  1. IO流
  2. java知識點拾遺(IO流-1)
  • 位元組流

    InputStream/OutputStream

  • 字元流

    Reader/Writer

  • 讀操作步驟(概念)
//1、建立源
File src = new File("abc.txt");
//2、選擇流
try {
  InputStream  is =new FileInputStream(src);
  //3、操作 (讀取)
  int data1 = is.read(); //第一個資料s
  int data2  = is.read(); //第二個資料x
  int data3  = is.read(); //第三個資料t
  int data4  = is.read(); //????不是資料,檔案的末尾傳回-1
  System.out.println((char)data1);
  System.out.println((char)data2);
  System.out.println((char)data3);
  System.out.println(data4);
  //4、釋放資源
  is.close();
} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}      
  • 操作步驟

位元組讀

//1、建立源
File src = new File("abc.txt");
//2、選擇流
InputStream  is =null;
try {
  is =new FileInputStream(src);
  //3、操作 (讀取)
  int temp ;
  while((temp=is.read())!=-1) { //一個位元組一個位元組地讀
    System.out.println((char)temp);
  }    

} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}finally {
  //4、釋放資源
  try {
    if(null!=is) {
      is.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}      

塊讀

//1、建立源
File src = new File("abc.txt");
//2、選擇流
InputStream  is =null;
try {
  is =new FileInputStream(src);
  //3、操作 (分段讀取)
  byte[] flush = new byte[1024*10]; //緩沖容器
  int len = -1; //接收長度
  while((len=is.read(flush))!=-1) {
    //位元組數組-->字元串 (解碼)
    String str = new String(flush,0,len); //String str = new String(flush, "utf8");
    System.out.print(str);
  }    

} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}finally {
  //4、釋放資源
  try {
    if(null!=is) {
      is.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}      
  • 寫操作
//1、建立源
File dest = new File("dest.txt");
//2、選擇流
OutputStream os =null;
try {
  os = new FileOutputStream(dest,true); //true表示追加寫入
  //3、操作(寫出)
  String msg ="IO is so easy\r\n";
  byte[] datas =msg.getBytes(); // 字元串-->位元組數組(編碼,預設字元集)
  //byte[] datas  = msg.getBytes("utf8"); 按照utf8字元集編碼
  os.write(datas,0,datas.length); //或者out.write(datas);
  os.flush();
}catch(FileNotFoundException e) {    
  e.printStackTrace();
}catch (IOException e) {
  e.printStackTrace();
}finally{
  //4、釋放資源
  try {
    if (null != os) {
      os.close();
    } 
  } catch (Exception e) {
  }
}      
  • 釋放資源

    先打開的後關閉,後打開的先關閉。

    可以利用Closeable接口封裝釋放資源的動作。

public static void close(Closeable... ios) {
  for(Closeable io:ios) {
    try {
      if(null!=io) {
        io.close();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}      

或者可以利用try …with…resources自動資源釋放(JDK7之後)

try(is;os) { //<----------is和os自動釋放     
或者
try( InputStream is=new FileInputStream(src);
     OutputStream os=new FileOutputStream(dest);){
     
  ......
  ......
}catch(FileNotFoundException e) {    
  e.printStackTrace();
}catch (IOException e) {
  e.printStackTrace();
}      
  • 純文字處理

    FileReader/FileWriter(内置解決字元編解碼問題)

    append()傳回Writer,故可以實作鍊式引用。

塊讀

//1、建立源
File src = new File("abc.txt");
//2、選擇流
Reader  reader =null;
try {
  reader =new FileReader(src);
  //3、操作 (分段讀取)
  char[] flush = new char[1024]; //緩沖容器,注意是字元數組不是位元組數組
  int len = -1; //接收長度
  while((len=reader.read(flush))!=-1) {
    //字元數組-->字元串,解碼無需指定字元集(系統已經處理好了)
    String str = new String(flush,0,len);
    System.out.println(str);
  }    

} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}finally {
  //4、釋放資源
  try {
    if(null!=reader) {
      reader.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}      

塊寫

//1、建立源
File dest = new File("dest.txt");
//2、選擇流
Writer writer =null;
try {
  writer = new FileWriter(dest);
  //3、操作(寫出)
  //寫法一
  //String msg ="I love you baby\r\n你知道我在等你嗎";
  //char[] datas =msg.toCharArray(); // 字元串-->字元數組(不存在編碼問題)
  //writer.write(datas,0,datas.length);
  寫法二
  String msg ="I love you baby\r\n你知道我在等你嗎";
  writer.write(msg);  
  writer.write("add");    
  writer.flush();
  
  //寫法三
  //writer.append("I love you baby\r\n").append("你知道我在等你嗎");
  //writer.flush();
}catch(FileNotFoundException e) {    
  e.printStackTrace();
}catch (IOException e) {
  e.printStackTrace();
}finally{
  //4、釋放資源
  try {
    if (null != writer) {
      writer.close();
    } 
  } catch (Exception e) {
  }
}      
  • 位元組數組流

    ByteArrayInputStream&ByteArrayOutputStream,在記憶體中,Java可以直接通路,無需關閉。

  • 處理流

    使用了裝飾模式。

  • java知識點拾遺(IO流-1)
  • 裝飾器類包裹/包裝基本類。接口方法(産生多态行為)從裝飾器類向基本類方向層層調用,然後由内層的基本類向外部的包裝類層層傳回。抽象類實作接口,但主要是要提供公共屬性。
  1. 流的緩沖
  • 提供緩沖的裝飾流類可以提高IO性能。
  • 控制流的基礎是節點流,底層不能沒有節點流。
  • 釋放外層裝飾器流類的對象,則内層的基本流類對象資源會自動釋放。釋放是從裡到外依次釋放。

這裡節點流是基本IO流類,而控制流是裝飾器IO流類。裝飾器IO流類提供流的緩沖提升IO效能。控制流類包裝節點流類——裝飾器類包裝基本類。

示例如下:

File src = new File("abc.txt");
...
is=new BufferedInputStream(new FileInputStream(src));
          裝飾器類                   基本類
          控制流類                   節點流類
          提升IO效能
          後釋放(手動)             先釋放(自動)
-------------------------------------------------------------------
File dest = new File("dest.txt");
...
os =new BufferedOutputStream( new FileOutputStream(dest));      
  1. 字元輸入輸出加入緩沖流
  • 讀入
//1、建立源
File src = new File("abc.txt");
//2、選擇流
BufferedReader  reader =null;
try {
  reader =new BufferedReader(new FileReader(src));
  //3、操作 (分段讀取)
  String line =null;
  while((line=reader.readLine())!=null) {
    //字元數組-->字元串
    System.out.println(line);
  }    

} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}finally {
  //4、釋放資源
  try {
    if(null!=reader) {
      reader.close();
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
}      
  • 寫出
//1、建立源
File dest = new File("dest.txt");
//2、選擇流
BufferedWriter writer =null;
try {
  writer = new BufferedWriter(new FileWriter(dest));
  //3、操作(寫出)      
  writer.append("I love you baby");
  writer.newLine(); //輸出一個\r\n
  writer.append("偏偏喜歡你");
  writer.flush();
}catch(FileNotFoundException e) {    
  e.printStackTrace();
}catch (IOException e) {
  e.printStackTrace();
}finally{
  //4、釋放資源
  try {
    if (null != writer) {
      writer.close();
    } 
  } catch (Exception e) {
  }
}      
  1. 轉換流

    CharactorStreams—>InputStreamReader/OutputStreamWriter—>ByteStreams

  • 将位元組流轉換成字元流
//操作System.in 和System.out
try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer =new BufferedWriter(new OutputStreamWriter(System.out));){
  //循環擷取鍵盤的輸入(exit退出),輸出此内容
  String msg ="";
  while(!msg.equals("exit")) {
    msg = reader.readLine(); //循環讀取
    writer.write(msg); //循環寫出
    writer.newLine();
    writer.flush(); //強制重新整理。不強制重新整理,在緩存未滿時不輸出,卡在上一步。
  }
}catch(IOException e) {
  System.out.println("操作異常");
}      
  • 處理指定字元集
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;

public class ConvertTest {
  public static void main(String[] args) {
    try(BufferedReader reader =
        new BufferedReader(
            new InputStreamReader(
                new URL("http://www.baidu.com").openStream(),"UTF-8"));
      BufferedWriter writer =
        new BufferedWriter(
          new OutputStreamWriter(
            new FileOutputStream("baidu.html"),"UTF-8"));){
      //3、操作 (讀取)
      String msg ;
      while((msg=reader.readLine())!=null) {
        //System.out.println(msg);
        writer.write(msg); //如果字元集不統一将出現亂碼
        writer.newLine();
      }          
      writer.flush();
    }catch(IOException e) {
      System.out.println("操作異常");
    }  
  }
}      
  1. 資料流

    DataInputStream/DataOutputStream儲存了資料及其類型。

//寫出
ByteArrayOutputStream baos =new ByteArrayOutputStream();
DataOutputStream dos =new DataOutputStream(new BufferedOutputStream(baos));
//操作資料類型 + 資料
dos.writeUTF("白日依山盡");
dos.writeInt(18);
dos.writeBoolean(false);
dos.writeChar('a');
dos.flush();
byte[] datas =baos.toByteArray();
System.out.println(datas.length);
//讀取
DataInputStream dis =new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//順序與寫出一緻
String msg = dis.readUTF(); 
int age = dis.readInt();
boolean flag = dis.readBoolean();
char ch = dis.readChar();
System.out.println(flag);