java i/o系统的类实在是太多了,这里我们只学习一些基本的和常用的,相信能够掌握这些就可以解决我们以后的普通应用了
1.什么是数据流 ?
数据流是指所有的数据通信通道
有两类流,inputstream and outputstream,java中每一种流的基本功能依赖于它们
inputstream 用于read,outputstream 用于write, 读和写都是相对与内存说的,读就是从其他地方把数据拿进内存,写就是把数据从内存推出去
这两个都是抽象类,不能直接使用
2.inputstream 的方法有:
read() 从流中读入数据 有3中方式:
int read() 一次读一个字节
int read(byte[]) 读多个字节到数组中
int read(byte[],int off,int len) 指定从数组的哪里开始,读多长
skip() 跳过流中若干字节
available() 返回流中可用字节数,但基于网络时无效,返回0
marksupported() 判断是否支持标记与复位操作
mark() 在流中标记一个位置,要与marksupported()连用
reset() 返回标记过的位置
close() 关闭流
3.outputstream 的方法:
write(int) 写一个字节到流中
write(byte[]) 将数组中的内容写到流中
write(byte[],int off,int len) 将数组中从off指定的位置开始len长度的数据写到流中
close() 关闭流
flush() 将缓冲区中的数据强制输出
4.file 类
file 可以表示文件也可以表示目录,file 类控制所有硬盘操作
构造器:
file(file parent,string child) 用父类和文件名构造
file(string pathname) 用绝对路径构造
file(string parent,string child) 用父目录和文件名构造
file(uri uri) 用远程文件构造
常用方法:
boolean createnewfile();
boolean exists();
例子:
//建立 test.txt 文件对象,判断是否存在,不存在就创建
import java.io.*;
public class createnewfile{
public static void main(string args[]){
file f=new file("test.txt");
try{
if(!f.exists())
f.createnewfile();
else
system.out.println("exists");
}catch(exception e){
e.printstacktrace();
}
}
}
boolean mkdir()/mkdirs()
boolean renameto(file destination)
例子://看一下这 mkdir()/mkdirs() 的区别和 renameto 的用法
import java.io.*;
public class createdir{
public static void main(string args[]){
file f=new file("test.txt");
file f1=new file("dir");
file f2=new file("top/bottom");
file f3=new file("newtest.txt");
try{
f.renameto(f3);
f1.mkdir();
f2.mkdirs();
}catch(exception e){
e.printstacktrace();
}
}
}
string getpath()/getabsolutepath()
string getparent()/getname()
例子://硬盘上并没有parent 目录和 test.txt 文件,但我们仍然可以操作,因为我们创建了他们的对象,是对对象进行操作
import java.io.*;
public class test{
public static void main(string args[]){
file f=new file("parent/test.txt");
file f1=new file("newtest.txt");
try{
system.out.println(f.getparent());
system.out.println(f.getname());
system.out.println(f1.getpath());
system.out.println(f1.getabsolutepath());
}catch(exception e){
e.printstacktrace();
}
}
}
string list[] //显示目录下所有文件
long lastmodified() //返回 1970.1.1 到最后修改时间的秒数
boolean isdirectory()
例子://列出目录下的所有文件和目录,最后修改时间,是目录的后面标出<dir>,是文件的后面标出文件长度
import java.io.*;
import java.util.*;
public class dir{
public static void main(string args[]){
file f=new file("dir");
string[] listall=null;
file temp=null;
try{
listall=f.list();
for(int i=0;i<listall.length;i++){
temp=new file(listall<i>);
system.out.print(listall<i>+"/t");
if(temp.isdirectory())
system.out.print("/t<dir>/t");
else
system.out.print(temp.length()+"/t");
system.out.println(new date(temp.lastmodified()));
}
}catch(exception e){
e.printstacktrace();
}
}
}
5.文件流的建立
file f=new file("temp.txt");
fileinputstream in=new fileinputstream(f);
fileoutputstream out=new fileoutputstream(f);
例子:文件拷贝
import java.io.*;
public class copy{
public static void main(string args[]){
fileinputstream fis=null;
fileoutputstream fos=null;
try{
fis=new fileinputstream("c2.gif");
fos=new fileoutputstream("c2_copy.gif");
int c;
while((c=fis.read()) != -1)
fos.write(c);
}catch(exception e){
e.printstacktrace();
}finally{
if(fis != null) try{ fis.close(); }catch(exception e){ e.printstacktrace(); }
if(fos!= null) try{ fos.close(); }catch(exception e){ e.printstacktrace(); }
}
}
}
6.缓冲区流
bufferedinputstream
bufferedoutputstream
他们是在普通文件流上加了缓冲的功能,所以构造他们时要先构造普通流
例子:文件拷贝的缓冲改进
import java.io.*;
public class copy{
public static void main(string args[]){
bufferedinputstream bis=null;
bufferedoutputstream bos=null;
byte buf[]=new byte[100];
try{
bis=new bufferedinputstream(new fileinputstream("persia.mp3"));
bos=new bufferedoutputstream(new fileoutputstream("persia_copy.mp3"));
int len=0;
while( true ){
len=bis.read(buf);
if(len<=0) break;
bos.write(buf,0,len);
}
bos.flush();//缓冲区只有满时才会将数据输出到输出流,用flush()将未满的缓冲区中数据强制输出
}catch(exception e){
e.printstacktrace();
}finally{
if(bis != null) try{ bis.close(); }catch(exception e){ e.printstacktrace(); }
if(bos!= null) try{ bos.close(); }catch(exception e){ e.printstacktrace(); }
}
}
}
7.原始型数据流
datainputstream
dataoutputstream
他们是在普通流上加了读写原始型数据的功能,所以构造他们时要先构造普通流
方法:
readboolean()/writeboolean()
readbyte()/writebyte()
readchar()/writebyte()
......
例子://这个流比较简单,要注意的就是读时的顺序要和写时的一样
import java.io.*;
public class dataout{
public static void main(string args[]){
dataoutputstream dos=null;
try{
dos=new dataoutputstream(new fileoutputstream("dataout.txt"));
dos.writeint(1);
dos.writeboolean(true);
dos.writelong(100l);
dos.writechar('a');
}catch(exception e){
e.printstacktrace();
}finally{
if(dos!=null)
try{
dos.close();
}catch(exception e){
}
}
}
}
import java.io.*;
public class datain{
public static void main(string args[]){
datainputstream dis=null;
try{
dis=new datainputstream(new fileinputstream("dataout.txt"));
system.out.println(dis.readint());
system.out.println(dis.readboolean());
system.out.println(dis.readlong());
system.out.println(dis.readchar());
}catch(exception e){
e.printstacktrace();
}finally{
if(dis!=null)
try{
dis.close();
}catch(exception e){
}
}
}
}
8.对象流
串行化:对象通过写出描述自己状态的数值来记述自己的过程叫串行话
对象流:能够输入输出对象的流
将串行化的对象通过对象流写入文件或传送到其他地方
对象流是在普通流上加了传输对象的功能,所以构造对象流时要先构造普通文件流
注意:只有实现了serializable接口的类才能被串行化
例子:
import java.io.*;
class student implements serializable{
private string name;
private int age;
public student(string name,int age){
this.name=name;
this.age=age;
}
public void greeting(){
system.out.println("hello ,my name is "+name);
}
public string tostring(){
return "student["+name+","+age+"]";
}
}
public class objectouttest{
public static void main(string args[]){
objectoutputstream oos=null;
try{
oos=new objectoutputstream(
new fileoutputstream("student.txt"));
student s1=new student("jerry",24);
student s2=new student("andy",33);
oos.writeobject(s1);
oos.writeobject(s2);
}catch(exception e){
e.printstacktrace();
}finally{
if(oos!=null)
try{
oos.close();
}catch(exception e){
e.printstacktrace();
}
}
}
}
import java.io.*;
public class objectintest{
public static void main(string args[]){
objectinputstream ois=null;
student s=null;
try{
ois=new objectinputstream(
new fileinputstream("student.txt"));
system.out.println("--------------------");
s=(student)ois.readobject();
system.out.println(s);
s.greeting();
system.out.println("--------------------");
s=(student)ois.readobject();
system.out.println(s);
s.greeting();
}catch(exception e){
e.printstacktrace();
}finally{
if(ois!=null)
try{
ois.close();
}catch(exception e){
e.printstacktrace();
}
}
}
}
9.字符流 inputstreamreader/outputstreamwriter
上面的几种流的单位是 byte,所以叫做字节流,写入文件的都是二进制字节,我们无法直接看,下面要学习的是字节流
java采用 unicode 字符集,每个字符和汉字都采用2个字节进行编码,ascii 码是 unicode 编码的自集
inputstreamreader 是 字节流 到 字符桥的桥梁 ( byte->char 读取字节然后用特定字符集编码成字符)
outputstreamwriter是 字符流 到 字节流的桥梁 ( char->byte )
他们是在字节流的基础上加了桥梁作用,所以构造他们时要先构造普通文件流
我们常用的是:
bufferedreader 方法:readline()
printwriter 方法:println()
例子:
import java.io.*;
public class printwritertest{
public static void main(string args[]){
printwriter pw=null;
try{
pw=new printwriter(
new outputstreamwriter(
new fileoutputstream("bufferedwriter.txt")));
pw.println("hello world");
}catch(exception e){
e.printstacktrace();
}finally{
if(pw!=null)
try{
pw.close();
}catch(exception e){
e.printstacktrace();
}
}
}
}
import java.io.*;
public class bufferedreadertest{
public static void main(string args[]){
bufferedreader br=null;
try{
br=new bufferedreader(
new inputstreamreader(
new fileinputstream("bufferedwriter.txt")));
system.out.println(br.readline());
}catch(exception e){
e.printstacktrace();
}finally{
if(br!=null)
try{
br.close();
}catch(exception e){
e.printstacktrace();
}
}
}
}
10.随机存取文件 randomaccessfile
可同时完成读写操作
支持随机文件操作的方法:
readxxx()/writexxx()
seek() 将指针调到所需位置
getfilepointer() 返回指针当前位置
length() 返回文件长度
例子:把若干个32位的整数写到一个名为 “temp.txt”的文件中,然后利用seek方法,以相反的顺序再读取这些数据
import java.io.*;
public class randomfile{
public static void main(string args[]){
randomaccessfile raf=null;
int data[]={12,31,56,23,27,1,43,65,4,99};
try{
raf=new randomaccessfile("temp.txt","rw");
for(int i=0;i<data.length;i++)
raf.writeint(data<i>);
for(int i=data.length-1;i>=0;i--){
raf.seek(i*4);
system.out.println(raf.readint());
}
}catch(exception e){
e.getmessage();
}finally{
if(raf!=null)
try{
raf.close();
}catch(exception e){
e.getmessage();
}
}
}
}
11.小结
这部分的难点就是类比较复杂,尤其是每个类的构造方式,我认为记住下面这个图比记类的继承关系更好些
a. 字节流:
inputstream
|-- fileinputstream (基本文件流)
|-- bufferedinputstream
|-- datainputstream
|-- objectinputstream
outputstream 同上图
bufferedinputstream datainputstream objectinputstream 只是在 fileinputstream 上增添了相应的功能,构造时先构造fileinputstream
b. 字符流:
reader
|-- inputstreamreader (byte->char 桥梁)
|-- bufferedreader (常用)
writer
|-- outputstreamwriter (char->byte 桥梁)
|-- bufferedwriter
|-- printwriter (常用)
c. 随机存取文件 randomaccessfile
闽公网安备 35060202000074号