Java6-Java IO(File类、流、序列化)

1、 文件操作 File 类:文件和目录路径名的抽象表示。只能操作文件的属性,文件的内容是不能操作的。 (1)File类基本操作 4个static方法 System . out. println ( File . pathSeparator) ; //路径分割符字符:; System . out. println (

1、 文件操作

File 类:文件和目录路径名的抽象表示。只能操作文件的属性,文件的内容是不能操作的。
(1)File类基本操作

  • 4个static方法

      System.out.println(File.pathSeparator);   //路径分割符字符:;
      System.out.println(File.pathSeparatorChar);  //路径分割符:;
      System.out.println(File.separator); //名称分割符字符:\
      System.out.println(File.separatorChar); //名称分割符:\

(2)File类构造方法

        //1、从父路径名字符串和子路径名字符串创建新的 File实例
        // File(String parent ,String child)
        File f6 = new File("D:","IO\\a.txt");

        //2、通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
        //File(String pathname)
        File f5 = new File("D:"+File.separator+"IO"+File.separator+"a.txt");

        //3、从父抽象路径名和子路径名字符串创建新的 File实例
        // File(File parent ,String child)
        File f3 = new File("D:");
        File f4 = new File(f3,"IO");

        //4、将给定的file:URI转换为抽象路径来创建新的 File实例
       //File(URI uri);
       

(3)File类操作深入

  • 创建方法

 boolean createNewFile(); //不存在返回true 存在返回false
 boolean mkdir(); //创建目录,如果上一级目录不存在,则会创建失败
 boolean mkdirs(); //创建多级目录,如果上一级目录不存在也会自动创建

  • 删除方法

boolean delete(); //删除文件或目录,如果表示目录,则目录下必须为空才能删除
boolean deleteOnExit(); //文件使用完成后删除

  • 判断方法

boolean canExecute();  //判断文件是否可执行
boolean canRead();  //判断文件是否可读
boolean canWrite();   //判断文件是否可写
boolean exists();   //判断文件或目录是否存在
boolean isDirectory();  //判断此路径是否为一个目录
boolean isFile();  //判断是否为一个文件
boolean isHidden();  //判断是否为隐藏文件
boolean isAbsolute();  //判断是否是绝对路径 文件不存在也能判断

  • 获取方法

String getName(); //获取此路径表示的文件或目录名称
String getPath(); //将此路径名转换为路径名字符串
String getAbsolutePath(); //返回此抽象路径名的绝对形式
String getParent(); //如果没有父目录返回null
long lastModified(); //获取最后一次修改的时间
long length(); //返回由此抽象路径名表示的文件的长度。
boolean renameTo(File f); //重命名由此抽象路径名表示的文件。
File[] liseRoots();//获取机器盘符
String[] list();  //返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。
String[] list(FilenameFilter filter); //返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录。

(4)操作练习

  • 创建一个指定文件的文件

 //从父抽象路径名和子路径名字符串创建新的 File实例。
        File dir = new File("D:"+File.separator+"IO");
        File file = new File(dir,"a.txt");

        //判断dir 是否存在且表示一个目录
        if(!(dir.exists()||dir.isDirectory())){
            //不存在,则创建
            dir.mkdirs();
            //创建 a.txt文件
            file.createNewFile(); //抛出异常
        }
        //返回由此抽象路径名表示的文件或目录的名称。
        System.out.println(file.getName()); //a.txt
        //返回此抽象路径名的父null的路径名字符串,如果此路径名未命名为父目录,则返回null。
        System.out.println(file.getParent());//D:\IO
        //将此抽象路径名转换为路径名字符串。
        System.out.println(file.getPath()); //D:\IO\a.txt
  • 给定目录下的所有文件夹和文件夹里面的内容
public static void getFileList(File file){
        //第一级子目录
        File[] files = file.listFiles();
        for(File f:files){
            //打印目录和文件
            System.out.println(f);
            if(f.isDirectory()){
                getFileList(f);
            }
        }
    }
public static void main(String[] args) throws Exception {
        File f = new File("D:"+File.separator+"WebStormFile");
        getFileList(f);
    }

2、字符流与字节流

(1)流的基本概念

  • IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式。

  • 按方向分为输入流和输出流。以内存为参照,数据从数据源中读取到内存为输入流,反之为输出流。

  • 流按照类型分,分为字节流、字符流和对象流。数据的传输都是以字节为单位传输。所以其本质都是字节流。

(2)OutputStream字节输出流

  • OutputStream类是Java IO API中所有输出流的基类。子类包括以下内容。
OutputStream //以字节为单位的输出流的超类,提供了write()函数从输出流中读取字节数据。

