一、文件的创建
-------------------------------------------------------
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");
  }
}