java-IO流

-94dc-b5cebca12fcb.jpg[/img]

I/O:站在程序的角度看流!(程序员)

1.流:完成当前程序和外设(网络,文件,其他程序)之间的数据交换
我们可以认为在外设(网络,文件,其他程序)上面有两个管道,这两个管道可用于程序和外设之间的数据交换

java-IO流_第1张图片

2.流的分类:
按照流的流向:
如上图:所有编号为奇数的流都是可以把外设中的数据输入到程序中,我们称为输入流
所有编号为偶数的流都是可以把程序中的数据输出到外设中,我们称之为输出流
按照流所处理的数据类型:字节流和字符流;
只能用于处理(读取/写入)字节流---我们称之为字节流
只能用于处理(读取/写入)字符(Unicode码)的流—我们称之为字符流
按照处理方式:节点流(低级流)和处理流(高级流)
从外设转换直接获取的流都是节点流;
对节点流进行封装,对其处理数据的方式进行改变,这个封装后的流我们称为处理流;

java-IO流_第2张图片
java-IO流_第3张图片
java-IO流_第4张图片
java-IO流_第5张图片

3.Input/OutStream流的子类方法:

//控制台输出
InputStream is=System.in;
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
System.out.println("请输出源文件目录:");
String s=br.readLine();
System.out.println("请输出目标文件目录:");
String s1=br.readLine();

FileIn/OutputStream:
FileOutputStream fos=new FileOutputStream(f);
// byte[] b="gjsajsahdk".getBytes();
// fos.write(b);

//int read():c从此输入流中读取一个字节
//如果读取到了字节则返回字节的ascii码,如果达到流的末尾(没有读取到数据)返回-1
//
FileInputStream fis=new FileInputStream(f);
//int read[byte[] b] :从流中读取数据,将读取到的数据存放到字节数组中
//如果字节数组的长度大于等于文件中字节个数,会一次性的将文件中的数据全部读取
//如果字节数组的长度小于文件中字节的个数,那么每一次读取都会将数组装满
//如果读取到了数据,则返回读取到得字节个数
//如果已经到达文件末尾则返回-1

//int read[byte[] b,int off,int len)
//从此输入流中将最多len个字节的数据读入一个byte数组中,从索引off开始存放
byte[] bu=new byte[20];
fis.read(bu, 3, 5);//通过fis从文件中读取到5个字符,放在bu中从索引为3的元素开始存放
System.out.write(bu);

//定义一个字节数组存放从流中读取到得文件中的数据
//通过流调用read()方法,将文件中的数据读取到数组中
// byte[] b=new byte[20];
// int j=fis.read(b);
// System.out.write(b,0,j);
// byte[] b=new byte[2];
// int i;
// while((i=fis.read(b))!=-1){
// String s=new String(b,0,i);
// System.out.println(s);
// System.out.write(b, 0, i);
// }
****************************************************************
FileInputStream fis=new FileInputStream(f);
byte[] b=new byte[2];
//流在当前位置还可以向读取到得字节数
int m=fis.available();
System.out.println(m);
int i=fis.read(b);
System.out.write(b);
//让文件指针向前/向后跳动指定字节数
fis.skip(-1);

System.out.println();
m=fis.available();
System.out.println(m);
i=fis.read(b);
System.out.write(b);
FilterIn/OutputStream(高级流):
子类---DataInputStream
//DataOutputStream :可以将程序中不同类型的数据写入到文件中
//DataInputStream 可以从数据源(外设)读入带有数据类型的数据(前提:外设存在带有数据类型的数据)

