整理 JAVA中的IO流 (字符流和字節流兩個大類)
阿新 • • 發佈:2019-01-10
sem tint io流 return char 如果 建立 err 管道流 java中的io流分為兩類,字符和字節:
- OutputStream和InputStream字節流的父類,抽象。OutputStream有兩個提供了實現的接口closable和flushable。
- Writer和Reader字符流的父類,抽象。
實際上在流的操作中,底層與文件進行讀寫的都是字節流,因為即使是字符流的對象,其最終實現讀寫的也是用的字節流。
- 操作文件的字節子類FileOutputStream和FileInputStream。
記住,這裏面寫出和讀入的都是字節。
class useByteStream { /** * 使用文件輸出字節流 * */ public static void testFileOutputStream() { OutputStream out = null; try { File f = new File(".\\log\\test.txt"); //out = new FileOutputStream(f); out = new FileOutputStream(f,true); //追加方式記錄到文件 String str = "Hello World!!!"; byte b[] = str.getBytes(); out.write(b); out.close(); } catch(FileNotFoundException e) { } catch(IOException e) { } } /** * 使用文件輸入字節流 */ public static void testFileInputStream() { InputStream out = null; try { File f = new File(".\\log\\test.txt"); out = new FileInputStream(f); String str = "Hello World!!!"; byte b[] = new byte[1000]; int len = out.read(b); System.out.println(new String(b,0, len) ); out.close(); } catch(FileNotFoundException e) { } catch(IOException e) { } } };
- 操作文件的字符子類FileWriter和FileReader
class useCharStream { /** * 使用文件字符輸出流 */ public static void testFileWriter() { Writer w = null; try { File f = new File(".\\log\\test2.txt"); w = new FileWriter(f,true); //追加方式 w.write("hello world\r\n"); w.close(); } catch(FileNotFoundException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } /** * 使用文件字符輸入流 */ public static void testFileReader() { Reader w = null; try { File f = new File(".\\log\\test2.txt"); w = new FileReader(f); char c[] = new char[1024]; w.read(c); System.out.println(c); w.close(); } catch(FileNotFoundException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } };
-
兩個轉換類,OutputStreamWriter,負責將寫入字符流轉為字節流,InputStreamReader,負責讀取字節流轉為字符流。
FileWriter的直接父類是OutputStreamWriter,並非Writer。
FileReader的直接父類是InputStreamReader,並非Reader。
因此,最終寫入文件和從文件讀出的都是字節流。以上都是基於文件流操作,接下來是基於內存操作流,如果只是寫業務代碼應該很少會用到。
- 內存操作流
ByteArrayInputStream\ByteArrayOutputStream。
class useMemoryStream { /** * 使用內存操作流,字節 */ public static void testByteArray() { String str = "Hello world"; ByteArrayInputStream bis = null; ByteArrayOutputStream bos = null; bis = new ByteArrayInputStream(str.getBytes()); bos = new ByteArrayOutputStream(); int temp =0; while((temp=bis.read())!=-1) { char c = (char)temp; bos.write(Character.toUpperCase(c)); } String newStr = bos.toString(); try { bis.close(); bos.close(); } catch(IOException e) { e.printStackTrace(); } System.out.println(newStr); } };
- 另外,管道流可以實現兩個線程之間的通信。
PipedInputStream 和 PipedOutputStream。
PipedOutputStream通過connect方法與PipedInputStream建立連接,後續PipedOutputStream.write的內容,就會PipedInputStream.read方法讀取
class Send implements Runnable
{
private PipedOutputStream pos = null;
public Send()
{
this.pos = new PipedOutputStream();
}
public void run()
{
String str = "Hello world!!!";
try
{
try
{
Thread.sleep(2000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
this.pos.write(str.getBytes());
System.out.println("thread:"+Thread.currentThread().getId()+",Send string:"+str);
}
catch(IOException e)
{
e.printStackTrace();
}
try
{
this.pos.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public PipedOutputStream getPos()
{
return this.pos;
}
};
class Receive implements Runnable
{
private PipedInputStream pis = null;
public Receive()
{
this.pis = new PipedInputStream();
}
public void run()
{
byte b[] = new byte[1024];
int len =0;
try
{
len = this.pis.read(b); //阻塞方式
}
catch(IOException e)
{
e.printStackTrace();
}
try
{
pis.close();
}
catch(IOException e)
{
e.printStackTrace();
}
System.out.println("thread:"+Thread.currentThread().getId()+",receive:"+new String(b,0,len));
}
public PipedInputStream getPis()
{
return this.pis;
}
};
class pipedTest
{
public void pipedStream()
{
Send s = new Send();
Receive r = new Receive();
try {
s.getPos().connect(r.getPis());
}
catch(IOException e)
{
e.printStackTrace();
}
new Thread(r).start();
new Thread(s).start();
}
};
以上都是無緩存的,考慮到一般場景下,提高使用性能,最好使用有緩存的字符流:BufferedReader和BufferedWriter。
-
BufferedReader
只能接受輸入為字符流,不能為字節流。所以有時候會使用InputStreamReader來轉換字節流給字符流使用。還有BufferedWriterclass useBuffer { public static void testBufferReader() { BufferedReader buf = null; //此處用到了字節流轉字符流的類InputStreamReader,這是因為BufferedReader只能接收字符流 buf = new BufferedReader(new InputStreamReader(System.in)); String str =null; try { str = buf.readLine(); } catch(IOException e) { e.printStackTrace(); } System.out.println("輸出的內容為:"+str); } public static void testBufferWriter() { File f = new File(".\\log\\test2.txt"); try { //默認緩沖區大小 8K 可以通過 new BufferedWriter(new FileWriter(f),1024);指定大小為1K BufferedWriter out =new BufferedWriter(new FileWriter(f)); out.write("123321123355555", 0, 10); out.write("\r\n"); out.close(); } catch (IOException e) { e.printStackTrace(); } } };
-
SCanner類,輸入數據類。
使用方法和BufferedReader類類似,並且方便驗證數據類型。class useScan { public static void testScan() { Scanner scan = new Scanner(System.in); //以回車作為輸入的結束符號,否則默認是空格 scan.useDelimiter("\r\n"); if(scan.hasNextInt()==true) { int str = scan.nextInt(); System.out.println("int "+str); } else { String str = scan.next(); System.out.println("string "+str); } } };
scan.hasNext
支持正則表達式。比如hasNext("^\\d{4}-\\d{2}-\\d{2}$")
就是日期格式yyyy-MM-dd的正則表達式,通過next("^\\d{4}-\\d{2}-\\d{2}$")
。
整理 JAVA中的IO流 (字符流和字節流兩個大類)