1. 程式人生 > >Java當中的IO流(中)

Java當中的IO流(中)

標題圖

Java當中的IO流(中)

刪除目錄

import java.io.File;

public class Demo{
 public static void main(String[] args){

  // 目錄
  File dir = new File("E:\\hello");
 // 刪除目錄
 System.out.println(dir.delete());
// removeDir(dir); 
// 下方方法
 }
}

如果目錄裡面有檔案,或者還有目錄,就無法刪除,會顯示為false的,那麼就要從裡頭往外進行刪除,可以進行遞迴的方法.

進行刪除裡標頭檔案或資料夾

public static void removeDir(File dir){

 // 使用listFiles()方法,檢視目錄下是否有檔案以及資料夾
 File[] files = dir.listFiles();

 // 如果沒有目錄
 if(files.length==0){
  dir.delete();
  return;
 }

 if(files!=null){
 for(File file : files){
  // 進行遍歷files物件,判斷是否是目錄
  if(file.isDirectory()){
 // 進行刪除目錄
   removeDir(file);
  }else{
  // 進行刪除檔案
   System.out.println(file+":"+file.delete());
  }
 }
 }
 System.out.println(dir+":"+dir.delete());
}

對學生資訊進行儲存

建立學生類:

public class Student implements Comparable<Student>{

 private String name;
 private int cn, en, ma;
 private int sum;

 public Student(String name, int cn, int en, intma){
  super();
  this.name = name;
  this.cn = cn;
  this.en = en;
  this.ma = ma;
  this.sum = cn + en + ma;
 }

 public Student(){
  super();
 }

 // compareTo
 @Override
 public int compareTo(Student o){

  int temp = this.sum - o.sum;
  
  return temp==0 ? this.name.compareTo(o.name):temp;
 }

 @Override
 public int hashCode(){
  final int prime = 31;
  int result = 1;
  result = prime + result + cn;
  result = prime + result + sum;
  return result;
 }
 
 public String getName(){
  return name;
 }
 public void setName(String name){
  this.name = name;
 }

 public void setCn(int cn){
  this.cn = cn;
 }
 public int getCn(){
  return cn;
 }

 public void setEn(int en){
  this.en = en;
 }
 public int getMa(){
  return ma;
 }

 public void setMa(int ma){
  this.ma = ma;
 }
 public int getSum(){
  return sum;
 }

 public void setSum(int sum){
  this.sum = sum;
 }

 @Override
 public String toString(){
  return "Student [name=" + name + ", sum=" + sum + "]";
 }
}

將學生的成績等按照分數排序:

將資訊儲存到檔案,就要使用IO流,有很多學生就要儲存集合

// 簡書作者:達叔小生

public class Demo {
 private static final String LINE_SEPARATOR = System.getProperty("line.separator");

 public static void main(String[] args) throws IOException {

  Set<Student> set = new TreeSet<Student>(Collections.reverseOrder());

  set.add(new Student("da",12,34,55));
  set.add(new Student("shu",23,44,53));
  set.add(new Student("dashu",24,12,34));

  // 建立目錄,對應目錄

  File dir = new File("Student");

  // 如果目錄不存在就建立

  if(!dir.exists()){
   dir.mkdir();
  }

 // 對應目錄下的檔案
  File desFiles = new File(dir,"student_info.txt");
 // 把資料寫入到檔案中
  writeToFile(set,desFiles);
 
 }

 // 方法writeToFile(set,desFiles);
 public static void writeToFile(Set<Student> set, File desFile ) throws IOException {

 FileOutputStream fos = null;

 try{
  fos = new FileOutputStream(desFile);
  // 遍歷物件
  for(Student stu:set){
   String info = stu.getName() + "\t" + stu.getSum() + LINE_SEPARATOR;
   // 資料寫到檔案中
   fos.write(info.getBytes());
  }
 }finally{
  if(fos!=null){
 try{
  // 關閉資源
  fos.close();
  }catch(IOException e){
  throw new RuntimeException("系統資源關閉失敗");
 }
 }
 }
 }
}

檔案清單,就是獲取目錄中的檔案,使用遞迴的方法,通過過濾器找到指定的所有檔案.

public class Demo{

 private static final String LINE_SEPARATOR = SeparatorTool.LINE_SEPARATOR;