try {
//通过fos可以将数据写入文件
//通过dos也可以将数据写到文件,并且dos可以将带有类型的数据写到文件
FileOutputStream  fos = new FileOutputStream("D:/t.txt");
DataOutputStream dos=new DataOutputStream(fos);
dos.writeInt(123);
dos.writeBoolean(false);
dos.writeDouble(3.141592653);
dos.flush();
//对数据库流来说先关低级流,再关高级流
//对本地文件流反之---压缩文件实例!
fos.close();
dos.close();

FileInputStream fis=new FileInputStream("D:/t.txt");
DataInputStream dis=new DataInputStream(fis);

boolean b=dis.readBoolean();
System.out.println(b);

int i=dis.readInt();
System.out.println(i);

// double d=dis.readDouble();
// System.out.println(d);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
BufferedIn/OutputStream类:
BufferedOutputStream:
byte[] b={97,98,99,100,101,102,103};
FileOutputStream fos=new FileOutputStream("D:/t.txt");
// fos.write(b);
//创建一个BufferedOutputStream对象--带有缓冲区的输出流
//当执行write方法时候把数据写入缓冲区,当执行flush方法时候才把数据写入文件中
//FileOutputStream可以直接把数据写入文件
BufferedOutputStream bos=new BufferedOutputStream(fos);
bos.write(b);
bos.flush();
LineNumberInputStream类:可以设置/获取当前的行号!


PrintStream类:
//对于低级输出流而言--只有最基本的write方法可以用来向外设写入数据
//参数类型比较单一(只能是字节,字节数组)
try {
FileOutputStream fos=new FileOutputStream("D:/hksadsa.txt");
// fos.write(97);
// fos.write("\r\n".getBytes());
// fos.write(98);

//PrintStream:
PrintStream ps=new PrintStream(fos,true);
ps.println("Long long ago");
ps.println("There is a shan and heshang");
ps.println("san name is xiaoxiong!");
ps.println("heshang's name is 石建雄!");
字符流-------------------------------------
//要读取文本文件我们必须创建一个流,指向文件
//如果要创建一个输入流指向文件,我们只能创建字节输入流
FileInputStream fis=new FileInputStream("D:/t.txt");
//针对文本文档,我们首选字符流来读取,但是我们只能创建文件的字节输入流
//所以我们要借助于InputStreamReader来将这个字节流转换成字符流
InputStreamReader isr=new InputStreamReader(fis);
// char[] c=new char[20];
// int len;
// while((len=isr.read(c))!=-1){
// for (int i = 0; i < len; i++) {
// System.out.print(c[i]);
// }
// }
//通过InputStreamReader对象进行读取,效率比较低,方法比较单一---所以我们要对其进行封装
//1.可以提高读取效率   2.扩展读取方法
BufferedReader br=new BufferedReader(isr);
//每次读取外设中的一行数据,赋值给str,如果没有读取到内容则str=null;
// String s=br.readLine();
// System.out.println(s);
String s=null;
while((s=br.readLine())!=null){
System.out.println(s);
}
特色流类:RandomAccessFile----------:
RandonAccessFile(字节):是一个文件流,可以用来自由的访问(读/写)文件
构造器:
RandonAccessFile raf = new RandonAccessFile(File 访问的文件,String 模式);
RandonAccessFile raf = new RandonAccessFile(String 访问文件的路径,String 模式);
模式可供选择的有4种:“r”,“rw”,“rws”,“rwd”
如果模式指定为“r”:表示这个流只能用来读取文件内容
如果模式指定为“rw”:表示这个流既能将文件内容读入到程序,也能将程序中的数据写入到文件中

//构造器  参数 :"rw"-- r:可读   w:可写
RandomAccessFile raf=new RandomAccessFile("D:/t.txt","rwd");
// byte[] b="小熊你好色!".getBytes();
// raf.write(b);
//seek():将流的指针向前/后移动到相对文件开头后的n个字节处
// raf.seek(6);
// raf.seek(8);
// int j=raf.read();
// System.out.println(j);
String s="hhhhahha";
//length():返回对应文件的长度(字节数)
long i=raf.length();
raf.seek(6);
raf.writeBytes(s);
// System.out.println(i);
raf.close();

流的一般操作:

[img]http://dl.iteye.com/upload/attachment/0074/9909/dfc0d966-bb1a-3c11

压缩文件实例:
压缩与解压文件---ZipOutputStream    ZipInputStream
public class TestZipSingleFile {

public static void main(String[] args) {
try {
//将D:/鱼鱼鱼.mp3压缩

//1,找到源文件
String srcPath = "D:/abc.mp3";
//2,根据源文件的名字生成压缩文件的名字
int i = srcPath.lastIndexOf(".");
String zipPath = srcPath.substring(0,i)+".zip";

//3,创建一个输入流指向源文件,因为我们要读取源文件的内容
FileInputStream fis = new FileInputStream(srcPath);

//4,创建一个输出流指向压缩文件,因为我们要把读取到得源文件的数据写到压缩文件
FileOutputStream fos = new FileOutputStream(zipPath);
ZipOutputStream zos = new ZipOutputStream(fos);

//5,创建一个房间(压缩条目)
File f = new File(srcPath);
//条目的名字要和源文件的名字一致
ZipEntry ze = new ZipEntry(f.getName());
zos.putNextEntry(ze);

//6,通过fis读取源文件,通过zos将读取到得内容写到压缩文件中对应的条目
byte[] b = new byte[500];
int len = -1;
while((len = fis.read(b))!=-1){
zos.write(b, 0, len);
}

zos.close();
fos.close();
fis.close();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

}
public class UnZip {

/**
* 将指定的压缩文件,解压到C盘
* @param zipPath
*/
public void unZipFile(String zipPath){
try {
FileInputStream fis = new FileInputStream(zipPath);
ZipInputStream zis = new ZipInputStream(fis);
ZipEntry ze = null;
while((ze=zis.getNextEntry())!=null){
String zeName = ze.getName();
String saveFile = "c:/"+zeName;
//保存当前文件,目录要存在
int n = saveFile.lastIndexOf("\\");
String dirPath = saveFile.substring(0,n);
File dir = new File(dirPath);
dir.mkdirs();
//通过zis读取到当前条目的数据,然后写到对用saveFile
FileOutputStream fos = new FileOutputStream(saveFile);
byte[] b = new byte[1000];
int len = -1;
while((len = zis.read(b))!=-1){
fos.write(b,0,len);
}
fos.close();
zis.closeEntry();
}
zis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}



public static void main(String[] args) {
String zipPath = "D:/Java/jdk1.6.0_02.zip";
new UnZip().unZipFile(zipPath);
}

}
public class TestZipDirectory{

/**
* 遍历文件夹
* @throws IOException
*/
public void bianLi(File f,ZipOutputStream zos,int index) throws IOException{
if(f.isFile()){
FileInputStream fis = new FileInputStream(f);
//为当前子文件创建条目:从第一级父目录开始
//截取当前子文件的条目路径
String zePath = f.getAbsolutePath().substring(index+1);
ZipEntry ze = new ZipEntry(zePath);
zos.putNextEntry(ze);
byte[] b = new byte[500];
int len = -1;
while((len = fis.read(b))!=-1){
zos.write(b, 0, len);
}
zos.closeEntry();
fis.close();
}else{
//不是文件则代表是目录,我们就要去到目录中所有的子文件
File[] files = f.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
bianLi(file,zos,index);
}
}
}


public static void main(String[] args) {
try {

File dir = new File("D:/Java/jdk1.6.0_02");
String srcPath = dir.getAbsolutePath();
int index = srcPath.lastIndexOf("\\");
System.out.println(index);
String zipPath = srcPath+".zip";
//创建一个zos流指向压缩文件
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipPath));
new TestZipDirectory().bianLi(dir,zos,index);
zos.close();


} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
对象序列化:-------------------
1, 对象序列化:将对象通过输出流保存到磁盘(文件)/网络
① 对象序列化的目的?
A> 将对象存放到磁盘中实现持久化(永久保存)
B> 将对象在网络中传输,实现信息交换
② 什么样的对象可以被序列化?
A> 这个对象所在的类实现了Serializable接口
B> 这个对象所在的类实现了Externalizable接口
③ 怎么样实现对象序列化?
借助于ObjectOutputStream(高级流),需要对低级流进行封装
public final void writeObject(Object obj)
④ 对象中的哪些元素可以被序列化?
对象类名和属性可以被序列,但是被static或者transient修饰的属性不能被
实例:
public class Person implements Serializable {

//一个类中如果实现Serializable接口,我们认为该类的对象可以被序列化
//但是如果该类可以被序列化的属性中有对象类型,那么这个对象的类也必须实现序列化接口


private String pname = "person";
//如果想保留对象的某个属性不被序列化,可以用transient修饰这个属性
//transient修饰的属性不会被序列化
transient String psex = "女";
protected int page = 22;
public String pinfo = "我真的是一个人";
public  Student s = new Student();

}
*******************************************************************************
public class Person implements Serializable {

//一个类中如果实现Serializable接口,我们认为该类的对象可以被序列化
//但是如果该类可以被序列化的属性中有对象类型,那么这个对象的类也必须实现序列化接口


private String pname = "person";
//如果想保留对象的某个属性不被序列化,可以用transient修饰这个属性
//transient修饰的属性不会被序列化
transient String psex = "女";
protected int page = 22;
public String pinfo = "我真的是一个人";
public  Student s = new Student();

}
public class TestObjectInputStream {

public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("D:/obj.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
while(1==1){
Object obj = ois.readObject();
if(obj instanceof Person){
Person p = (Person) obj;
System.out.println(p.psex);
System.out.println(p.page);
System.out.println(p.pinfo);
}else if(obj instanceof Student){
Student s = (Student) obj;

}

}

} catch (Exception e) {
System.out.println("对象读取结束!");
}
}

}
public class TestObjectOutputStream {


public static void main(String[] args) {

try {
Person p = new Person();
Student s = new Student();

String path = "D:/obj.txt";
FileOutputStream fos = new FileOutputStream(path);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(p);
//oos.writeObject(s);
oos.flush();
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}

}
小结
回顾:
流的定义:我们可以认为在所有的外设(文件、网络、其他程序)中都有两个“管道”,如果我们的程序想要和某个外设之间进行数据交换,那么我们的程序就要获得这两个“管道”。
流的分类:
按照流的方向:输入流和输出流
输入流:外设中的数据进入到程序中
输出流:程序中的数据写入到外设中
按照流处理的数据类型:字节流和字符流
字节流:只能处理字节类型数据的流
字符流:只能处理字符类型数据的流
按照流的处理方式:节点流(低级流)和处理流(高级流)
低级流:从外设中直接获取的流
高级流:由于低级流处理数据方式单一,使用起来就不够灵活,我们可以对低级流进行封装,封转之后的流我们称之为高级流。
字节输入流:InputStream
低级字节输入流:
•ByteArrayInputStream(以数组作为外设,可以将一个字节数组中的数据输入到程序中)
•FileInputStream(以文件作为外设,可以将各种类型文件的数据输入到程序中)
•StringBufferedInputStream(以字符串作为外设,可以将字符串中的数据读出来)
//InputStream is = net.getInputStream();
高级字节输入流:
•DataInputStream:可以读取带有数据类型的数据
•BufferedInputStream:提供了一个缓冲区,读取效率更高
•LineNumberInputStream:可以添加行标记实现对应行的读取
•ObjectInputStream:可以将一个对象保存到低级流指向的地方(对象序列化)

字节输出流:OutputStream
低级字节输出流:
•ByteArrayOutputStream(以数组作为外设,可以将程序中的数据写到数组中)
•FileOutputStream(以文件作为外设,可以将程序中的数据写入到文件中)
高级字节输出流:
•DataOutputStream:可以将带有类型的数据写到文件中
•BufferedOutputStream:提供了一个缓冲区,可以提供写入的效率(调用flush()方法)
•PrintStream: 扩展了很多方法(print(),println()…)

字符输入流:Reader
低级字符输入流:
•CharArrayReader:(将一个字符数组作为外设,可以将字符数组中的数据读到程序中)
•StringReader:(将字符串作为外设,可以将一个字符串的内容读取出来)
•FileReader:(继承了InputStreamReader,将文件作为外设,通常我们获取到得文件流都是字节流)
高级字符输入流:
•InputStreamReader 是字节流通向字符流的桥梁
•BufferedReader:带有缓冲区的字符输入流
•FilterReader


字符输出流:Writer
低级字符输出流:
•CharArrayWriter
•StringWriter
•FileWriter(继承OutputStreamWriter,以文件作为外设)
高级字符输出流:
•OutputStreamWriter:将字节输出流转换成字符输出流
•BufferedWriter:带有缓冲区的字符输出流
•FilterWriter
•PrintWriter:扩展了print/println(),更方便我们的输出操作

你可能感兴趣的:(java,IO)