ByteArrayOutputStream  //字节数组输出流,写入ByteArrayOutputStream的数据被写入到一个byte数组,缓冲区会随着数据的不断写入而自动增长,可使用toByteArray()和toString()获取数据。

PipedOutputStream  //管道输出流,和PipedInputStream一起使用,能实现多线程间的管道通信。

FilterOutputStream  //过滤输出流,是DataOutputStream,BufferedOutputStream和PrintStream的超类

DataOutputStream  //数据输出流,用来装饰其他的输出流,允许应用程序以与机器无关方式向底层写入基本Java数据类型。

BufferedOutputStream  //缓冲输出流,它的作用是为另一个输出流添加缓冲功能。

PrintStream  //打印输出流,用来装饰其他输出流,为其他输出流添加功能,方便的打印各种数据值

FileOutputStream  //文件输出流,通常用于向文件进行写入操作。

ObjectOutputStream  //对象输出流,它和ObjectInputStream一起对基本数据或者对象的持久存储。

总结

  • OutputStream是一个典型的装饰者模式,使用的时候直接new子类。

  • OutputStream可以输出到console,文件,磁盘等目标媒介中。

示例

public static void main(String args[]) throws Exception
{
    // 第1步、使用File类找到一个文件
    File f = new File("d:\\51gjie.txt"); // 声明File对象
    // 第2步、通过子类实例化父类对象
    OutputStream out = null; // 准备好一个输出的对象
    try
    {
        out = new FileOutputStream(f); // 通过对象多态性,进行实例化
        // 第3步、进行写操作
        String str = "欢迎来到www.51gjie.com"; // 准备一个字符串
        byte b[] = str.getBytes(); // 只能输出byte数组,所以将字符串变为byte数组
        out.write(b); // 将内容输出,保存文件
    }
    catch(IOException e)
    {}
    finally
    {
        out.close(); // 关闭输出流
    }
}

(3)InputStream字节输入流

此抽象类是表示字节输入流的所有类的超类。需要定义 InputStream 子类的应用程序必须总是提供返回下一个输入字节的方法。

BufferedInputStream  // 提供了缓冲功能。 

DataInputStream  // 允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。 

PipedInputStream  // 允许以管道的方式来处理流。当连接到一个PipedOutputStream后,它会读取后者输出到管道的数据。 

PushbackInputStream  // 允许放回已经读取的数据。 

SequenceInputStream  // 能对多个inputstream进行顺序处理。

示例

public class InputStreamDemo01{
    public static void main(String args[]) throws Exception{    // 异常抛出,不处理
        // 第1步、使用File类找到一个文件
        File f= new File("d:" + File.separator + "test.txt") ;    // 声明File对象
        // 第2步、通过子类实例化父类对象
        InputStream input = null ;    // 准备好一个输入的对象
        input = new FileInputStream(f)  ;    // 通过对象多态性,进行实例化
        // 第3步、进行读操作
        byte b[] = new byte[1024] ;        // 所有的内容都读到此数组之中
        input.read(b) ;        // 读取内容   网络编程中 read 方法会阻塞
        // 第4步、关闭输出流
        input.close() ;                        // 关闭输出流
        System.out.println("内容为:" + new String(b)) ;    // 把byte数组变为字符串输出
    }
};

总结

  • 一个从流中读取数据的组件尝试用InputStream替代任何它的子类(比如FileInputStream)进行开发。能够让兼容任何类型而非某种确定类型的输入流。

  • Java中的Inputstream是不能重复读取的,读取是单向的。有一个pos指针指示每次读取之后下一次要读取的起始位置,当读到最后一个字符的时候,pos指针不会重置。
    *在这里插入图片描述

(4)Writer字符输出流

  • Writer类是Java IO中所有Writer的基类。
BufferedWriter  //字符缓冲输出流
FileWriter  //用来写入字符串到文件
OutputStreamWriter   //转换流:写入字符,同时可以设置编码集。
  • 例子
public class WriterDemo01{
    public static void main(String args[]) throws Exception{    // 异常抛出,不处理
        // 第1步、使用File类找到一个文件
        File f= new File("d:" + File.separator + "test.txt") ;    // 声明File对象
        // 第2步、通过子类实例化父类对象
        Writer out = null ;    // 准备好一个输出的对象
        out = new FileWriter(f)  ;    // 通过对象多态性,进行实例化   
        // 第3步、进行写操作
        String str = "Hello World!!!" ;        // 准备一个字符串
        out.write(str) ;                        // 将内容输出,保存文件
        // 第4步、关闭输出流
        out.close() ;                        // 关闭输出流
        //public class FileWriter extends OutputStreamWriter
        //public class OutputStreamWriter extends Writer    FileWriter实际上继承自 OutputStreamWriter
    }
};

