io流
1.按照操作數據類型分爲字節流和字符流
2.按流向分爲輸出流和輸入流
字節流的抽象基類
InputStream OutputStream
字符流的抽象基類
Reader Writer
常用io字符流類
1.
FileWriter fw = new FileWriter();//自動創建文件,會拋出異常,如果文件存在會覆蓋
write(String)方法向中寫入數據,也會拋出異常
fflush()方法刷新流,將數據寫入對象中,
或者直接用close()方法關閉流,也有刷新作用。
FileWriter fw = new FileWriter(“”,true);第二個參數,表示接下來的操作都是續寫文件
write方法常用傳入參數 (String) (buf,0,num)
1.1
處理IO異常標準格式
FileWriter fw = null;
try
{
fw = new FileWriter();// 如果在try中定義,作用域會變小,所以在外部定義,然後初始 化
fw.write();
}
catch(IOException ex)
{
System.out.println(ex.toString());
}
finally
{
try
{
if(fw!=null)//如果上面文件創建失敗就不用關閉了
{
fw.close();
}
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
2.
FileReader fr = new FileReader();//如果文件不存在就會報錯
fr.read();//每次讀取一個文件字符,返回字符的int值,如果文件 結束返回-1,所以返回值不等於-1可以作爲循環讀取整個文件的條件 !一個程序中,每次自動接着上次的位置向下讀
read(buf) read方法傳入一個字符數組參數,則文件裏的數組大小的內容會讀入到數組中並返回實際讀入的字符個數,讀到末尾也是返回-1
read方法是不用刷新的
根據這個特性可寫成新的循環條件
while((num = fr.read(buf))!=-1)
{
System.out.print(new String(buf,0,num));//這裏最好不要用println可能會形成不想要的換行
}
如果可讀取字符個數小於數組長度,則read方法會把剩下字符讀完,還是返回讀入字符個數,下次再讀取時,纔會返回-1.
這種一次讀取多個字符的read方法比較常用。
運用上面的知識可以寫一個複製文件的例子
public class Demo {
public static void main(String[] args) {
// TODO Auto-generated method stub
FileReader fr = null;
FileWriter fw = null;
try
{
fr = new FileReader("C:\\Users\\dellpc\\Desktop\\buf.txt");
fw = new FileWriter("F:\\test.txt");
char[] buf = new char[1024];
int num = 0;
while((num = fr.read(buf))!=-1)
{
fw.write(buf,0,num);
}
}
catch (IOException x)
{
System.out.println(x.toString());
}
finally
{
if(fr!=null )
{
try
{
fr.close();
}
catch(IOException x)
{
System.out.println(x.toString());
}
}
if(fw!=null)
{
try
{
fw.close();
}
catch(IOException x)
{
System.out.println(x.toString());
}
}
}
}
}
3.
BufferedWriter //緩衝區寫入
需要封裝流對象 BufferedWriter fw = new BufferedWriter(new FileWriter());
使用方法和FileWriter基本相同 每次寫入後要刷新,fflush();
fw.newLine();開啓新的一行,緩衝區纔有的方法,跨平臺方法,和readLine一樣緩衝區特有方法
關閉緩衝區fw.close()其實就是關閉流對象
BufferedReader //緩衝區讀取
也需要封裝流對象 BufferedReader fr = new BufferedReader(new FileReader());
使用方法和FileReader基本相同,不過有一個特別的方法readLine();
一次可以讀取文件的一行,返回讀取到的字符串,讀到流(文件)的末尾就返回null,但是返回的字符串中不包括換行符,用print打印出來就可以知道
readLine()讀取文件例子
public static void main(String[] args) throws Exception{
BufferedReader fr = new BufferedReader(new FileReader("C:\\Users\\dellpc\\Desktop\\buf.txt"));
String line = null;
int num = 0;
char[] buf = new char[1024];
while((num = fr.read(buf))!=-1)
{
System.out.print(new String(buf,0,num));
}
fr.close();
}
}
readLine()是讀取數據最爲方便的一種方法
爲什麼加入緩衝技術,是爲了更有效率,其是緩衝技術就是在普通的操作數據的基礎上加入了數組,將一部分數據先放到數組中,再整體操作。
運用緩衝區技術實現文件複製
public class Demo {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
BufferedReader fr = new BufferedReader(new FileReader("C:\\Users\\dellpc\\Desktop\\buf.txt"));
BufferedWriter fw = new BufferedWriter(new FileWriter("F:\\test.txt"));
String str = null;
while((str = fr.readLine())!=null)
{
fw.write(str);
fw.newLine();
fw.flush();
}
fw.close();
}
}
用到newLine()就是因爲readLine()不返回一行的換行符導致的。
常用io字節流
1.
FileOutputStream
1.1使用方法
FileOutputStream fos = new FileOutputStream(“”);
write(char[]buf)方法,常用的傳入參數是二進制數組,我們想傳入字符串時,可以調用字符串的getByte()方法
字符流類內部其實使用的也是字節流,先把字符存到二進制數組中,通過刷新flush()方法完成寫入,所以直接用字節流類write()方法時,不需要flush()刷新
close()方法
2.
FileInputStream
2.1使用方法
FileInputStream fis = new FileInputStream(“”);
read方法和BufferedReader一樣,傳入數組當參數時要傳入字節數組byte[];
2.2InputStream字節流的特殊方法
available(),獲取數據大小,返回整數值,如果用FileInputStream打開一個英文文本文件,可以先用available()方法獲取文件大小,這是就可以申請一個大小剛好的二進制數組byte[] buf = new byte[fis.available()];就不用用read方法循環讀取了。直接讀取一次就是整個文本。
(byte[]數組一個元素佔一字節即8bit,這也是文本中一個英文字符所佔空間大小)
2.3字節流複製文件的例子
public class Demo {
public static void main(String args[]) throws Exception
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
fos = new FileOutputStream(“F:\333.xlsx”);
fis = new FileInputStream(“F:\15003401.xlsx”);
byte[] buf = new byte[17496];
int len =0;
int num = fis.available();
System.out.println(num);
while((len = fis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
}
catch (Exception x)
{
System.out.println(x.toString());
}
finally
{
if(fos!=null)
{
try
{
fos.close();
}
catch(Exception x)
{
}
}
if(fis!=null)
{
try
{
fis.close();
}
catch(Exception x)
{
}
}
}
}
}
3.BufferedInputStream
字節流緩衝區
4.BufferedOutputStream
番外
1.自定義字節流讀取鍵盤輸入
class MyBufferedInputStream
{
private InputStream in;
private byte[] buf = new byte[1024];
private int pos =0,count = 0;
MyBufferedInputStream(InputStream in)
{
this.in = in;
}
public int myRead() throws Exception//一次讀入一個字節從緩衝區
{
if(count == 0)
{
count = in.read(buf);
if(count<0)
{
return -1;
}
pos = 0;
byte b = buf[pos];
count--;
pos++;
return b&255;
}
else if(count>0)
{
byte b = buf[pos];
count--;
pos++;
return b&255;
}
return -1;
}
public void myClose() throws Exception
{
in.close();
}
}
public class Demo {
public static void main(String args[]) throws Exception
{
InputStream in = System.in;
StringBuilder sb = new StringBuilder();
while(true)
{
int ch = in.read();
if(ch=='\r')
{
continue;
}
if(ch == '\n')
{
String s = sb.toString();
if("over".equals(s))
{
break;
}
else
{
System.out.println(s);
sb.delete(0,sb.length());
}
}
else
{
sb.append((char)ch);
}
}
}
}
鍵盤錄入不能在程序裏實現結束,需要手動按ctrl+c才能結束。字節流read方法返回的是一字節二進制的整數形式,因爲如果返回byte形式8個二進制就等於-1,和結束標誌衝突了,返回整數形式時也需要一點修改,只保留最低8位,所以和255進行且&運算。
5.字節轉換流
InputStreamReader = new InputStreamReader(new InputStream())
OutputStreamWriter = new OutputStream(new OutputStream());
這樣就可以調用一些字符流方法
還可以進一步封裝成BufferedReader與BufferedWriter方法,比如readLine和newLine
5.1常用的鍵盤錄入方法
public class Demo {
public static void main(String args[]) throws Exception
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while((line = bufr.readLine())!=null)
{
//System.out.println(line);
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
bufr.close();
}
}
如果用System.in封裝的字節流只能一個一個讀取.用上文的bufr單獨去鍵盤錄入更爲方便,一次能讀取一行。
番外
流的操作很靈活,但是流的對象很多,要靈活運用流,就要
1.明確源和目的
比如要把一個文本打印到控制檯上,用到轉化流的話,可以這樣定義流的變量
BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\Users\\dellpc\\Desktop\\buf.txt")));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
而如果想把鍵盤錄入內容寫到文本里的時候可以這樣
BufferedReader bufr = new BufferedReader(System.in);
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new InputStreamReader(new FileInputStream("C:\\Users\\dellpc\\Desktop\\buf.txt"))));
2.明確操作對象
是不是純文本?
是:字符流
不是:字節流.
3.體系明確後,明確具體操作對象
通過設備來進行區分
原設備:內存,硬盤(文件),鍵盤
目的設備:內存,硬盤(文件),控制檯