java i/o操作
1. I/O介紹:
中I/O操作主要是指使用Java進行輸入,輸出操作. Java所有的I/O機制都是基於資料流進行輸入輸出,這些資料流表示了字元或者位元組資料的流動序列。Java.io是大多數面向資料流的輸入/輸出類的主要軟體包。此外,Java也對塊傳輸提供支援,在核心庫 java.nio中採用的便是塊IO。流IO的好處是簡單易用,缺點是效率較低。塊IO效率很高,但程式設計比較複雜。 Java.io包中包含了流式I/O所需要的所有類。在java.io包中有四個基本類:InputStream、OutputStream及Reader、Writer。 Java的IO模型設計非常優秀,它使用Decorator模式,按功能劃分Stream,您可以動態裝配這些Stream,以便獲得您需要的功能。例如,您需要一個具有緩衝的檔案輸入流,則應當組合使用FileInputStream和BufferedInputStream。
io流的四個基本類
java.io包中包含了流式I/O所需要的所有類。在java.io包中有四個基本類:InputStream、OutputStream及Reader、Writer類,它們分別處理位元組流和字元流:
一、java io的開始:檔案
public class Demo {
public static void main(String[] args){
File f = new File("e:\\file");
if(f.isDirectory()){
System.out .println(f.getPath());
}
}
}
程式碼中isDirectory()方法是判斷檔案是資料夾還是一個檔案,getPath()方法是列印檔案(這裡指的是file資料夾)的路徑。
檔案刪除
import java.io.File;
public class Demo11 {
public static void main(String[] args) {
File f = new File("f:\\demo.txt");
f.delete();
if(boo){
System.out .println("成功刪除檔案");
}
}
}
File類獲取目錄子目錄
import java.io.File;
/**
* 獲取一個目錄下的所有子項
* @author Administrator
*/
public class FileDemo {
public static void main(String[] args){
/*
* 檢視當前專案根目錄下的所有子項
*/
File dir = new File(".");
//首先判斷是否為一個目錄
if(dir.isDirectory()){
//獲取當前目錄下的所有子項
File[] subs = dir.listFiles();
for(File sub : subs){
String name = sub.getName();
//目錄是沒有長度的
long length = sub.length();
System.out.println(name+":"+length);
}
}
}
}
FileFilter類
import java.io.File;
import java.io.FileFilter;
/**
* listFiles方法支援檔案過濾器
*
* FileFilter介面,實現該介面需要實現抽象方法: boolean accept(File f)該方法要求我們定義過濾條件
* listFiles方法會將當前目錄下滿足accept方法的子項返回
* @author Administrator
*/
public class FileDemo2 {
public static void main(String[] args){
File dir = new File(".");
if(dir.isDirectory()){
//建立過濾器例項
FileFilter filter = new MyFilter();
//使用過濾器過濾子項
File[] subs = dir.listFiles(filter);
for(File sub : subs){
System.out.println(
sub.getName());
}
}
}
}
class MyFilter implements FileFilter{
public boolean accept(File file) {
System.out.println(
"正在過濾:"+file.getName());
return file.getName().startsWith(".");
}
}
建立多級目錄下的一個檔案
import java.io.File;
import java.io.IOException;
/**
* 建立多級目錄下的一個檔案
* @author Administrator
*
*/
public class FileDemo3 {
public static void main(String[] args) throws IOException{
File file = new File(
"a"+File.separator+
"b"+File.separator+
"c"+File.separator+
"d"+File.separator+
"e"+File.separator+
"f"+File.separator+
"g"+File.separator+
"h.txt"
);
/*
* 建立檔案時,應首先判斷當前檔案所在的
* 目錄是否存在,因為若不存在,會丟擲
* 異常的。
*/
/*
* File getParentFile()
* 獲取當前檔案或目錄所在的父目錄
*/
File parent = file.getParentFile();
if(!parent.exists()){
parent.mkdirs();
}
if(!file.exists()){
file.createNewFile();
System.out.println("檔案建立完畢");
}
}
}
RandomAccessFile用於讀寫檔案資料的類
mport java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException{
/*
* 對專案跟目錄下一個名為demo.dat
* 的檔案內容進行讀寫
*/
RandomAccessFile raf
= new RandomAccessFile("demo.dat","rw");
// File file = new File("demo.dat");
// RandomAccessFile raf2= new RandomAccessFile(file,"rw");
int num = 97;
raf.write(num);
raf.close();// 使用IO後,一定要記得關閉
}
}
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo2 {
public static void main(String[] args) throws IOException{
RandomAccessFile raf= new RandomAccessFile("demo.dat","r");
int i = raf.read();
System.out.println(i);
//再讀取一個位元組
i = raf.read();
System.out.println(i);
//再讀取一個位元組
i = raf.read();
System.out.println(i);
raf.close();
}
}
使用RandomAccessFile完成複製操作
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo3 {
public static void main(String[] args) throws IOException{
/*
* 1:建立一個RandomAccessFile用於讀取待複製的檔案
* 2:建立一個RandomAccessFile用於將原檔案的中資料寫入該檔案
* 3:迴圈從原檔案中讀取每一個位元組並寫入目標檔案中
* 4:關閉兩個RandomAccessFile
*/
long start = System.currentTimeMillis();
RandomAccessFile src= new RandomAccessFile("src.jpg","r");
RandomAccessFile des= new RandomAccessFile("copy.jpg","rw");
int d = -1;
while( (d = src.read()) != -1 ){
des.write(d);
}
System.out.println("拷貝完畢");
src.close();
des.close();
long end = System.currentTimeMillis();
System.out.println("耗時:"+(end-start)+"ms");
}
}
使用RandomAccessFile批量寫出一組位元組
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo4 {
public static void main(String[] args) throws IOException{
RandomAccessFile raf= new RandomAccessFile("test.txt","rw");
String str = "我愛北京天安門";
/* String的getBytes()方法:將當前字串按照當前系統預設的字符集轉換為對應的位元組。*/
byte[] buf = str.getBytes("gbk");
raf.write(buf);
raf.close();
}
}
使用RandomAccessFile讀取一個位元組陣列的資料
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
public class RandomAccessFileDemo5 {
public static void main(String[] args) throws IOException{
RandomAccessFile raf= new RandomAccessFile("test.txt","r");
/*int read(byte[] buf)一次嘗試從檔案中讀取buf陣列length個位元組並從該陣列的第一個位置處起存放實際讀取到的位元組。返回值為實際讀取到的位元組數*/
byte[] buf = new byte[50];
int len = raf.read(buf);
System.out.println(len);
System.out.println(Arrays.toString(buf));
/*從位元組陣列轉換為對應的字串*/
String str = new String(buf,"GBK");
System.out.println(str.trim());
raf.close();
}
}
使用RandomAccessFile基於快取形式複製檔案
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo6 {
public static void main(String[] args) throws IOException{
RandomAccessFile src= new RandomAccessFile("src.jpg","r");
RandomAccessFile des= new RandomAccessFile("copy.jpg","rw");
long start = System.currentTimeMillis();
byte[] buf = new byte[1024*10];
int len = -1;
/*int read(byte[] buf)若返回值為-1,表示沒有資料可讀了*/
while((len = src.read(buf))!=-1){
/*void write(byte[] b,int offset,int len)該方法的作用是將給定的位元組陣列中offset處開始,連續len個位元組寫出*/
des.write(buf,0,len);
}
long end = System.currentTimeMillis();
System.out.println("耗時:"+(end-start));
src.close();
des.close();
}
}
使用RandomAccessFile向檔案中寫入基本型別資料
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo7 {
public static void main(String[] args) throws IOException{
RandomAccessFile raf= new RandomAccessFile("raf.dat","rw");
int num = Integer.MAX_VALUE;
//連續寫4個位元組,將int值寫出
raf.writeInt(num);
raf.writeDouble(1.4);
raf.writeLong(1234l);
raf.close();
}
}
使用RandomAccessFile讀取基本型別資料
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo8 {
public static void main(String[] args) throws IOException{
RandomAccessFile raf= new RandomAccessFile("raf.dat","r");
int i = raf.readInt();
System.out.println(i);
double d = raf.readDouble();
System.out.println(d);
long l = raf.readLong();
System.out.println(l);
raf.close();
}
}
檢視RandomAccessFile的指標位置
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException{
RandomAccessFile raf= new RandomAccessFile("raf.dat","rw");
/*
* long getFilePointer()
* 獲取當前RAF的指標位置
*/
long p = raf.getFilePointer();
System.out.println(p);//0
raf.write(97);//寫一個位元組
System.out.println(raf.getFilePointer());//1
raf.writeInt(1);//連續寫4個位元組
System.out.println(raf.getFilePointer());//5
/*
* 若想從檔案的某個地方讀取位元組
* 需要先將指標移動到這個位置
* void seek(long position)
*/
raf.seek(0);
//通過raf讀取一個位元組
int n = raf.read();
System.out.println(n);
System.out.println(raf.getFilePointer());//1
raf.close();
}
}
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* int skipBytes(int n)
* 該方法會嘗試跳過n個位元組,返回值為實際
* 跳過的位元組數
*/
public class RandomAccessFileDemo2 {
public static void main(String[] args) throws IOException{
RandomAccessFile raf= new RandomAccessFile("raf.dat","r");//跳過1個位元組
raf.skipBytes(1);
int i = raf.readInt();
System.out.println(i);
raf.close();
}
}
位元組流InputStream/OutputStream
1. InputStream抽象類
InputStream 為位元組輸入流,它本身為一個抽象類,必須依靠其子類實現各種功能,此抽象類是表示位元組輸入流的所有類的超類。 繼承自InputStream 的流都是向程式中輸入資料的,且資料單位為位元組(8bit);
InputStream是輸入位元組資料用的類,所以InputStream類提供了3種過載的read方法.Inputstream類中的常用方法:
(1) public abstract int read( ):讀取一個byte的資料,返回值是高位補0的int型別值。若返回值=-1說明沒有讀取到任何位元組讀取工作結束。
(2) public int read(byte b[ ]):讀取b.length個位元組的資料放到b陣列中。返回值是讀取的位元組數。該方法實際上是呼叫下一個方法實現的
(3) public int read(byte b[ ], int off, int len):從輸入流中最多讀取len個位元組的資料,存放到偏移量為off的b陣列中。
(4) public int available( ):返回輸入流中可以讀取的位元組數。注意:若輸入阻塞,當前執行緒將被掛起,如果InputStream物件呼叫這個方法的話,它只會返回0,這個方法必須由繼承InputStream類的子類物件呼叫才有用,
(5) public long skip(long n):忽略輸入流中的n個位元組,返回值是實際忽略的位元組數, 跳過一些位元組來讀取
(6) public int close( ) :我們在使用完後,必須對我們開啟的流進行關閉.
- 1) FileInputStream把一個檔案作為InputStream,實現對檔案的讀取操作
- 2) ByteArrayInputStream:把記憶體中的一個緩衝區作為InputStream使用
- 3) StringBufferInputStream:把一個String物件作為InputStream
- 4) PipedInputStream:實現了pipe的概念,主要線上程中使用
- 5) SequenceInputStream:把多個InputStream合併為一個InputStream
2.OutputStream抽象類
OutputStream提供了3個write方法來做資料的輸出,這個是和InputStream是相對應的。
1. public void write(byte b[ ]):將引數b中的位元組寫到輸出流。
2. public void write(byte b[ ], int off, int len) :將引數b的從偏移量off開始的len個位元組寫到輸出流。
3. public abstract void write(int b) :先將int轉換為byte型別,把低位元組寫入到輸出流中。
4. public void flush( ) : 將資料緩衝區中資料全部輸出,並清空緩衝區。
5. public void close( ) : 關閉輸出流並釋放與流相關的系統資源。
- 1) ByteArrayOutputStream:把資訊存入記憶體中的一個緩衝區中
- 2) FileOutputStream:把資訊存入檔案中
- 3) PipedOutputStream:實現了pipe的概念,主要線上程中使用
- 4) SequenceOutputStream:把多個OutStream合併為一個
流結束的判斷:方法read()的返回值為-1時;readLine()的返回值為null時。
3. 檔案輸入流: FileInputStream類
FileInputStream可以使用read()方法一次讀入一個位元組,並以int型別返回,或者是使用read()方法時讀入至一個byte陣列,byte陣列的元素有多少個,就讀入多少個位元組。在將整個檔案讀取完成或寫入完畢的過程中,這麼一個byte陣列通常被當作緩衝區,因為這麼一個byte陣列通常扮演承接資料的中間角色。
作用:開啟檔案,從檔案讀資料到記憶體的類。
使用方法(1)
File fin=new File(“d:/abc.txt”);
FileInputStream in=new FileInputStream( fin);
使用方法(2)
FileInputStream in=new FileInputStream(“d: /abc.txt”);
程式舉例:將fos.dat程式的內容顯示在顯示器上
import java.io.FileInputStream;
import java.io.IOException;
public class FisDemo {
public static void main(String[] args) throws IOException{
FileInputStream fis= new FileInputStream("fos.dat");
int i = fis.read();
System.out.println(i);//97
byte[] buf = new byte[21];
int len = fis.read(buf);
String str = new String(buf,"UTF-8");
System.out.println(str);
fis.close();
}
}
4.檔案輸出流:FileOutputStream類
作用:用來處理以檔案作為資料輸出目的資料流,或者說是從記憶體區讀資料入檔案
FileOutputStream類用來處理以檔案作為資料輸出目的資料流。
建立一個檔案流物件有兩種方法:
方式1:
File f=new File (“d:/myjava/write.txt “);
FileOutputStream out= new FileOutputStream (f);
方式2:
FileOutputStream out=new FileOutputStream(“d:/myjava/write.txt “);
方式3:建構函式將 FileDescriptor()物件作為其引數。
FileDescriptor() fd=new FileDescriptor();
FileOutputStream f2=new FileOutputStream(fd);
方式4:建構函式將檔名作為其第一引數,將布林值作為第二引數。
FileOutputStream f=new FileOutputStream(“d:/abc.txt”,true);
注意: (1)檔案中寫資料時,若檔案已經存在,則覆蓋存在的檔案;
(2)的讀/寫操作結束時,應呼叫close方法關閉流。
程式舉例:使用鍵盤輸入一段文章,將文章儲存在檔案fos.dat中
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FosDemo {
public static void main(String[] args) throws IOException{
FileOutputStream fos= new FileOutputStream("write.txt");
fos.write(97);
String str = "天安門上太陽升";
byte[] buf = str.getBytes("UTF-8");
fos.write(buf);
fos.close();
}
}
5. FileInputStream流和FileOutputStream的應用
package day02;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo {
public static void main(String[] args) throws IOException{
FileInputStream fis= new FileInputStream("src.jpg");
FileOutputStream fos= new FileOutputStream("copy2.jpg");
byte[] buf = new byte[10240];
int len = -1;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
System.out.println("複製完畢");
fis.close();
fos.close();
}
}
6. 緩衝輸入輸出流 BufferedInputStream/ BufferedOutputStream
計算機訪問外部裝置非常耗時。訪問外存的頻率越高,造成CPU閒置的概率就越大。為了減少訪問外存的次數,應該在一次對外設的訪問中,讀寫更多的資料。為此,除了程式和流節點間交換資料必需的讀寫機制外,還應該增加緩衝機制。緩衝流就是每一個數據流分配一個緩衝區,一個緩衝區就是一個臨時儲存資料的記憶體。這樣可以減少訪問硬碟的次數,提高傳輸效率。
BufferedInputStream:當向緩衝流寫入資料時候,資料先寫到緩衝區,待緩衝區寫滿後,系統一次性將資料傳送給輸出裝置。
BufferedOutputStream :當從向緩衝流讀取資料時候,系統先從緩衝區讀出資料,待緩衝區為空時,系統再從輸入裝置讀取資料到緩衝區。
1)將檔案讀入記憶體:
將BufferedInputStream與FileInputStream相接
FileInputStream in=new FileInputStream( “file1.txt ” );
BufferedInputStream bin=new BufferedInputStream( in);
2)將記憶體寫入檔案:
將BufferedOutputStream與 FileOutputStream相接
FileOutputStreamout=new FileOutputStream(“file1.txt”);
BufferedOutputStream bin=new BufferedInputStream(out);
3)鍵盤輸入流讀到記憶體
將BufferedReader與標準的資料流相接
InputStreamReader sin=new InputStreamReader (System.in) ;
BufferedReader bin=new BufferedReader(sin);
例子:
BufferedOutputStream
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BosDemo {
public static void main(String[] args) throws IOException{
FileOutputStream fos= new FileOutputStream("bos.txt");
BufferedOutputStream bos= new BufferedOutputStream(fos);
String str = "偉大領袖毛主席";
byte[] buf = str.getBytes("UTF-8");
bos.write(buf);
/* 強制將當前緩衝流中的緩衝區中的資料全部寫出,無論緩衝區是否被裝滿*/
bos.flush();
bos.close();//close時,也會自動呼叫一次flush
}
}
BufferedInputStream/ BufferedOutputStream加速檔案拷貝
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo2 {
public static void main(String[] args)throws IOException {
FileInputStream fis= new FileInputStream("src.AVI");
BufferedInputStream bis= new BufferedInputStream(fis);
FileOutputStream fos= new FileOutputStream("copy2.AVI");
BufferedOutputStream bos= new BufferedOutputStream(fos);
int d = -1;
while ((d = bis.read()) != -1) {
bos.write(d);
}
System.out.println("複製完畢");
/* 關閉流時,只關閉最外層的高階流即可*/
bis.close();
bos.close();
}
}
7. 字元流Writer/Reader
Java中字元是採用Unicode標準,一個字元是16位,即一個字元使用兩個位元組來表示。為此,JAVA中引入了處理字元的流。
1. Reader抽象類
用於讀取字元流的抽象類。子類必須實現的方法只有 read(char[], int, int) 和 close()。但是,多數子類將重寫此處定義的一些方法,以提供更高的效率和/或其他功能。
1) FileReader :與FileInputStream對應
主要用來讀取字元檔案,使用預設的字元編碼,有三種建構函式:
(1)將檔名作為字串 :FileReader f=new FileReader(“c:/temp.txt”);
(2)建構函式將File物件作為其引數。
File f=new file(“c:/temp.txt”);
FileReader f1=new FileReader(f);
(3) 建構函式將FileDescriptor物件作為引數
FileDescriptor() fd=new FileDescriptor()
FileReader f2=new FileReader(fd);
2) CharArrayReader:與ByteArrayInputStream對應
3) StringReader : 與StringBufferInputStream對應
4) InputStreamReader
從輸入流讀取位元組,在將它們轉換成字元:Public inputstreamReader(inputstream is);
5) FilterReader: 允許過濾字元流 protected filterReader(Reader r);
6) BufferReader :接受Reader物件作為引數,並對其新增字元緩衝器,使用readline()方法可以讀取一行。 Public BufferReader(Reader r);
2. Writer抽象類
寫入字元流的抽象類。子類必須實現的方法僅有 write(char[], int, int)、flush() 和 close()。但是,多數子類將重寫此處定義的一些方法,以提供更高的效率和/或其他功能。 其子類如下:
3 .InputStream與Reader差別 OutputStream與Writer差別
InputStream和OutputStream類處理的是位元組流,資料流中的最小單位是位元組(8個bit)
Reader與Writer處理的是字元流,在處理字元流時涉及了字元編碼的轉換問題
import java.io.*;
public class EncodeTest {
private static void readBuff(byte [] buff) throws IOException {
ByteArrayInputStream in =new ByteArrayInputStream(buff);
int data;
while((data=in.read())!=-1) System.out.print(data+" ");
System.out.println(); in.close(); }
public static void main(String args[]) throws IOException {
System.out.println("記憶體中採用unicode字元編碼:" );
char c='好';
int lowBit=c&0xFF; int highBit=(c&0xFF00)>>8;
System.out.println(""+lowBit+" "+highBit);
String s="好";
System.out.println("本地作業系統預設字元編碼:");
readBuff(s.getBytes());
System.out.println("採用GBK字元編碼:");
readBuff(s.getBytes("GBK"));
System.out.println("採用UTF-8字元編碼:");
readBuff(s.getBytes("UTF-8")); }
}
Reader類能夠將輸入流中採用其他編碼型別的字元轉換為Unicode字元,然後在記憶體中為其分配記憶體
Writer類能夠將記憶體中的Unicode字元轉換為其他編碼型別的字元,再寫到輸出流中。
BufferedReader緩衝字元輸入流可以以行為單位讀取字串
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class BufferReaderDemo {
public static void main(String[] args) throws IOException{
FileInputStream fis= new FileInputStream("pw.txt");
InputStreamReader isr= new InputStreamReader(fis,"UTF-8");
BufferedReader br= new BufferedReader(isr);
String str = null;
while((str=br.readLine())!=null){
System.out.println(str);
}
br.close();
}
}
InputStreamReader字元輸入流用於讀取字元資料的流
package day03;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class ISRDemo {
public static void main(String[] args)throws IOException{
FileInputStream fis= new FileInputStream("osw.txt");
InputStreamReader isr= new InputStreamReader(fis,"UTF-8");
int d = -1;
while((d = isr.read())!=-1){
char c = (char)d;
System.out.print(c);
}
isr.close();
}
}
OutStream
FileInputStream和FileOutputStream
FileInputStream
import java.io.FileInputStream;
import java.io.IOException;
/**
* FileInputStream 節點流用於從檔案中讀取位元組的流
*/
public class FisDemo {
public static void main(String[] args) throws IOException{
FileInputStream fis= new FileInputStream("fos.dat");
int i = fis.read();
System.out.println(i);//97
byte[] buf = new byte[21];
int len = fis.read(buf);
String str = new String(buf,"UTF-8");
System.out.println(str);
fis.close();
}
}