 public static void main(String[] args) throws IOException {
 // 明確一個目錄
  File dir = new File("E:\\hello");

 // 過濾器 建立類 FileFilterByJava
 FileFilter filter = new FileFilterBySuffix(".java"); 

 // 建立集合
 List<File> list = new ArrayList<File>();

  // 指定檔案清單
  getFileList(dir,filter,list);
 System.out.println(list.size());
 
 File desFile = new File(dir,"javalist.txt");
 writeToFile(list,desFile);
 }

// 方法writeToFile

public static void writeToFile(List<File> list, File desFile) throws IOException {

 FileOutputStream fos = null;
 BufferedOutputStream bufos = null;

 try{
  fos=new FileOutputStream(destFile);
  bufos=new BufferedOutputStream(fos);

  for(File file : list){
  String info = file.getAbsolutePath()+LINE_SEPARATOR
  bufos.write(info.getBytes());
  bufos.flush();
  }
  }finally{
   if(bufos!=null){
    try{
     fos.close();
    }catch(IOException e){
     throw new RuntimeException("關閉失敗");
    }
   }
  }
}

 public static void getFileList(File dir, FileFilter filter, List<File> list){
  // 獲取目錄下的子目錄
 File[] files = dir.llistFiles();
 // 過濾器
 
 // 遍歷子目錄
 for(File file : files){
  // 進行判斷是否是目錄,如果是進行遞迴
  if(file.isDirectory()){
   // 進行遞迴
   getFileList(file,filter,list);
  }else{
   // if(file.getName().endsWith(".java")){
    if(filter.accept(file)){
     list.add(file);
    }
   }
  }
 }
}

FileFilterByJava:

// 簡書作者:達叔小生

import java.io.File;

public class FileFilterBySuffix implements FileFilter {

 private String suffix;
 public FileFilterBySuffix(String suffix){
  super();
  this.suffix = suffix;
 }

 @Override
 public boolean accept(File pathname) {
  return pathname.getName().endsWith(suffix);
 }
}

分隔符工具:

public class SeparatorTool {

 private SeparatorTool(){
  super();
 }

 public static final String LINE_SEPARATOR = System.getProperty("line.separator");
 public static final String PATH_SEPARATOR = System.getProperty("path.separator");
 public static final String FILE_SEPARATOR = System.getProperty("file.separator");
}

位元組流輸入和輸出,字元流,位元組流讀取字元
InputStream和OutputStream
FileInputStream和FileOutputStream
BufferedInputStream和BufferedOutputStream

// 簡書作者:達叔小生

