一个 File 类的对象,表示了磁盘上的文件或目录。
File 类提供了与平台无关的方法来对磁盘上的文件或目录进行操作。
流 (Stream) 是字节的源或目的。
两种基本的流是:输入流 (Input Stream) 和输出流 (Output Stream) 。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。
流分为两种,一种是节点流,一种是过滤流
节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。
过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。
import java.io.*;
public class IOStreamTest {
public static void main(String args[]) throws IOException, InterruptedException, ClassNotFoundException{
System. out .println( "============================== 字符流 ==============================" );
System. out .println();
System. out .println( "-------------------------File-------------------------" );
System. out .println( "1. 直接指定文件路径 创建文件 " );
File f1= new File( "C://test.txt" );
if (f1.createNewFile()){
System. out .println( " 创建文件成功 " );
}
else {
System. out .println( " 创建文件失败 , 所在路径已存在相同文件 " );
}
System. out .println();
System. out .println( "2. 使用根目录 + 文件路径方式 创建文件 " );
File fDir1= new File(File. separator ); // 创建默认 WorkSpace 所在盘符
String sFile1= "J2EE" +File. separator + "Java Workspace" +File. separator + "Test" +
File. separator + "com" +File. separator + "source" +File. separator + "1.txt" ; // 创建路径名及文件名
File f2= new File(fDir1,sFile1);
f2.createNewFile();
System. out .println( "3. 文件的删除与临时文件的建立 " );
f2.deleteOnExit(); // 在 java 虚拟机终止时,删除此对象指定的文件。
Thread.sleep (1000); // 利用线程延迟 1 秒
System. out .println( " 倒计时 " );
for ( int i=1;i>=1;i--){
System. out .println(i+ " 秒 " );
}
System. out .println( "E:" +f2+ " 文件删除成功 " );
File f3=File.createTempFile ( "zzz" , "txt" ); // 在系统的临时目录中创建一个临时文件
f3.deleteOnExit(); // 系统终止时,销毁临时文件
System. out .println( " 临时文件已经销毁 " );
System. out .println();
System. out .println( "4. 使用根目录 + 文件路径方式 通过一个字符串数组 " +
" 返回此路径所表示的目录中的文件和文件夹 " );
File fDir2= new File(File. separator );
String sFile2= "J2EE" +File. separator + "Java Workspace" +File. separator + "Test" +
File. separator + "com" +File. separator + "source" ;
File f4= new File(fDir2,sFile2);
String[] strDir=f4.list( new FilenameFilter()
{ // 构造一个匿名内部类,因为 FilenameFilter 是一个接口,必须用一个类来实现
public boolean accept(File dir,String name)
{
return name.indexOf( ".java" )!=-1;
}
});
/* 如果 list() 方法不加任何参数,表示返回此目录下的所有文件及文件夹列表
FilenameFilter 接口表示一个过滤器,实现此接口的类,需要实现 accept(File dir, String name) 方法,
用来测试指定文件是否应该包含在某一文件列表中 */
/* 筛选出该目录中后缀名为 .java 的文件, indexOf(int ch) 返回指定字符在此字符串中第一次出现处的索引
如果有此文件,返回一个索引值 ( 以 Unicode 代码单元表示 ) ,本身不等于 -1 ,返回 true
若没有,返回 -1 , -1 ! =-1 ,所以为 false*/
for ( int i=0;i<strDir. length ;i++){ // 循环打印文件名
System. out .println(strDir[i]);
}
System. out .println();
if (f4.isDirectory()){ // 测试此抽象路径名表示的文件是否是一个目录
System. out .println( " 此路径是一个目录 " );
}
else {
System. out .println( " 此路径不是一个目录 " );
}
System. out .println();
System. out .println( "----------------FileInputStream & FileOuputStream----------------" );
System. out .println( "1. 读入一个数据,打印输出在控制台 " );
/*int data;
while((data=System.in.read())!=-1){// 用输入流从键盘接受一个值,直到等于 -1 为止
System.out.write(data);// 由输入流传入的数据,须由输出流打印输出,不可用 sysout
}*/
System. out .println( "2. 向磁盘中的文件写入数据 " );
FileOutputStream fos1= new FileOutputStream( "C:/Test.txt" );
fos1.write( " 大家好 " .getBytes()); // 只能写入一个字节或字节数组
fos1.close(); // 关闭输出流,释放资源
System. out .println( "3. 从磁盘中的文件读取数据 " );
FileInputStream fis1= new FileInputStream( "C:/Test.txt" );
byte [] buf1= new byte [100]; // 构造一个 byte[] 字节数组的缓冲区 , 输入流加载文件后默认存入缓冲区中
int len1=fis1.read(buf1); /* 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 buf1 中 ,
以整数形式返回实际读取的字节数 */
System. out .println( new String(buf1,0,len1));
/* 构造一个 String 类对象,为了防止读取缓冲区中的无用数据,不能直接构造,
需要构造带参数的 String ,配置 3 个参数,缓冲区,起始位置,长度 */
fis1.close();
System. out .println();
System. out .println( "----------------BufferedInputStream & BufferedOuputStream----------------" );
System. out .println( "1. 向文件中写入内容 " );
OutputStream out= new FileOutputStream( "C:/Test.txt" );
//OutputStream 不可实例化对象 须由派生类来实例化
BufferedOutputStream bos= new BufferedOutputStream(out);
// 创建一个缓冲输出流,需要一个输出流对象作为参数
bos.write( " 欢迎大家收看孙鑫 java 视频 " .getBytes()); // 只能写入一个字节或字节数组
// 将字节或字节数组写入此缓冲的输出流。
bos.flush(); /* 刷新此缓冲的输出流,强制将缓冲区中的字节或字节数组写入输出流,
否则当此缓冲区满时,才会将其中的字节或字节数组写入输出流 */
/*bos1.close();*/ // 关闭缓冲输出流,可以使缓冲区中的字节或字节数组写入输出流
System. out .println( " 已将内容写入文件 " );
System. out .println( "2. 从文件中读取内容 " );
InputStream in= new FileInputStream( "C:/Test.txt" );
//InputStream 不可实例化对象 须由派生类来实例化
BufferedInputStream bis= new BufferedInputStream(in);
// 创建一个缓冲输入流,需要一个输入流对象作为参数
byte [] buf2= new byte [100]; // 构造一个 byte[] 字节数组的缓冲区 , 输入流加载文件后默认存入缓冲区中
int len2=bis.read(buf2); /* 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 buf2 中 ,
以整数形式返回实际读取的字节数 */
System. out .println( new String(buf2,0,len2));
/*bos1.close();*/ // 需要记得关闭输出流
System. out .println();
System. out .println( "----------------DataInputStream & DataOuputStream----------------" );
DataOutputStream dos= new DataOutputStream(bos);
/* 创建一个数据输出流,需要一个输出流对象作为参数,最好是缓冲输出流对象,
因为通过输出流对象作为参数构造一个缓冲输出流,可以增加一个带缓冲读写的功能,提高读写的效率
在通过缓冲输出流对象作为参数构造一个数据输出流,可以再增加一个读写 java 中基本数据类型的功能,
否则,用单纯的输出流对象作为参数就没有缓冲读写的功能了,这样就可以把三个流类链接起来了
FileOuputStream-- 链接 --BufferedOuputStream-- 链接 --DataOuputStream*/
byte b=3;
int i=5;
char c= 'C' ;
float f=5;
dos.writeByte(b);
dos.writeInt(i);
dos.writeChar(c);
dos.writeFloat(f);
dos.flush();
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());
/*bos1.close();*/ // 需要记得关闭输出流
System. out .println();
System. out .println( "----------------PipedInputStream & PipedOuputStream----------------" );
/* 管道流,用于进程间的通信,要使管道流有用,必须同时构造管道输入流与管道输出流
需要定义两个类,全部实现线程的 run() 方法,集成 Thread 或者实现 Runnable 接口
生产者类 Producer 提供管道输出流 输出信息,
消费者类 Consumer 提供管道输入流 接收信息 */
PipedOutputStream pos= new PipedOutputStream();
PipedInputStream pis= new PipedInputStream();
pis.connect(pos); // 使此管道输入流连接到管道输出流 相反也可以
/*pos.connect(pis);*/ // 将此管道输出流连接到接收者
new Producer(pos).start();
new Thread( new Consumer(pis)).start();
System. out .println();
System. out .println( "============================== 字符流 ==============================" );
// Java 使用 Unicode 来表示字符串和字符,两个字节 16 位表示一个字符
System. out .println();
System. out .println( "----------------InputStreamReader & OuputStreamWrite----------------" );
System. out .println( "1. 用字符输出流读写信息 " );
try {
OutputStream os= new FileOutputStream( "C:/Test.txt" );
OutputStreamWriter osw= new OutputStreamWriter(os);
// 使用输出流对象作为参数构造一个字符输出流,默认的输出流 OutputStream 是字节流
BufferedWriter bw= new BufferedWriter(osw);
// 三层链接,用字符输出流对象来构造一个字符缓冲流
bw.write( " 欢迎观看孙鑫 java 教程 " ); // 字符流可以直接用 write() 方法输出字符串
bw.flush(); /* 刷新此缓冲的输出流,强制将缓冲区中的字节或字节数组写入输出流,
否则当此缓冲区满时,才会将其中的字节或字节数组写入输出流 */
InputStream is= new FileInputStream( "C:/Test.txt" );
InputStreamReader isr= new InputStreamReader(is);
BufferedReader br= new BufferedReader(isr);
System. out .println(br.readLine());
/* 字符流可以直接输出或读取字符串,可以用 readLine() 方法读取文件的一行,所以不用构造 byte[] 数组
来读取字节或字节数组
*/
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System. out .println();
System. out .println( "2. 用字符输出流 获取从键盘输入的值,由 sysout 输出 " );
InputStreamReader isr2= new InputStreamReader(System. in ); // 传递一个 System.in 输入流参数
BufferedReader br2= new BufferedReader(isr2);
String strLine;
/*while((strLine=br2.readLine())!=null){
System.out.println(strLine);
}*/ //while 循环在 eclipse 环境下会无限输入输出, DOS 环境下可用 Ctrl+C 来退出
for ( int j=0;j<5;j++){ // 使用 for 来控制次数
strLine=br2.readLine();
System. out .println(strLine);
}
br2.close();
System. out .println();
System. out .println( "======================== 此类同时支持输入输出 ========================" );
System. out .println();
System. out .println( "------------------------RandomFileTest------------------------" );
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( "C:/Test.txt" , "rw" );
/* 构造一个 RandomFileTest 类对象,第一个参数为文件的路径,第二个参数指定用以打开文件的访问模式
"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException 。
"rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
"rws" 打开以便读取和写入,对于 "rw" ,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
"rwd" 打开以便读取和写入,对于 "rw" ,还要求对文件内容的每个更新都同步写入到底层存储设备 */
s1.writeStudent(raf);
s2.writeStudent(raf);
s3.writeStudent(raf);
Student s= new Student();
raf.seek(0);
// 设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。 0 表示为指针偏移量的起始位置
for ( long j=0;j<raf.length();j=raf.getFilePointer()) //getFilePointer() 返回此文件中的当前偏移量
{
s.readStudent(raf);
System. out .println(s. num + ":" +s. name + ":" +s. score );
}
raf.close();
System. out .println();
System. out .println( "======================== 对象序列化 ========================" );
System. out .println();
System. out .println( "--------------------- 接口: serializable & externalizable---------------------" );
/* 对象序列化将 Java 对象的基本数据类型和图形通过在流中转换为字节流,用文件保存起来实现对象的持久存储
并在日后还原这个对象 如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象
当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量
某个类如果想要实现对象序列化,必须实现 serializable 或 externalizable 接口 */
/* 外界可默认调用实现对象序列化类所定义的私有 writeObject() 和私有 readObject() 的方法,此类方法特殊
不受访问权限控制,由外部类直接调用另一个类的私有方法 */
Employee e1= new Employee( "zhangsan" ,25,3000.50);
Employee e2= new Employee( "lisi" ,24,3200.40);
Employee e3= new Employee( "wangwu" ,27,3800.55);
FileOutputStream fos= new FileOutputStream( "C:/Test.txt" );
ObjectOutputStream oos= new ObjectOutputStream(fos);
// 构造一个对象输出流的对象
oos.writeObject(e1);
oos.writeObject(e2);
oos.writeObject(e3);
oos.close();
FileInputStream fis= new FileInputStream( "C:/Test.txt" );
ObjectInputStream ois= new ObjectInputStream(fis);
Employee e;
for ( int k=0;k<3;k++)
{
e=(Employee)ois.readObject();
System. out .println(e. name + ":" +e. age + ":" +e. salary );
}
ois.close();
}
}
class Producer extends Thread{ // 生产者类,发送信息
private PipedOutputStream pos ;
public Producer(PipedOutputStream pos) {
this . pos =pos;
}
public void run(){
try {
pos .write( " 欢迎学习孙鑫 java 教程 " .getBytes()); // 只能写入一个字节或字节数组
pos .close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable{ // 消费者类,接收信息
private PipedInputStream pis ;
public Consumer(PipedInputStream pis) {
this . pis =pis;
}
public void run() {
try {
byte [] buf3= new byte [100];
int len3= pis .read(buf3);
System. out .println( new String(buf3,0,len3));
} catch (IOException e) {
e.printStackTrace();
}
}
}
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 );
}
public void readStudent(RandomAccessFile raf) throws IOException
{
num =raf.readInt();
name =raf.readUTF();
score =raf.readDouble();
}
}
class Employee implements Serializable
{
String name ;
int age ;
double salary ;
transient Thread t = new Thread();
public Employee(String name, int age, double salary)
{
this . name =name;
this . age =age;
this . salary =salary;
}
private void writeObject(java.io.ObjectOutputStream oos) throws IOException
{
oos.writeInt( age );
oos.writeUTF( name );
oos.writeDouble( salary );
System. out .println( "Write Object" );
}
private void readObject(java.io.ObjectInputStream ois) throws IOException
{
age =ois.readInt();
name =ois.readUTF();
salary =ois.readDouble();
System. out .println( "Read Object" );
}
}