Java学习笔记---IO操作
一、文件的创建
-------------------------------------------------------
File类,表示磁盘上的文件或目录,可对文件或目录进行操作.
* 常用方法
File.separator separator用于表示目录间的分隔符
creatNewFile() 创建一个新文件
mkdir() 创建一个目录
delete() 可以将文件删除
deleteonExit() 当程序终止后删除文件
createTempFile() 创建临时文件
list() 反回当前目录下的所有文件名和子目录的名字
isDirectory() 判断是不是目录
isFile 判是不是文件
FilenameFilter() 文件名的过滤器,它是个接口,
它有个方法accept(File dir,String name)返回企为值为boolean型,判断每个文件名是不是,符合要求
1. 创建一个文件
File f=new File("1.txt");
f.creatNewFile(); //创建一个名为1.txt的文件
f.mkdir(); //创建一个名为1.txt的目录
2. File f=new File("E://java//abc//1.text"); //在windows下可以这么做,在linux下则不行,linux下没有盘符
f.createNewFile(); 在e:/java/abc下创建1.text文件
-----------------------------------------------------
3. File fDir=new File(File.separator); //separator用于表示目录间的分隔符,这里是表示在系统根目录下
也可以 File fDir=new File(/); Windows可以这样表示跟目录
String strFile="java"+File.separator+"abc"+file.separator+"1.txt"; // java/abc/1.txt
File f=new File(fDir,strFile); //fDir是创建文件的父目录,strFile是文件位置
f.createNewfile();
f.delete() //可以将文件删除
f.deleteonExit() //当程序终止后删除文件
Thread.sleep(3000); //3秒后程序会结束,这样这个文件创建3秒后,程序结束,然后执deleteonExit删除文件
--------------------------------
4. for (int i=0;i<5;i++)
{ File f=File.createTempFile("winsun",".tmp"); //创建5个临时文件,文件名是winsun,后缀名是tmp,文件位置在环境
变量的temp所指定的临时文件的目录下 createTempFile是一个静态变量,可以直接调用
f.deleteOnExit();
}
Thread.sleep(3000);
for (int i=0;i<5;i++)
{ File.createTempFile("winsun",".tmp"); } //可以这样直接创建5个临时文件
---------------------------------
5. File fDir=new File(File.separator);
String strFile="java"+File.separator+"abc"+file.separator+"aa"; //因为list()显示的目录是从当
前文件所在盘开始的,所以必须
从跟目录一直找到要用到的文件目录
File f=new File(fDir,strFile);
if (f.isDirectory()) //判断是不是目录
{ String[] names=f.list(); //list返回的是一个String类型的静态数组
for (int i;i<names.length;i++)
{ System.out.println(names[i]); }
}
else
{ System.out.println("没有该目录");
}
------------------------------------------
6. 文件名的过滤器的用法
File fDir=new File(File.separator);
String strFile="java"+File.separator+"abc";
File f=new File(fDir,strFile);
String[] names=f.list(new FilenameFilter() //在list()中建个文件过滤器
{ public boolean accept(File dir,String name)
{ return name.indexOf(".java")!=-1; } // 显示扩展名为.java的文件,如果不等于-1返回true,否则返回flase
}); //匿名内部类,在查看java原文件中看到,File的list(FilenameFilter filter)方法中,自已调用了accept方法,
for (int i;i<names.length;i++)
{ System.out.println(names[i]); }
---------------------------------------------
*********************************************
---------------------------------------------
二、文件的读写
流的分类:1、节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。
2、过滤流:使用节点流作为输入输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。
* InputStream
三个基本的读方法
abstract int read() : 读取一个字节的数据,但是按整型返回的,如果返回-1表示读到了文件流的末尾。
整型占四个字节,它的第一个字节才是有效的数据(注意)
int read(byte[] b) : 将数据读入一个字节数组,同时返回实际读取的字节数
int read(byte[]b,int off,int len)
其它方法
long skip(long n): 在输入流中跳过n个字节,并返回实际跳过的字节数。
int available(): 返回可读取的字节数。
void close():关闭输入流,释放和这个流相关的系统资源。
void mark(),void reset(),booleanmarkSupported(),在这个流中都是空实现的方法
* ouputStream
三个基本的写方法
abstract void write(int b): 往输出流中写入一个字节,但传进去一个整型的数据,它只写整型的第一个字节
void write(byte[] b)
void write(byte[]b,int off,int len)
其它方法
void flush(): 刷新输出流,强制缓冲区中的输出字节被写出。(它只对使用了缓冲的流类起作用)
void close():关闭输出流
--------------------------------
System.in 和 System.out 的 in 和out 都是PrintStream类型的
import java.io.*;
class StreamTest
{ public static void main(String[] args)throws Exception
{ int data;
while((data=System.in.read())!=-1) //read它可以读取一个字节的数据,但它的返回值是一个整型,如果返回-1说明
已经到了流的结尾
{ System.out.write(data);} //write方法的参数也是整型
}
}
---------------------------------------------------
***文件输入输出流 FileInputStream FileOutputStream (节点流)***
FileOutputStream fos=new FileOutputStream("1.txt")
fos.write("http://hongxuan.ful.cn".getBytes()); //write只能写入一个字节或是一个字节数组,不能写入字符串,但它的getBytes能获取一个字节数组
fos.close();
FileOutputStream fos=new FileOutputStream("1.txt",true) //后面加true是在文件后面追加
fos.write("http://hongxuan.ful.cn".getBytes());
fos.close();
FileInputStream fis=new FileInputStream("1.txt");
byte[] buf=new byte[100];
int len=fis.read(buf);
System.out.println(new String(buf,0,len));
fis.close();
StringBuffer s=new StringBuffer();
FileInputSteam fis=new FileInputStream();
int c;
while ((c=fis.read())!=-1)
s.append((char)c);
System.out.println(s.toString);
----------------------------------------
**BufferedInputStream BufferedOutputStream () (过滤流)使用已经存在的节点来构造,提供带缓冲的读写,提高了读写效
率
BufferedInputStream 真正实现了mark()和reset()方法
BufferedOutputStream 实现了flush()方法
FileOutputStream fos=new FileOutputStream("1.txt");
BufferedOutputstream bos=new BufferedOutputStream(fos);
bos.write("http://hongxuan.ful.cn",getBytes()); //这时1.txt中并没有数据,数据在缓充区中,因为缓充区中还没有满
// bos.flush(); //刷新缓充区,执行这条语句,就会把缓冲区中的内容写到1.txt文件中
bos.close(); //如果不加bos.flush()的话bos.close()后,也会把数据写到1.txt中了
FileInputStream fis=new FileInputStream("1.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
byte[] buf=new byte[100];
int len=bis.read(buf);
System.out.println(new String(buf,0,len));
bis.close();
-------------------------------
**DataInputStream 和 DataOutputStream (过滤流) 提供了读写java中的基本数据类型的功能
FileOutputStream fos=new FileOutputStream("1.txt");
BufferedOutputstream bos=new BufferedOutputStream(fos);
DataOutputStream dos=new DataOutputStream(bos); //将3个流连到一起
byte b=3; int i=78; char ch='a'; float f=4.5f;
dos.writeByte(b);
dos.writeint(b);
dos.writeChar(b);
dos.writeFloat(b);
dos.close();
FileInputStream fis=new FileInputStream("1.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
DataInputStream dis=new DataInputStream(bis);
System.out.println(dis.readByte());
System.out.println(dis.readInt());
System.out.println(dis.readChar());
System.out.println(dis.readFloat());
dis.close();
------------------------------------------------------
** PipedInputStream 和 PipedOutputStream (管道流,用于线程间的通信,必须同时构造管道输入流和管道输出流)
*PipedInputStream的两个构造方法
PipedInputStream()
PipedInputStream(PipedOutputStream src)
PipedInputStream 的方法connect(PipedOutputStream src) 使此传送输入流连接到传送输出流 src。
import java.io.*;
class PipedStreamTest
{ public static void main(String[] args)
{ PipedOutputStream pos=new PipedOutputStream();
PipedInputStream pis=new PipedInputStream();
//在连接时会抛出个异常
try{ pos.connect(pis); //可以用管道输出流连管道输入流,也可用管道输入流连管理输出流
可定成 pis.connect(pos);
new Produer(pos).start();
new Consumer(pis).start();
}
catch(Exception e)
{ e.printStackTrace(); }
}
}
class Producer extends Thread
{ private PipedOutputStream pos;
public Producer(PipedOutputStream pos)
{ this.pos=pos; }
public void run()
{ try
{ pos.write("Hello,welcome you!",getBytes());
pos.close();
}
catch(Exception e)
{ e.printStackTrace();
}
}
}
Class Consumer extends Thread
{ private PipedInputStream pis;
public Consumer(PipedInputStream pis)
{ this.pis=pis;
}
public void run()
{ try{ byte[] buf=new byte[100];
int len=pis.read(buf);
System.out.println(new String(buf,0,len));
pis.close();
}
catch(Exception e)
{ e.printStackTrace(); }
}
}
--------------------------------------------------------------
--------------------------------------------------------------
--------------------------------------------------------------
--------------------------------------------------------------
reader writer (两个抽象类)
InputStreamReader 从字节流到字符流的转换
OutputStreamWriter 从字符流到字节流的转换
// 带缓冲的字符流
BufferedWriter
BufferedReader
//用字符流向文本文件中写入数据
FileOutputStream fos=new FileOutputStream("1.txt");
OutputStreamWriter osw=new OutputStreamWriter(fos);//将字符流转为字节流的输出
BufferedWriter bw=new BufferedWriter(osw);
bw.write("http://hongxuan.ful.cn");
bw.close();
//从文本文件中读入数据
FileInputStream fis=new FileInputStream("1.txt");
InputStreamReader isr=new InputStreamReader(fis);//将字节流转为字符流读出
BufferedReader br=new BufferedReader(isr);
System.out.println(br.readLine());
br.close();
---------------------------
//在命令行中读入数据然后显示数据
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
String StrLine;
while((StrLine=br.readLine())!=null)
{ System.out.println(strLine); }
br.close();
----------------------------------------------------------
----------------------------------------------------------
----------------------------------------------------------
****RandomAccessFile类同时实现了DataInput和DataOutput接口,可以对文件随机存取,在文件任何位置
读取或写入数据。
它有一个指针,用来进行读写操作的下一数据的位置。
写入一个字符串的方法
writeBytes(String s); 将一个字符的两个字节的第一个字节写入到文件中,第二个字节舍弃(最好不用)
writeChars(String s); 将两个字节表示的一个数据,全都写入到文件中
writeUTF(String str); 英文件一般占一个字节,中文是三个字节,它会在写入数据的前面两个字节处,记录
写入数据的长度,比如写入"myblog"这样6个字符,它会在"myblog"前记录个6。表明
"myblog"占六个字节长度,对应的有一个readUTF() (最好用这个)
getFilePointer: 文件指针,获取文件当前位置
seek(long pos): 设置文件指针的偏移量,将pos设为0,文件指针就指向文件起始位置。
import java.io.*;
class RandomFileTest
{ public static void main(String[] args) throws Exception
{ Student s1=new Student(1,"zhangsan",98,5);
Student s2=new Student(2,"lisi",96.5);
Student s3=new Student(3,"wangwu",78.5);
RandomAccessFile raf=new RandomAccessFile("student.txt","rw");
s1.writeStudent(raf);
s2.writeStudent(raf);
s3.writeStudent(raf);
Student s=new Student();
raf.seek(0);
for (long i=0;i<raf.length();i=raf.getFilePointer()) //获取一个文件的长度,它的返回值是一个long型
{ s.readStudent(raf);
System.out.println(s.num+":"+s.name+":"+s.score);
}
raf.close();
}
}
class Student
{ int num;
String name;
double score;
public Student()
{
}
public Student(int num,String name,double score)
{ this.num=num;
this.name=name;
this.score=score;
}
public void writeStudent(RandomAccessFile raf) throws IOException
{ raf.writeInt(num);
raf.writeUTF(name);
raf.writeDouble(score);
}
pubic void readStudent(RandomAccessFile raf) throws IOException
{ num=raf.readInt();
name=raf.readUTF();
score=raf.readDouble();
}
}
--------------------------------------------------
--------------------------------------------------
--------------------------------------------------
*****对象序列化
* 将对象转换为字节流保存起来,并在日后还原这个对象,这种机制叫做对象序列化。
* 将一个对象保存到永久存储设备上称为持续性。
* 一个对象要想能够实现序列化,必须实现Serializable接口或Externalizable接口。
Serializable接口中没有任何方法,是个空接口,是个标识接口,对象去实现这个接口,表明这个对象,可以进行
序列化了。
Externalizable接口它继承自Serializable接口
---实现对象的序列化,可利用io包中的两个类,
ObjectOutputStream,它实现了DataOutput接口,它提供了往输出流中写入java基本数据类型的功能,
ObjectOutputStream()
ObjectOutputStream(OutputStream out)
它的方法,writeObject(Object obj)可以写入指定的对象,到对象的输出流中,它可以完成对象的序列化。
ObjectInputStream,它实现了DataInput接口,它也提供了java基本数据类型读写的功能,
它的方法,readObject()从对象输入流中读取一个对象。可实现对象的反序列化操作。
*当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。
*如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
*如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个
NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。
import java.io.*;
class ObjectSerialTest
{ public static void main(String[] args) throws Exception
{ Employee e1=new Employee("zhangsan",25,3000.50);
Employee e1=new Employee("lisi",24,3200.40);
Employee e1=new Employee("wangwu",27,3800.55);
FileOutputStream fos=new FileOutputStream("employee.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(e1);
oos.writeObject(e2);
oos.writeObject(e3);
oos.close();
FileInputStream fis=new FileInputStream("employee.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Employee e;
for (int i=0;i<3;i++)
{ e=(Employee)ois.readObject(); //它返回的是一个Object类型,所以得转换成Employee类型
System.out.println(e.name":"+e.age+":"+e.salary);
}
}
}
class Employee implements Serializable
{ String name;
int age;
double salary; //如果在salary前加上transient,salary这个变量也不会保存
transient Thread t=new Thread(); 这里的线程对象t是个不可序列化的对象,但前面要是加个transient,
t这个对象就不会参与到序列化当中.
public Employee(String name,int age,double salary)
{ this.name=name;
this.age=age;
this.salary=salary;
}
//下面的两个方法比较特殊,private的方法,一般不可以被外部调用,但下面的两个方法,可以被调用
如果想对 对象进行控制,可以用下面的两个方法,按自已的想法去读写对象信息, 下面的这两方法就是
在读和写的时候都没有加salary这个变量
private void writeObject(ObjectOutputStream oos) throws IOException
{ oos.writeInt(age);
oos.writeUTF(name);
System.out.println("Write Object");
}
private void readObject(ObjectInputStream ois) throws IOException
{ oos.writeInt(age);
oos.writeUTF(name);
System.out.println("Read Object");
}
}