public class CharStreamDemo{
 public static void main(String[] args) throws IOException{

   // writeCNText();
  FileInputStream fis = new FileInputStream("dashu\\dashu.txt");
 // 如何判斷? 一箇中文預設為兩個位元組
 byte[] buff = new byte[1024];
 int len = 0;

 while( (len = fis.read(buff) != -1){
  String str = new String(buff,0,len);
  System.out.println(str);
 }
 fis.close();
 }
 
 public static void readCNText() throws FileNotFoundException{

 FileInputStream fis = new FileInputStream("dashu\\dashu.txt");
 
 }

 public static void writeCNText() throws FileNotFoundException, IOException{

  FileOutputStream fos = new FileOutputStream("dashu\\dashu.txt");
  fos.write("簡書作者:達叔小生".getBytes());
  fos.close();
 }

}

編碼表

編碼表 ASCII 美國標準資訊交換碼
將生活中的一切用計算機的二進位制進行對應表示關係表
中文的,GB2312,用兩個位元組表示,6到7千
GBK,常用的中文碼錶,用兩位元組表示,2萬多
unicode為國際標準碼錶,用兩個位元組表示
UTF-8是基於unicode的,用一個位元組儲存,更加標準.

// Java中

char c = 'a';
無論什麼都是兩個位元組

字元流FileReader

解碼和編碼

字串
構造方法

方法 說明
String() 是初始化一個String物件,表示一個空字元序列
String(byte[] byte) 是使用平臺預設的字符集解(預設的字符集為gbk)碼指定的byte的陣列
String(byte[] bytes, Charset charset) 是通過使用指定的charset解碼指定的byte陣列

FileInputStream

java.lang.Object
-> java.io.InputStream
-> java.io.FileInputStream

public class FileInputStream extends InputStream
從檔案系統中的某個檔案中獲取輸入位元組

如果要讀取字元流,就要用FileReader.

位元組流是用FileInputStream哦~


讀取字元檔案的 FileReader

java.io

類 FileReader

java.lang.Object

-> java.io.Reader

-> java.io.InputStreamReader

-> java.io.FileReader

public class FileReader extends InputStreamReader

此類的構造方法自帶預設的字符集編碼和位元組緩衝區,FileReader用於讀取字元流.

// 簡書作者:達叔小生

// 版本開始為JDK1.1

FileInputStream -> InputStreamReader

FileReader類是一個操作字元檔案的便捷類,有預設的字符集編碼和位元組緩衝區

FileReader的構造方法:

方法 說明
FileReader(File file) 是用來給定從中讀取資料的File
FileReader(FileDescriptor fd) 是給定從中讀取資料的FileDescriptor
FileReader(String fileName) 是用來讀取資料的檔名

java.io.InputStreamReader繼承的方法

close, getEncoding, read, ready

java.io.Reader繼承的方法

mark, markSupported, read, reset, skip

基礎頂層

java.io

類 Reader

java.lang.Object

-> java.io.Reader

用於讀取字元流的抽象類 Reader
public abstract class Reader extends Object
implements Readable, Closeable


Reader方法:

close()為關閉該流,並且釋放所有資源

mark(int readAheadLinmit)為標記流中的當前位置
markSupported()為判斷此流是否支援mark()

read()為讀取單個字元
read(char[] cbuf)為將字元讀入陣列
read(char[] sbuf, int off, int len)為將字元一部分讀入陣列
read(CharBuffer target)為試圖將字元讀入指定的字元緩衝區

ready()為判斷是否準備讀取此流
reset()為重置此流
skip(long n)為跳過字元

FileReader程式碼:

FileReader fr = new FileReader("dashu\\dashu.txt");

int ch = fr.read();
System.out.println(ch);
fr.close();
int ch = 0;
int count = 0;

while((ch=fr.read()) != -1){
 if(ch=='好'){
  count++;
 }
}

System.out.println("count =" + count);

字元流FileWriter

java.io

類 Writer

java.lang.Object

-> java.io.Writer

public abstract class Writer extends Object 
implements Appendable, Closeable, Flushable

寫入字元流的抽象類

FileWriter

FileWriter是用來寫入字元檔案的便捷類

FileOutputStream -> OutputStreamWriter

public class FileWriter extends OutputStreamWriter
java.io 類 FileWriter

java.lang.Object

-> java.io.Writer

-> java.io.OutputStreamWriter

-> java.io.FileWriter

FileWriter此類的構造方法是假定預設的字元編碼和預設的位元組緩衝區大小,FileWriter是用於寫入字元流

FileWriter(File file)
FileWriter(File file, boolean append)

FileWriter(FileDescriptor fd)

FileWriter(String fileName)
FileWriter(String fileName, boolean append)

FileWriter程式碼例子:

// 輸出流
import java.io.FileWriter;

public class FileWriterDemo{
 public static void main(String[] args) throws IOException {

  // FileWriter, 如果不存在建立一個
  FileWriter fw = new FileWriter("dashu\\dashu.txt");
  fw.write("簡書作者:達叔小生");
  fw.flush();
  fw.close();
 }
}

flush()和close()

flush為重新整理該流的緩衝,將流中緩衝區的資料重新整理到目的地,重新整理後的流可以使用

public abstract void flush() throws IOException

close為關閉此流,關閉流之前要先重新整理,關閉資源用的,在關閉前會將緩衝區裡的資料重新整理到目的地,然後在關閉流,關閉了就不可以在使用了.

public void close(){
 flush();
}
// 簡書作者:達叔小生
public abstract void close() throws IOException

異常:

java.io.IOException: Steam closed

OutputStreamWriter字元流

FileOutputStream -> OutputStreamWriter

FileWriterFileReader都是有預設的字符集編碼,如GBK

字元流通過位元組流的橋樑類是
OutputStreamWriter類 -> java.io

可以用charset將寫入流中的字元編碼為位元組
OutputStreamWriter預設的字符集可以給定,否則為平臺預設

java.lang.Object

-> java.io.Writer

-> java.io.OutputStreamWriter

public class OutputStreamWriter extends Writer

效率:OutputStreamWriter -> BufferedWriter

Writer out = new BufferedWriter(new OutputStream(System.out));

OutputStreamWriter方法:

OutputStreamWriter(OutputStream out)為使用預設的字元編碼
OutputStreamWriter(OutputStream out, Charset cs)為使用給定的字符集編碼

OutputStreamWriter例子

// GBK UTF-8
public class Demo{
 public static void main(String[] args) throws UnsupportedEncodingException, IOException {
  // 有的人用的卻是UTF-8
  OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("dashu\\dashu.txt"), "utf-8" );
  osw.write("簡書作者:達叔小生");
  osw.close();
 }
}

升級:

// 導致亂碼
public static void read() throws IOException{

 FileReader fr = new FileReader("dashu\\dashu.txt");
 // int ch = (char)fr.read();

 char[] buff = new char[1024];
 int len = fr.read(buff);
 System.out.println(new String(buff,0,len);
 fr.close();
}

字元流 InputStreamReader

java.io

類 InputStreamReader

java.lang.Object

-> java.io.Reader

-> java.io.InputStreamReader

public class InputStreamReader extends Reader

InputStreamReader是用來指定編碼讀取中文的,是位元組流通向字元流的橋樑,可以用charset讀取位元組並解碼為字元.

為了提高效率,可以BufferedReader內包裝InputSteamReader

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

InputStreamReader例子:

構造方法:

InputStreamReader(InputStream in)
InputStreamReader(InputStream in, Charset cs)
InputStreamReader(InputStream in, CharsetDecoder dec)
InputStreamReader(InputStream in, String charsetName)

InputStreamReader方法:

// 簡書作者:達叔小生
close()
getEncoding()
read()
read(char[] cbuf, int offset, int length)
ready()
public static void read() throws IOException {
 // 建立InputStreamReader物件
 InputStreamReader isr = new InputStreamReader(new FileInputStream("dashu\\dashu.txt"), "utf-8");
 
char[] buff = new char[1024];
 int len = isr.read(buff);
 System.out.println(new String(buff,0,len));
 isr.close();
}
// InputStreamReader  Console輸出

IO流-InputStreamReader和OutputStreamWriter 轉換流

// 簡書作者:達叔小生

 InputStreamReader isr = new InputStreamReader(new FileInputStream("dashu\\dashu.txt"), "GBK");
 
 char[] buff = new char[1024];
 int len = isr.read(buff);
 System.out.println(new String(buff,0,len));
 isr.close();

InputStreamReader的子類為FileReader
OutputStreamWriter的子類為FileWriter

在上面有寫到字元流和位元組的橋樑為OutputStreamWriterInputStreamReader,所以稱為字元轉換流

其字元轉換流原理為位元組流和編碼表

字元流通過位元組流的橋樑類是
OutputStreamWriter類 -> java.io
可以用charset將寫入流中的字元編碼為位元組

InputStreamReader 是用來指定編碼讀取中文的,是位元組流通向字元流的橋樑

FileWriterFileReaderOutputStreamWriterInputStreamReader的子類,只是用來操作字元檔案的便捷類,使用的是預設的編碼表.

如果要使用其他編碼時,要使用字元轉換流,反之操作的是檔案,且用預設的編碼時,就使用FileWriterFileReader.

不轉換:

FileReader fr = new FileReader("dashu.txt");

轉換流:

InputStreamReader isr = new InputStreamReader(new FileInputStream("dashu.txt"), "GBK");

要點

位元組到字元, 輸入流, 為InputStreamReader, 是需要讀的,
讀的是要給人懂的得,才能讀,從看不懂的到看得懂的.

字元到位元組, 輸出流, 為OutputStreamWriter, 是需要寫的,
寫的是從看懂的到看不懂.

用字元流複製文字檔案

public class CopyTextFileTest{
 public static void main(String[] args) throws IOException {
  copyTextFile();
 }

 public static void copyTextFile() throws IOException {
  // 明確目標
 FileReader fr = new FileReader("dashu.java");
 // 明確目的
 FileWriter fw = new FileWriter("hello\\hello.txt");

 // 迴圈,讀字元
 // int ch = 0;
 // while((ch=fr.read()) != -1){
 // fw.write(ch);
 // }

 // 效率高的
 char[] buff = new char[1024];
 int len = 0;
 while((len=fr.read(buff) != -1){
  fw.write(buff,0,len);
 }
 // 關閉資源
 fw.close();
 fr.close();
 }
}

字元流緩衝區物件複製文字檔案

java.io

類 Reader

java.lang.Object

-> java.io.Reader

public abstract class Reader extends Object

implements Readable, Closeable

Reader是用來讀取字元流的抽象類

// 簡書作者:達叔小生
BufferedReader
BufferedWriter

字元輸入流中讀取文字-BufferedReader

緩衝區是給流的

java.io

類 BufferedReader

java.lang.Object

-> java.io.Reader

-> java.io.BufferedReader

從字元輸入流中讀取文字,用來緩衝各個字元
public class BufferedReader extends Reader

FileReaderInputStreamReader

BufferedReader in = new BufferedReader(new FileReader("dashu.txt"));

BufferedReader 的構造方法:

// 簡書作者:達叔小生
BufferedReader(Reader in)為預設大小
BufferedReader(Reader in, int sz)使用指定的大小

BufferedReader的方法

方法 說明
close() 返回型別為void,是用來關閉資源的
mark(int readAheadLimit) 返回型別為void, 是用來標記流中的當前位置
markSupported() 返回型別為boolean, 判斷此流是否支援mark()操作
read() 返回型別為int,是用來讀取單個字元的
read(char[] cbuf, int off, int len) 返回型別為Int,是將字元陣列一部分讀入
readLine() 返回型別為String, 是用來讀取一個文字的
ready() 返回型別為boolean, 是用來判斷此流是否已經準備好
reset() 返回為void, 是將流重置到最新的標記
skip(long n) 返回型別為long, 是用來跳過字元的

將文字寫入到字元輸出流-BufferedWriter

java.io

類 BufferedWriter

java.lang.Object

-> java.io.Writer

-> java.io.BufferedWriter

public class BufferedWriter extends Writer

將文字寫入字元輸出流

FileWriterOutputStreamWriter

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("dashu.txt"));

BufferedWriter 的方法

方法 說明
close() 返回型別為void,是用來關閉資源的
flush() 返回型別為void,是用來重新整理該流的緩衝
newLine() 返回型別為void,是用來寫入一個行分隔符
write(char[] cbuf, int off, int len) 返回型別為void, 是用來寫入字元陣列的一部分
write(int c) 返回型別為void,是用來寫入單個字元
write(String s, int off, int len) 返回型別為void, 寫入字串的一部分

字元流的緩衝區

// 簡書作者:達叔小生

public class CharStreamBufferedDemo{
 public static void main(String[] args) throws IOException {

  // BufferedReader和BufferedWriter 字元流緩衝區
 // BufferedReader
 // 從字元輸入流中讀取文字,用來緩衝各個字元
 // BufferedWriter 
 // 將文字寫入到字元輸出流

 copyTextByBuffer();
 readText();
 writeText();
 }

 public static void writeText()  throws IOException {

  BufferedWriter b = new BufferedWriter(new FileWriter("hello.java");

  for(int x=1, x<=4; x++){
   b.write(x);
   b.newLine();
   b.flush();
  }
  b.close();
 }

 public static void readText() throws IOException {

  BufferedReader buffer = new BufferedReader(new FileReader("dashu.java");

  // String line = buffer.readLine();
  // System.out.println(line);

 String line = null;
 while((line=buffer.readLine()) != null){
  System.out.println(line);
 }
  buffer.close();
 }

 public static void copyTextByBuffer(){

  BufferedReader bufr = new BufferedRead(new FileReader("hello.txt"));
  BufferedWriter bufw = new BufferedWriter(new FileWriter("hello\\dashu.txt"));

  // 迴圈
 String line = null;
 while((lline = bufr.readLine() != null){
   bufr.write(line);
   bufr.newLine();
   bufr.flush();
  }
  bufw.close();
  bufr.close();
 }
}

流是一連流串的字元,是資訊的通道,分輸出流和輸入流。

IO的分類

第一種分:輸入流和輸出流。
第二種分:位元組流和字元流。
第三種分:節點流和處理流。

Java中流的分類:

流的運動方向,可分為輸入流和輸出流兩種。

流的資料型別,可以分為位元組流和字元流。

輸入流類都是抽象類
InputStream(位元組輸入流)或抽象類Reader類(字元輸入流)的子類。

輸出流類都是抽象類
OutputStream(位元組輸出流)或抽象類Writer類(字元輸出流)的子類。

輸入流從檔案輸入為讀取輸出流從檔案輸出為寫入資料

輸入流
輸入流用於讀取資料,使用者可以從輸入流中讀取資料,但不能寫入資料。

輸入流讀取資料過程如下:
(1)開啟一個流。
如:FileInputStream inputFile=new FileInputStream("資料來源");
(2)從資訊源讀取資訊。
如:inputFile.read();
(3)關閉流。
如:inputFile.close();

輸出流
輸出流用於寫入資料。只能寫,不能讀。

寫資料到輸出流過程如下:
(1)開啟一個流。
如:FileOutputStream outFile=new FileOutputStream("資料來源");
(2)寫入資訊到目的地。
如:outFile.write(inputFile.read()):
(3)關閉流。
如:outFile.close();

字元流ReaderWriter

位元組字元轉換流:

// 簡書作者:達叔小生
InputStreamReader
OutputStreamWriter

往後餘生,唯獨有你
簡書作者:達叔小生
90後帥氣小夥,良好的開發習慣;獨立思考的能力;主動並且善於溝通
簡書部落格: https://www.jianshu.com/u/c785ece603d1

結語

  • 下面我將繼續對 其他知識 深入講解 ,有興趣可以繼續關注
  • 小禮物走一走 or 點贊