java程序设计--孙鑫java无难事Lesson9《IO操作》
本节要点:1.Java I/O流及操作
2.Java I/O库的设计原则,
3.字符集的编码,
4.RandomAccessFile类,
5.对象的序列化
详细内容:
1.File类操作
(1)一个File类的对象,表示了磁盘上的文件或目录。
(2)File类提供了与平台无关的方法来对磁盘上的文件或目录进行操作。
File类测试代码如下:
- import java.io.*;
- class FileTest
- {
- public static void main(String[] args) throws Exception
- {
- /*
- //创建文件
- File file=new File("1.txt");//相对路径
- file.createNewFile();
- */
- /*
- //创建目录
- File file2=new File("1");
- file2.mkdir();
- */
- /*
- //绝对路径创建文件
- File file3=new File("F:\\java\\JavaLesson\\Lesson9\\2.txt");
- file3.createNewFile();
- */
- /*
- //平台无关性创建文件
- File fileDir=new File( File.separator);// 一个分隔符代表根目录
- String strFile="java"+File.separator+"JavaLesson"+File.separator+"Lesson9"+File.separator+"3.txt";
- File file4=new File(fileDir,strFile);
- file4.createNewFile();//创建
- // file4.delete();//删除
- Thread.sleep(3000);//暂停加强演示效果
- file4.deleteOnExit();
- */
- /*
- //创建临时文件
- for(int i=0;i<5;i++)
- {
- File f=File.createTempFile("Temp",".tmp");
- Thread.sleep(3000);//暂停加强演示效果
- f.deleteOnExit();
- }
- */
- //列举文件
- File fileDir=new File( File.separator);// 一个分隔符代表根目录
- String strFile="java"+File.separator+"JavaLesson"+File.separator+"Lesson9";
- File file5=new File(fileDir,strFile);
- //运用匿名内部类 筛选文件
- String[] strFileName=file5.list(new FilenameFilter()
- {
- public boolean accept(File dir, String name)
- {
- return name.indexOf(".java")!=-1;
- }
- } );
- for(int i=0;i<strFileName.length;i++)
- {
- System.out.println(strFileName[i]);
- }
- }
- }
import java.io.*;
class FileTest
{
public static void main(String[] args) throws Exception
{
/*
//创建文件
File file=new File("1.txt");//相对路径
file.createNewFile();
*/
/*
//创建目录
File file2=new File("1");
file2.mkdir();
*/
/*
//绝对路径创建文件
File file3=new File("F:\\java\\JavaLesson\\Lesson9\\2.txt");
file3.createNewFile();
*/
/*
//平台无关性创建文件
File fileDir=new File( File.separator);// 一个分隔符代表根目录
String strFile="java"+File.separator+"JavaLesson"+File.separator+"Lesson9"+File.separator+"3.txt";
File file4=new File(fileDir,strFile);
file4.createNewFile();//创建
// file4.delete();//删除
Thread.sleep(3000);//暂停加强演示效果
file4.deleteOnExit();
*/
/*
//创建临时文件
for(int i=0;i<5;i++)
{
File f=File.createTempFile("Temp",".tmp");
Thread.sleep(3000);//暂停加强演示效果
f.deleteOnExit();
}
*/
//列举文件
File fileDir=new File( File.separator);// 一个分隔符代表根目录
String strFile="java"+File.separator+"JavaLesson"+File.separator+"Lesson9";
File file5=new File(fileDir,strFile);
//运用匿名内部类 筛选文件
String[] strFileName=file5.list(new FilenameFilter()
{
public boolean accept(File dir, String name)
{
return name.indexOf(".java")!=-1;
}
} );
for(int i=0;i<strFileName.length;i++)
{
System.out.println(strFileName[i]);
}
}
}
2.流式I/O
流(Stream)是字节的源或目的。
两种基本的流是:输入流(Input Stream)和输出流(Output Stream)。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。
(1) 流的分类
节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。
过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。
(2) InputStream和OutputStream类 操作字节流
InputStream和OutputStream类层次如下图所示:
FileInputStream和FileOutputStream节点流,
用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。
BufferedInputStream和BufferedOutputStream过滤流,
需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。
DataInputStream和DataOutputStream过滤流,
需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。PipedInputStream和PipedOutputStream管道流,
用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。
- import java.io.* ;
- class StreamTest
- {
- public static void main(String[] args) throws Exception
- {
- /*
- int data;
- while( (data=System.in.read()) !=-1)
- {
- System.out.write(data);
- }
- */
- /*
- //BufferedOutputStream写入
- FileOutputStream fileout=new FileOutputStream(new File("StreamTest1.txt"));
- BufferedOutputStream bo=new BufferedOutputStream(fileout);
- fileout.write("Java FileOutputStream Test".getBytes());
- bo.write("Java BufferedOutputStream Test".getBytes());
- bo.flush();//需要刷新缓冲区 不关闭输出流
- bo.close();//关闭同样可以刷新 但是将关闭输出流
- //BufferedInputStream读取
- FileInputStream filein=new FileInputStream(new File("StreamTest1.txt"));
- BufferedInputStream bi=new BufferedInputStream(filein);
- byte[] b=new byte[100];
- int len=bi.read(b);
- String str=new String(b,0,len);
- System.out.println(str);
- */
- /*
- //DataOutputStream和DataInputStream测试
- //DataOutputStream写入
- FileOutputStream fileout=new FileOutputStream(new File("StreamTest2.txt"));
- DataOutputStream dos=new DataOutputStream(fileout);
- byte bt=3;
- int i=4;
- boolean bool=false;
- char ch='a';
- float f=1.3f;
- dos.writeByte(bt);
- dos.writeInt(i);
- dos.writeBoolean(bool);
- dos.writeChar(ch);
- dos.writeFloat(f);
- dos.close();
- //DataInputStream读取
- FileInputStream filein=new FileInputStream(new File("StreamTest2.txt"));
- DataInputStream dis=new DataInputStream(filein);
- System.out.println(dis.readByte());
- System.out.println(dis.readInt());
- System.out.println(dis.readBoolean());
- System.out.println(dis.readChar());
- System.out.println(dis.readFloat());
- */
- /*
- //OutputStreamWriter写入
- FileOutputStream fileout=new FileOutputStream(new File("StreamTest3.txt"));
- OutputStreamWriter osw=new OutputStreamWriter(fileout);
- BufferedWriter bw= new BufferedWriter(osw);
- bw.write("java BufferedWriter Test");
- bw.close();
- //InputStreamReader读取数据
- FileInputStream filein=new FileInputStream(new File("StreamTest3.txt"));
- InputStreamReader fsr=new InputStreamReader(filein);
- BufferedReader br=new BufferedReader(fsr);
- String strline=br.readLine();
- System.out.println(strline);
- */
- //从标准输入设备读写
- InputStreamReader fsr=new InputStreamReader(System.in);
- BufferedReader br=new BufferedReader(fsr);
- String strline=new String();
- while((strline=br.readLine())!=null)
- {
- System.out.println(strline);
- }
- br.close();
- }
- }
import java.io.* ;
class StreamTest
{
public static void main(String[] args) throws Exception
{
/*
int data;
while( (data=System.in.read()) !=-1)
{
System.out.write(data);
}
*/
/*
//BufferedOutputStream写入
FileOutputStream fileout=new FileOutputStream(new File("StreamTest1.txt"));
BufferedOutputStream bo=new BufferedOutputStream(fileout);
fileout.write("Java FileOutputStream Test".getBytes());
bo.write("Java BufferedOutputStream Test".getBytes());
bo.flush();//需要刷新缓冲区 不关闭输出流
bo.close();//关闭同样可以刷新 但是将关闭输出流
//BufferedInputStream读取
FileInputStream filein=new FileInputStream(new File("StreamTest1.txt"));
BufferedInputStream bi=new BufferedInputStream(filein);
byte[] b=new byte[100];
int len=bi.read(b);
String str=new String(b,0,len);
System.out.println(str);
*/
/*
//DataOutputStream和DataInputStream测试
//DataOutputStream写入
FileOutputStream fileout=new FileOutputStream(new File("StreamTest2.txt"));
DataOutputStream dos=new DataOutputStream(fileout);
byte bt=3;
int i=4;
boolean bool=false;
char ch='a';
float f=1.3f;
dos.writeByte(bt);
dos.writeInt(i);
dos.writeBoolean(bool);
dos.writeChar(ch);
dos.writeFloat(f);
dos.close();
//DataInputStream读取
FileInputStream filein=new FileInputStream(new File("StreamTest2.txt"));
DataInputStream dis=new DataInputStream(filein);
System.out.println(dis.readByte());
System.out.println(dis.readInt());
System.out.println(dis.readBoolean());
System.out.println(dis.readChar());
System.out.println(dis.readFloat());
*/
/*
//OutputStreamWriter写入
FileOutputStream fileout=new FileOutputStream(new File("StreamTest3.txt"));
OutputStreamWriter osw=new OutputStreamWriter(fileout);
BufferedWriter bw= new BufferedWriter(osw);
bw.write("java BufferedWriter Test");
bw.close();
//InputStreamReader读取数据
FileInputStream filein=new FileInputStream(new File("StreamTest3.txt"));
InputStreamReader fsr=new InputStreamReader(filein);
BufferedReader br=new BufferedReader(fsr);
String strline=br.readLine();
System.out.println(strline);
*/
//从标准输入设备读写
InputStreamReader fsr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(fsr);
String strline=new String();
while((strline=br.readLine())!=null)
{
System.out.println(strline);
}
br.close();
}
}
- 管道流测试代码如下:
- import java.io.* ;
- class PipedStreamTest
- {
- public static void main(String[] args)
- {
- PipedOutputStream pos=new PipedOutputStream();
- PipedInputStream pis=new PipedInputStream();
- try
- {
- pis.connect(pos);//连接管道
- new Producer(pos).start();
- new Consumer(pis).start();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }
- //生产者线程
- class Producer extends Thread
- {
- private PipedOutputStream pos;
- 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;
- Consumer(PipedInputStream pis)
- {
- this.pis=pis;
- }
- public void run()
- {
- try
- {
- byte[] bt=new byte[100];
- int len=pis.read(bt,0,bt.length);
- System.out.write(bt,0,len);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }
管道流测试代码如下:
import java.io.* ;
class PipedStreamTest
{
public static void main(String[] args)
{
PipedOutputStream pos=new PipedOutputStream();
PipedInputStream pis=new PipedInputStream();
try
{
pis.connect(pos);//连接管道
new Producer(pos).start();
new Consumer(pis).start();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
//生产者线程
class Producer extends Thread
{
private PipedOutputStream pos;
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;
Consumer(PipedInputStream pis)
{
this.pis=pis;
}
public void run()
{
try
{
byte[] bt=new byte[100];
int len=pis.read(bt,0,bt.length);
System.out.write(bt,0,len);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
(4)Java I/O库的设计原则
Java的I/O库提供了一个称做链接的机制,可以将一个流与另一个流首尾相接,形成一个流管道的链接。这种机制实际上是一种被称为Decorator(装饰)设计模式的应用。
通过流的链接,可以动态的增加流的功能,而这种功能的增加是通过组合一些流的基本功能而动态获取的。
我们要获取一个I/O对象,往往需要产生多个I/O对象,这也是Java I/O库不太容易掌握的原因,但在I/O库中Decorator模式的运用,给我们提供了实现上的灵活性。I/O流的链接如下图所示:
Java程序语言使用Unicode来表示字符串和字符。
Reader和Writer这两个抽象类主要用来读写字符流。
Reader和Writer类层次如下图所示:
RandomAccessFile类同时实现了DataInput和DataOutput接口,提供了对文件随机存取的功能,利用这个类可以在文件的任何位置读取或写入数据。
RandomAccessFile类提供了一个文件指针,用来标志要进行读写操作的下一数据的位置。
RandomAccessFile测试代码如下:
- import java.io.*;
- class RandomAccessFileTest
- {
- public static void main(String[] args) throws Exception
- {
- Student stu1=new Student(1,"ZhangSan",98.5);
- Student stu2=new Student(2,"liSi",97.5);
- Student stu3=new Student(3,"WangWu",88.5);
- RandomAccessFile raf=new RandomAccessFile("Student.txt","rw");
- //写入
- stu1.write(raf);
- stu2.write(raf);
- stu3.write(raf);
- //读取
- raf.seek(0);//移动文件指针 否则 EOFException
- Student stu=new Student();
- for(long i=0;i<raf.length();i=raf.getFilePointer())
- {
- stu.read(raf);
- System.out.println(stu);
- }
- raf.close();
- }
- }
- class Student
- {
- int num;
- String name;
- Double score;
- Student( )
- {
- }
- Student(int num,String name,double score)
- {
- this.num=num;
- this.name=name;
- this.score=score;
- }
- public void write(RandomAccessFile raf) throws Exception
- {
- raf.writeInt(num);
- raf.writeUTF(name);
- raf.writeDouble(score);
- }
- public void read(RandomAccessFile raf) throws Exception
- {
- num=raf.readInt();
- name=raf.readUTF();
- score=raf.readDouble();
- }
- public String toString()
- {
- return "num:"+num+" "+"name:"+name+" "+"score:"+score;
- }
- }
import java.io.*;
class RandomAccessFileTest
{
public static void main(String[] args) throws Exception
{
Student stu1=new Student(1,"ZhangSan",98.5);
Student stu2=new Student(2,"liSi",97.5);
Student stu3=new Student(3,"WangWu",88.5);
RandomAccessFile raf=new RandomAccessFile("Student.txt","rw");
//写入
stu1.write(raf);
stu2.write(raf);
stu3.write(raf);
//读取
raf.seek(0);//移动文件指针 否则 EOFException
Student stu=new Student();
for(long i=0;i<raf.length();i=raf.getFilePointer())
{
stu.read(raf);
System.out.println(stu);
}
raf.close();
}
}
class Student
{
int num;
String name;
Double score;
Student( )
{
}
Student(int num,String name,double score)
{
this.num=num;
this.name=name;
this.score=score;
}
public void write(RandomAccessFile raf) throws Exception
{
raf.writeInt(num);
raf.writeUTF(name);
raf.writeDouble(score);
}
public void read(RandomAccessFile raf) throws Exception
{
num=raf.readInt();
name=raf.readUTF();
score=raf.readDouble();
}
public String toString()
{
return "num:"+num+" "+"name:"+name+" "+"score:"+score;
}
}
3.字符集的编码
字符编码部分内容较为复杂,在此不做深究,列出一个测试代码如下:
- import java.util.*;
- import java.nio.charset.*;
- class CharsetTest
- {
- public static void main(String[] args) throws Exception
- {
- /*
- //列举当前可用字符集
- Map map=Charset.availableCharsets();
- Set names=map.keySet();
- Iterator iter=names.iterator();
- while(iter.hasNext())
- {
- System.out.println(iter.next());
- }
- */
- Properties pps=System.getProperties();
- //pps.list(System.out);
- //编码与解码的问题
- pps.put("file.encoding","ISO-8859-1");
- byte[] buf=new byte[100];
- int data;
- int i=0;
- while((data=System.in.read())!='q')
- {
- buf[i]=(byte)data;
- i++;
- }
- String strbuf=new String(buf,0,i);
- System.out.println(strbuf);
- //重新解码
- String strGBK=new String(strbuf.getBytes("ISO-8859-1"),"GBK");
- System.out.println(strGBK);
- }
- }
import java.util.*;
import java.nio.charset.*;
class CharsetTest
{
public static void main(String[] args) throws Exception
{
/*
//列举当前可用字符集
Map map=Charset.availableCharsets();
Set names=map.keySet();
Iterator iter=names.iterator();
while(iter.hasNext())
{
System.out.println(iter.next());
}
*/
Properties pps=System.getProperties();
//pps.list(System.out);
//编码与解码的问题
pps.put("file.encoding","ISO-8859-1");
byte[] buf=new byte[100];
int data;
int i=0;
while((data=System.in.read())!='q')
{
buf[i]=(byte)data;
i++;
}
String strbuf=new String(buf,0,i);
System.out.println(strbuf);
//重新解码
String strGBK=new String(strbuf.getBytes("ISO-8859-1"),"GBK");
System.out.println(strGBK);
}
}
4.对象序列化
将对象转换为字节流保存起来,并在日后还原这个对象,这种机制叫做 对象序列化 。
将一个对象保存到永久存储设备上称为 持续性 。
一个对象要想能够实现序列化,必须实现Serializable接口或Externalizable接口。
(1)当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。
(2)如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
(3)如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。对象序列化测试代码如下:- import java.io.*;
- class ObjectSerializeTest
- {
- public static void main(String[] args) throws Exception
- {
- Employee e1=new Employee("ZhangSan",25,3500.50);
- Employee e2=new Employee("LiSi",26,3200.80);
- Employee e3=new Employee("WangWu",35,4500.50);
- //写入对象
- 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();
- System.out.println(e);
- }
- ois.close();
- }
- }
- //类的序列化
- class Employee implements Serializable
- {
- String name;
- int age;
- double salary;
- //将对象(一般为不可序列化对象)标记为transient将不参与序列化,否则产生NotSerializableException
- transient Thread th=new Thread();
- public Employee(String name ,int age,double salary)
- {
- this.name=name;
- this.age=age;
- this.salary=salary;
- }
- public String toString()
- {
- return "name:"+name+" "+"age:"+age+" "+"salary:"+salary;
- }
- //自定义序列化方法 在类外可以被调用 特例
- private void writeObject(java.io.ObjectOutputStream out) throws IOException
- {
- out.writeInt(age);
- out.writeUTF(name);
- System.out.println("Write object!");
- }
- private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
- {
- age=in.readInt();
- name=in.readUTF();
- System.out.println("read object!");
- }
- }