IO流:用于處理設(shè)備上的數(shù)據(jù),即:InputStream在孝,OutputStream
IO流的具體分類:
1,根據(jù)處理的數(shù)據(jù)類型不同分為:字節(jié)流與字符流
2,根據(jù)流的方向不同分為:輸出流與輸入流
字符流的由來(lái):
因?yàn)槲募木幋a不同蕊唐,而有了對(duì)字符進(jìn)行高效操作的字符流對(duì)象
原理:其實(shí)就是基于字節(jié)流讀取數(shù)據(jù)時(shí),去查了 指定編碼表
字節(jié)流與字符流的區(qū)別
1烁设,字節(jié)流讀取的 時(shí)候替梨,讀取一個(gè)字節(jié)就返回一個(gè)字節(jié),
字符流使用了字節(jié)流讀取到一個(gè)或多個(gè)字節(jié)流時(shí)署尤,先去查指定的編碼 表耙替,將查到的字符返回
2,字節(jié)流能夠讀取所有的類型數(shù)據(jù)曹体,而字符流只能處理字符類型
一.File
- 目錄列表
假設(shè)我們想查看目錄列表俗扇,可使用list()方法查看File對(duì)象下所有的目錄,但是如果想查看類型為.java類的文件箕别,那么我們就使用“目錄過(guò)濾器”
package File;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;
public class DirList {
public static void main(String[] args) {
File file = new File(".");
String[] list;
list = file.list(new DirFilter(".*"));
Arrays.sort(list,String.CASE_INSENSITIVE_ORDER);
for(String str : list){
System.out.println(str);
}
}
}
package File;
import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.Pattern;
public class DirFilter implements FilenameFilter{
private Pattern pattern;
public DirFilter(String filenName){
pattern = Pattern.compile(filenName);
}
@Override
public boolean accept(File dir, String name) {
return pattern.matcher(name).matches();
}
}
DirFilter 這個(gè)類存在的原因就是把a(bǔ)ccept() 方法提供給 list() 使用铜幽,使list()可以回調(diào)accept() 進(jìn)而決定哪些文件包含在列表里 這就是策略模式的體現(xiàn)
list()方法會(huì)為此目錄下的所有的方法都調(diào)用accept()方法,來(lái)判斷此文件是否在內(nèi)
- 目錄的檢查及創(chuàng)建
File 類不僅僅只代表存在的目錄串稀,也可以用File對(duì)象來(lái)創(chuàng)建不存在的目錄除抛,也可以用File查看文件的各種特性
輸入流 InputStream
每一種數(shù)據(jù)源都有相應(yīng)的InputStream子類,因?yàn)镮nputStream是個(gè)處于頂層的類母截,用來(lái)處理各種數(shù)據(jù)源的類都繼承了InputStream類到忽,我們來(lái)看看這些類:
ByteArrayInputStream:處理字節(jié)數(shù)組的類,允許將內(nèi)存的緩沖區(qū)當(dāng)做InputStream使用清寇。
StringBufferInputStream:將String轉(zhuǎn)換成InputStream喘漏,內(nèi)部實(shí)現(xiàn)用的是StringBuffer。
FileInputStream:從文件中讀取數(shù)據(jù)华烟。
PipedInputStream:用于從管道中讀取數(shù)據(jù)翩迈。
SequenceInputStream:將多個(gè)流對(duì)象轉(zhuǎn)化成一個(gè)InputStream。
FilterInputStream:裝飾器類盔夜,為其它InputStream類提供功能负饲。
- 讀取文件內(nèi)容
package InputStream;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedInputFile2 {
public static String read(String fileName) throws IOException{
BufferedReader br = new BufferedReader(new FileReader(fileName));
StringBuilder sb = new StringBuilder();
String s = "";
while((s = br.readLine())!=null){
sb.append(s+"\n");
}
if(br!=null){
br.close();
}
return sb.toString();
}
public static void main(String[] args) {
try {
System.out.println(read("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
* DataInputStream類
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class DataOutputStreamDemo{
public static void main(String[] args) throws IOException{
File file = new File("d:" + File.separator +"hello.txt");
DataInputStream input = new DataInputStream(new FileInputStream(file));
char[] ch = new char[10];
int count = 0;
char temp;
while((temp = input.readChar()) != 'C'){
ch[count++] = temp;
}
System.out.println(ch);
}
}
輸出流 OutputStream
OutputStream 是所有的輸出字節(jié)流的父類堤魁,它是一個(gè)抽象類。
ByteArrayOutputStream返十、FileOutputStream是兩種基本的介質(zhì)流妥泉,它們分別向Byte 數(shù)組、和本地文件中寫入數(shù)據(jù)吧慢。PipedOutputStream 是向與其它線程共用的管道中寫入數(shù)據(jù)涛漂,
ObjectOutputStream 和所有FilterOutputStream的子類都是裝飾流。具體例子跟InputStream是對(duì)應(yīng)的检诗。
- 文件復(fù)制
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
if(args.length!=2){
System.out.println("命令行參數(shù)輸入有誤匈仗,請(qǐng)檢查");
System.exit(1);
}
File file1=new File(args[0]);
File file2=new File(args[1]);
if(!file1.exists()){
System.out.println("被復(fù)制的文件不存在");
System.exit(1);
}
InputStream input=new FileInputStream(file1);
OutputStream output=new FileOutputStream(file2);
if((input!=null)&&(output!=null)){
int temp=0;
while((temp=input.read())!=(-1)){
output.write(temp);
}
}
input.close();
output.close();
}
}
* DataOutputStream
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamDemo{
public static void main(String[] args) throws IOException{
File file = new File("d:" + File.separator +"hello.txt");
char[] ch = { 'A', 'B', 'C' };
DataOutputStream out = null;
out = new DataOutputStream(new FileOutputStream(file));
for(char temp : ch){
out.writeChar(temp);
}
out.close();
}
}
添加屬性和有用的接口
java IO 類庫(kù)需要多種不同功能的組合,這正是使用裝飾器模式的理由所在
這也是java IO類庫(kù)里存在filter(過(guò)濾器)的原因所在逢慌,抽象類filter是所有裝飾器的基類悠轩。裝飾器類必須和它所裝飾的類具有相同的接口,但它也可以擴(kuò)展
裝飾器在給我們提供許多靈活性的時(shí)候也給我們帶來(lái)了復(fù)雜性攻泼,我們必須創(chuàng)建許多類 才能得到我們需要的單個(gè)的IO對(duì)象
Reader 和 Writer
Reader 是所有的輸入字符流的父類火架,它是一個(gè)抽象類。
Writer 是所有的輸出字符流的父類忙菠,它是一個(gè)抽象類
設(shè)計(jì)Reader和Writer主要是為了國(guó)際化何鸡,老的IO流僅支持8位的字節(jié)流,不能很好的支持16位的牛欢,所以添加Reader和Writer就是為了所有的IO操作中能很好地 支持Unicode
InputStreamReader 可以把 InputStream 轉(zhuǎn)化為 Reader
OutoutStreamWrite 可以把OutputStream轉(zhuǎn)化為Write
- 從文件中讀取數(shù)據(jù)
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
char[] ch=new char[100];
Reader read=new FileReader(f);
int temp=0;
int count=0;
while((temp=read.read())!=(-1)){
ch[count++]=(char)temp;
}
read.close();
System.out.println("內(nèi)容為"+new String(ch,0,count));
}
}
- BufferedReader
注意:BufferedReader只能接受字符流的緩沖區(qū)骡男,因?yàn)槊恳粋€(gè)中文需要占據(jù)兩個(gè)字節(jié),所以需要將System.in這個(gè)字節(jié)輸入流變?yōu)樽址斎肓?/li>
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BufferedReaderDemo{
public static void main(String[] args){
BufferedReader buf = new BufferedReader(
newInputStreamReader(System.in));
String str = null;
System.out.println("請(qǐng)輸入內(nèi)容");
try{
str = buf.readLine();
}catch(IOException e){
e.printStackTrace();
}
System.out.println("你輸入的內(nèi)容是:" + str);
}
}
字節(jié)流與字符流的轉(zhuǎn)換
InputStreamReader:字節(jié)到字符的橋梁
OutputStreamWriter:字符到字節(jié)的橋梁
這兩個(gè)流對(duì)象是字符體系中的成員傍睹,它們有轉(zhuǎn)換作用隔盛,本身又是字符流,所以在構(gòu)造的時(shí)候需要傳入字節(jié)流對(duì)象進(jìn)來(lái)拾稳。
//將字節(jié)輸出流轉(zhuǎn)化為字符輸出流
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "d:"+File.separator+"hello.txt";
File file=new File(fileName);
Writer out=new OutputStreamWriter(new FileOutputStream(file));
out.write("hello");
out.close();
}
//將字節(jié)輸入流變?yōu)樽址斎肓?import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "d:"+File.separator+"hello.txt";
File file=new File(fileName);
Reader read=new InputStreamReader(new FileInputStream(file));
char[] b=new char[100];
int len=read.read(b);
System.out.println(new String(b,0,len));
read.close();
}
}
標(biāo)準(zhǔn)IO流
標(biāo)準(zhǔn)IO模型吮炕,java提供了System.in,System.out,System.err
其中System.err和System.out都已報(bào)裝成了PrintStream 但是System.in
卻是一個(gè)未被報(bào)裝過(guò)的InputStream,所以在System.in之前要對(duì)其進(jìn)行包裝
package OutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Echo {
public static void main(String[] args) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String c = "";
try {
while((c=reader.readLine())!=null&&c.length()!=0){
System.out.println(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 將System.out 轉(zhuǎn)換為PrintWrite
System.out 是一個(gè)PrintStream 而PrintStream 是一個(gè)OutputStream 而PrintWrite有一個(gè)可以接受OutputStream 參數(shù)的構(gòu)造器
PrintWriter out = new PrintWriter(System.out,true);
out.println("hello ");
壓縮
- 利用GZIP進(jìn)行簡(jiǎn)單的壓縮
GZIP接口非常的簡(jiǎn)單,如果要對(duì)單個(gè)的數(shù)據(jù)流進(jìn)行壓縮访得,GZIP就很合適
package zip;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GIZPcomress {
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(
new FileReader(
"E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
BufferedOutputStream os = new BufferedOutputStream(
new GZIPOutputStream(
new FileOutputStream(
"E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile4.java")));
System.out.println("write file");
int c;
while ((c = br.read()) != -1) {
os.write(c);
}
br.close();
os.close();
System.out.println("read file");
BufferedReader br2 = new BufferedReader(
new InputStreamReader(
new GZIPInputStream(
new FileInputStream(
"E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile4.java"))));
String s = "";
while ((s = br2.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 用zip 進(jìn)行壓縮 解壓
package zip;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
//壓縮
public class ZipCompress {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile5.zip");
CheckedOutputStream cs = new CheckedOutputStream(fos, new Adler32());
ZipOutputStream zs = new ZipOutputStream(fos);
BufferedOutputStream bos = new BufferedOutputStream(zs);
zs.setComment("this is zip file");
System.out.println("開(kāi)始?jí)嚎s");
BufferedReader reader = new BufferedReader(new FileReader("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
zs.putNextEntry(new ZipEntry("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
int s = 0;
while((s=reader.read())!=-1){
bos.write(s);
}
bos.close();
System.out.println("checkNum:"+cs.getChecksum().getValue());
System.out.println("開(kāi)始讀文件");
FileInputStream fis = new FileInputStream("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile5.zip");
CheckedInputStream cis = new CheckedInputStream(fis, new Adler32());
ZipInputStream zi = new ZipInputStream(fis);
BufferedInputStream bis = new BufferedInputStream(zi);
ZipEntry zn = null;
while((zn = zi.getNextEntry())!=null){
System.out.println("this file:"+zn);
int n = 0;
while((n = bis.read())!=-1){
System.out.write(n);
}
}
System.out.println("checkNum:"+cs.getChecksum().getValue());
} catch (Exception e) {
e.printStackTrace();
}
}
}
序列化
Java平臺(tái)允許我們?cè)趦?nèi)存中創(chuàng)建可復(fù)用的Java對(duì)象龙亲,但一般情況下,只有當(dāng)JVM處于運(yùn)行時(shí)悍抑,這些對(duì)象才可能存在鳄炉,即,這些對(duì)象的生命周期不會(huì)比JVM的生命周期更長(zhǎng)传趾。但在現(xiàn)實(shí)應(yīng)用中迎膜,就可能要求在JVM停止運(yùn)行之后能夠保存(持久化)指定的對(duì)象泥技,并在將來(lái)重新讀取被保存的對(duì)象浆兰。Java對(duì)象序列化就能夠幫助我們實(shí)現(xiàn)該功能磕仅。java 的對(duì)象的序列化將那些實(shí)現(xiàn)了Serializable接口的對(duì)象轉(zhuǎn)換成字節(jié)序列,并且能夠在以后將字節(jié)序列恢復(fù)為原來(lái)的對(duì)象
什么時(shí)候用序列化:
a)當(dāng)你想把的內(nèi)存中的對(duì)象保存到一個(gè)文件中或者數(shù)據(jù)庫(kù)中時(shí)候;
b)當(dāng)你想用套接字在網(wǎng)絡(luò)上傳送對(duì)象的時(shí)候;
c)當(dāng)你想通過(guò)RMI傳輸對(duì)象的時(shí)候纱兑;
package Serializable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class A {
private static int i = 10;
private transient static String s = "java";
public static void main(String[] args) {
try {
User user = new User();
user.setSex('男');
user.setUsername("小李");
user.setUserpass("123");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.out"));
oos.writeObject(user);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.out"));
User user2 = (User)ois.readObject();
//String ss = ois.readUTF();
//System.out.println(ss);
System.out.println(user2.getUsername());
System.out.println(user2.getSex());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
- 序列化的控制
有時(shí)候我們不想整個(gè)對(duì)象都序列化讼渊,只需要對(duì)象的一部分序列化,此時(shí)就應(yīng)該用到:Externalizable
Externalizable 是一個(gè)接口 需要實(shí)現(xiàn)兩個(gè)方法writeExternal(),readExternal()
package Serializable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class Bilp1 implements Externalizable{
private User user;
public Bilp1(){
System.out.println("Bilp1()");
}
public Bilp1(User user){
this.user = user;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// TODO Auto-generated method stub
//out.writeObject(user);
System.out.println("writeExternal()");
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
// TODO Auto-generated method stub
System.out.println("readExternal()");
}
}
- transient關(guān)鍵字
當(dāng)某個(gè)字段被聲明為transient后肚医,默認(rèn)序列化機(jī)制就會(huì)忽略該字段。此處將User類中的username字段聲明為transient
private transient String username;