(5)Reader字符输入流

  • Reader是一个抽象类,它是以字符为单位的输入流的公共父类。
BufferedReader //从流里面读取文本,通过缓存的方式提高效率,读取的内容包括字符、数组和行。缓存的大小可以指定,也可以用默认的大小,大部分情况下,默认大小就够了。

InputStreamReader //转换流:把字节翻译成字符的,可以处理乱码问题。

FileReader //方便读取字符文件的。
  • 使用read()读取单个字符并输出
import java.io.*;
class FileReaderDemo
{
    public static void sop(Object obj)
    {
        System.out.print(obj);
    }
    public static void main(String[] args)throws IOException
    {
      //创建一个文件读取流对象,和指定名称的文件相关联起来。
      //要保证该文件是已经存在的。如果不存在,会发生异常,即FileNotFoundException    
      FileReader fr = new FileReader("F:\\myfile\\test.txt");
      
      //调用读取流对象的read方法。
      //read方法:一次读取一次字符,而且会自动往后面读取字符。
      int ch = 0;
      while((ch=fr.read())!=-1)
      {
          sop((char)ch);
      }
     
     /*
     while(true)
      {
        int ch = fr.read();
        if(ch==-1)
            break;
         sop((char)ch);  //读取文件中的一个字符 
      }
    */
      fr.close();
    }
}

在这里插入图片描述

(6)字节流与字符流的区别

  • 字符流使用了缓冲区,而字节流没有使用缓冲区;

详细API学习路径:http://www.51gjie.com/java/695.html

3、序列化与反序列化

  • Java 对象序列化就是把对象写入到输出流中,用来存储或传输;反序列化就是从输入流中读取对象;
  • 序列化是基于字节的,不能使用基于字符的流;

(1)实现

  • 枚举类型对象都是默认可以被序列化的
// Gender类,表示性别
// 每个枚举类型都会默认继承类java.lang.Enum,而Enum类实现了Serializable接口,所以
public enum Gender {  
    MALE, FEMALE  
} 
  • 实现了 java.io.Serializable 接口序列化
// Person 类实现了 Serializable 接口,它包含三个字段。另外,它还重写了该类的 toString() 方法,以方便打印 Person 实例中的内容。
public class Person implements Serializable {  
    private String name = null;  
    private Integer age = null;  
    private Gender gender = null;  

    public Person() {  
        System.out.println("none-arg constructor");  
    }  
 
    public Person(String name, Integer age, Gender gender) {  
        System.out.println("arg constructor");  
        this.name = name;  
        this.age = age;  
        this.gender = gender;  
    }  
 
    // 省略 set get 方法
    @Override 
    public String toString() {  
        return "[" + name + ", " + age + ", " + gender + "]";  
    }  
} 
  • 序列化程序示例
// SimpleSerial类,是一个简单的序列化程序,它先将Person对象保存到文件person.out中,然后再从该文件中读出被存储的Person对象,并打印该对象。
public class SimpleSerial {  
    public static void main(String[] args) throws Exception {  
        File file = new File("person.out");  
        ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file)); // 注意这里使用的是 ObjectOutputStream 对象输出流封装其他的输出流
        Person person = new Person("John", 101, Gender.MALE);  
        oout.writeObject(person);  
        oout.close();  
 
        ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));  // 使用对象输入流读取序列化的对象
        Object newPerson = oin.readObject(); // 没有强制转换到Person类型  
        oin.close();  
        System.out.println(newPerson);  
        //arg constructor  
        //[John, 31, MALE]
    }  
} 

  • 序列化一个对象首先要创造某些OutputStream对象(如FileOutputStream、ByteArrayOutputStream等),然后将其封装在一个ObjectOutputStream对象中,在调用writeObject()方法即可序列化一个对象;

  • 反序列化的过程需要创造InputStream对象(如FileInputstream、ByteArrayInputStream等),然后将其封装在ObjectInputStream中,在调用readObject()即可;

  • String类型的对象、枚举类型的对象、数组对象,都是默认可以被序列化的;

(2)transient关键字

  • 有些时候不能使用默认序列化机制。当类的某个字段被 transient 修饰,默认序列化机制就会忽略该字段。此处将Person类中的age字段声明为transient,如下所示:
public class Person implements Serializable {  
    ...  
    transient private Integer age = null;  
    ...  
} 
// 再执行SimpleSerial应用程序,会有如下输出:
//arg constructor  
//[John, null, MALE]
知秋君
上一篇 2024-07-23 15:02
下一篇 2024-07-23 14:36

相关推荐