JAVA- IO流

目录流的分类文件流案例一:FileReaderFileWriter文件复制FileInputStream非文本文件复制( FileInputStream、FileOutputStream)缓冲流非文本文件复制 BufferedInputStream、BufferedOutputStream文本复制(BufferedReader、BufferedWriter)文件加密转换流字符集标准输入输出流 \打印流\数据流对象流随机存取文件流JDK9新特性 NIO.2中Path、Paths、Files类的使用按数据单位分
摘要由CSDN通过智能技术生成

目录

File类 

File类的使用

构造器

 常用方法

IO流

流的分类

文件流

案例一:FileReader

FileWriter

文件复制

FileInputStream

非文本文件复制( FileInputStream、FileOutputStream)

缓冲流

非文本文件复制 BufferedInputStream、BufferedOutputStream

文本复制(BufferedReader、BufferedWriter)

文件加密

转换流

字符集

标准输入输出流 \打印流\数据流

对象流

随机存取文件流

JDK9新特性 

NIO.2中Path、Paths、Files类的使用


File类 

File类的使用

1、File类的一个对象,代表一个文件或一个文件目录(俗称文件夹)

2、 File类生命在java.io包下

3. File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,
    并未涉及到写入或读取文件内容的操作。如果需要读取或写入文件内容,必须使用I0流来完成。

4.后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的”终点".

构造器

 

 代码:输出文件路径,并没有创建文件

    public static void main(String[] args) {
        //构造器1:
        File file1=new File("hello.txt");  //相对路径,相对于当前nodule
        File file2=new File("D:\\IDEA项目\\hi.txt"); //绝对路径
        System.out.println(file1);//hello.txt
        System.out.println(file2);//D:\IDEA项目\hi.txt

        //构造器2
        File file3=new File("D:\\IDEA项目","1.txt");
        System.out.println(file3);//D:\IDEA项目\1.txt

        //构造器3
        File file4=new File(file3,"2.txt");
        System.out.println(file4);//D:\IDEA项目\1.txt\2.txt

    }

 常用方法

public String getAbsolutePath():获取绝对路径

public String getPath():获取路径

public String getName():获取名称

public String getParent():获取上层文件目录路径,若无,返回null

public Long Length():获取文件长度(字节数)。不能获取目录长度

public Long lastModified() :获取最后一次修改的时间,毫秒数

下面两个方法都适用于文件目录

public String[ ] List():获取指定目录下的所有文件或者文件目录的名称数组

public File[ ] ListFiles():获取指定目录下的所有文件或者文件目录的File数组

public boolean isDirectory():判断是否是文件目录

public boolean isFile() :判断是否是文件

public boolean exists():判断是否存在

public booLean canRead() :判断是否可读

public boolean canWrite():判断是否可写

public boolean isHidden() :判断是否隐藏

 移动文件:

public boolean renameTo(File dest):把文件重命名为指定的文件路径

比如:file1.renameTo(file2)为例,将file1重命名为file2

要想保证返回true,需要file1在硬盘中是存在的,file2是不存在的

创建硬盘中对应的文件或文件目录

public boolean createNewFile() :创建文件。若文件存在,则不创速,返回false

public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建

public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建

删除磁盘中的文件或文件目录
public boolean delete(): 删除文件或者文件夹

删除文件夹时必须先把文件夹内的文件删光才可以删除文件夹
删除注意事项:
Java中的删除不走回收站。

 代码:

    public static void main(String[] args) throws IOException {
        File file1 = new File("hi.txt");
        if (!file1.exists()) {
            file1.createNewFile();
            System.out.println("创建成功");
        } else {//文件存在
        file1.delete();
        System.out.println("删除成功");
    }

IO流

流的分类

按数据单位分为字节流和字符流

按照流向分为输入流和输出流

按照角色为节点流和处理流

                                                                  IO流体系

文件流

访问文件的那行是节点流 (文件流)

FileInputStream 方法: ( read(byte[ ]  buffer) )

FileOutputStream  方法: ( write(byte[ ]  buffer,0,len) )

FileReader  方法: ( read(char[ ]  cbuf) )

FileWrite 方法: ( write(char[ ]  cbuf,0,len) )

案例一:FileReader

read():返回读入的一个字符,如果达到文件末尾返回-1

异常的处理,要用到try-catch-finally,否则流出异常会无法关闭,或者没有读取到文件时关闭时空指针异常。

读入的文件不存在会出现FileNotFoundException

 FileReader fileReader = null;
        try {
            File file = new File("D:\\IDEA项目\\day106\\hello.txt");

            //提供具体的流
            fileReader = new FileReader(file);

            //数据读入
            //read():返回读入的一个字符,如果达到文件末尾返回-1
            int data = fileReader.read();
            while (data != -1) {
                System.out.print((char) data);
                data = fileReader.read();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、回收流
            try {
                if(fileReader!=null) //判断不为空才释放
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

 read()的重载:read(char[] cbuf):返回每次读入cbuf数组中每个字符的个数,达到文件末尾,返回-1。

注意:cbuf [ 5 ] 数组每次从file中读取5个字符,如果文件中剩余字符不足五个,那就把从0开始读进数组中,但是数组后面的上次读取的数据不会清空。

例:helloworld123,输出的字符数组分别为hello   world   123ld

FileWriter

从内存中写出数据到硬盘的文件里

 1、输出操作,对应的File可以不存在,并不会报异常

2、File对应的硬盘中文件如果不存在,在输出的过程中,会自动创建此文件

      File对应的硬盘中文件如果存在:

              如果构造器是FileWriter(file,false)/ FileWriter(file):对原有文件覆盖

               如果流使用的构造器是FileWriter(file,true):不会对原文件覆盖,而是在原文件上追加

public static void main(String[] args) {
        FileWriter fw = null;
        try {
            //1、提供File类对象,指明写出到的文件
            File file = new File("hello1.txt");

            //2、提供FileWriter对象,用于数据写出
            fw = new FileWriter(file);

            //3、写出操作
            fw.write("hello!");
            fw.write("hello!");

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //4、资源关闭
            try {
                if(fw!=null)
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

文件复制

例:从一个文件中读取内容放入另一个文件中

注:不能使用字符流处理字节文件(例如图片)

public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;

        try {
            //1、提供File类对象,指明写出\读入的文件
            File file1 = new File("hello.txt");
            File file2 = new File("hello1.txt");

            //2、提供FileWriter\FileReader对象,用于数据写出\读入
            fr = new FileReader(file1);
            fw = new FileWriter(file2);

            //3、操作
            char[] cbuf = new char[5];
            int len;  //记录每次读取到cbuf数组中的长度
            while ((len = fr.read(cbuf)) != -1) {//判断没有读取到末尾
                fw.write(cbuf, 0, len); //读取数组中 [0,len)的字符
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、关闭流
            try {
                if (fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

FileInputStream

操作与字符流一致 

读取文件,如果文件中有中文,可能会出现乱码,因为中文使用3个byte存储的(在UTF-8中),无法完整读出

 总结:

文本文件(.txt | .java |.c |.cpp)用字符流处理

非文本文件(.jpg | .avi | .mp3 | .doc | .ppt ...)用字节流处理

public static void main(String[] args) {
        FileInputStream fis= null;
        try {
            //1、造文件
            File file=new File("hello.txt");

            //2、造流
            fis = new FileInputStream(file);

            //3、读数据
            byte[] buf=new byte[5];
            int len;
            while((len=fis.read(buf))!=-1){
                String s=new String(buf,0,len);
                System.out.println(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、关闭流
            try {
                if(fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

非文本文件复制( FileInputStream、FileOutputStream)

public class IOTest {
    public static void main(String[] args) {
       long start= System.currentTimeMillis();
        String srcPath = "美女.jpg";
        String destPath = "美女2.jpg";
        copyFile(srcPath, destPath);
        long end= System.currentTimeMillis();
        System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 246 毫秒
    }
    public static  void copyFile(String srcPath,String destPath){
        FileInputStream fis= null;
        FileOutputStream fos= null;
        try {
            //1、造文件
            File srcfile=new File(srcPath);
            File destfile=new File(destPath);

            //2、造流
            fis = new FileInputStream(srcfile);
            fos = new FileOutputStream(destfile);


            //3、读数据
            byte[] buf=new byte[5];
            int len;
            while((len=fis.read(buf))!=-1){
                fos.write(buf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、关闭流
            try {
                if(fis!=null)
                    fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fos!=null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

缓冲流

处理流之一:套接在已有流上的流 

BufferInputStream 方法:( read(byte[ ] buffer) )

BufferOutputStream 方法:( write(byte[ ] buffer,0,len) / flush())

BufferReader 方法:( read(byte[ ] cbuf) / readLine() )

BufferWriter 方法:( write(char[ ] cbuf,0,len) / flush() )

flush()方法:刷新缓冲区,先把缓冲区中的内容写出去

对比字节流,缓冲流的速度快很多,因为缓冲流内部提供了缓冲区 。

例如:

非文本文件复制 BufferedInputStream、BufferedOutputStream

public class IOTest {
    public static void main(String[] args) {
        long start= System.currentTimeMillis();
        String srcPath = "美女.jpg";
        String destPath = "美女2.jpg";
        copyFile(srcPath, destPath);
        long end= System.currentTimeMillis();
        System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 44 毫秒
    }
    public static void copyFile(String srcPath, String destPath) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        BufferedInputStream bis = null;
        try {
            //1、造文件
            File srcfile = new File(srcPath);
            File destfile = new File(destPath);

            //2.1、造节点流
            fis = new FileInputStream(srcfile);
            fos = new FileOutputStream(destfile);
            //2.2 造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            //3、读数据
            byte[] buf = new byte[10];
            int len;
            while ((len = bis.read(buf)) != -1) {
                bos.write(buf, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、关闭流,先关外层,再关内层
            try {
                if(bos!=null)
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(bis!=null)
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            //关闭外层流的同时内层流也会自动关闭,所以内层流关闭可省略
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

文本复制(BufferedReader、BufferedWriter)

public class IOTest {
    public static void main(String[] args) {
        long start= System.currentTimeMillis();
        String srcPath = "hello.txt";
        String destPath = "hello1.txt";
        copyFile(srcPath, destPath);
        long end= System.currentTimeMillis();
        System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 2 毫秒
    }
    public static void copyFile(String srcPath, String destPath) {
        BufferedWriter bw = null;
        BufferedReader br = null;
        try {

            //1、造文件 2.1、造节点流 2.2 造缓冲流
            br = new BufferedReader(new FileReader(new File(srcPath)));
            bw = new BufferedWriter(new FileWriter(new File(destPath)));

            //3、读数据
            //方式一:
//            char[] buf = new char[10];
//            int len;
//            while ((len = br.read(buf)) != -1) {
//                bw.write(buf, 0, len);
//            }
            //方式二:
            String data;
            while((data=br.readLine())!=null){
                //方法一:
                bw.write(data+"\n");//data不包含换行符,可以手动加入
                //方法二:
                bw.write(data);
                bw.newLine(); //换行
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、关闭流,关外层,内层自动关闭
            try {
                if(bw!=null)
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(br!=null)
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}

文件加密

在write写入之前,让读取的数据异或一个值,然后会读取到异或后的数据,相当于加密过程

解密时,将加密过的文件读取到的数据再次异或该值,就会变成加密前的数据。

例如:

public class IOTest {
    public static void main(String[] args) {
        long start= System.currentTimeMillis();
        String srcPath = "hello.txt";
        String destPath = "hello1.txt";
        copyFile(srcPath, destPath);
        long end= System.currentTimeMillis();
        System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 1 毫秒
    }
    public static void copyFile(String srcPath, String destPath) {
        BufferedWriter bw = null;
        BufferedReader br = null;
        try {

            //1、造文件 2.1、造节点流 2.2 造缓冲流
            br = new BufferedReader(new FileReader(new File(srcPath)));
            bw = new BufferedWriter(new FileWriter(new File(destPath)));

//            3、读数据
            char[] buf = new char[10];
            int len;
            while ((len = br.read(buf)) != -1) {
                for(int i=0;i<len;i++)
                    buf[i]= (char) (buf[i]^5);
                bw.write(buf, 0, len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、关闭流,先关外层,再关内层
            try {
                if(bw!=null)
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(br!=null)
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}

 

加密后变为

 解密:只是将加密代码的文件名改了

public class IOTest {
    public static void main(String[] args) {
        long start= System.currentTimeMillis();
        String srcPath = "hello1.txt";
        String destPath = "hello2.txt";
        copyFile(srcPath, destPath);
        long end= System.currentTimeMillis();
        System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 2 毫秒
    }
    public static void copyFile(String srcPath, String destPath) {
        BufferedWriter bw = null;
        BufferedReader br = null;
        try {

            //1、造文件 2.1、造节点流 2.2 造缓冲流
            br = new BufferedReader(new FileReader(new File(srcPath)));
            bw = new BufferedWriter(new FileWriter(new File(destPath)));

//            3、读数据
            char[] buf = new char[10];
            int len;
            while ((len = br.read(buf)) != -1) {
                for(int i=0;i<len;i++)
                    buf[i]= (char) (buf[i]^5);
                bw.write(buf, 0, len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、关闭流,先关外层,再关内层
            try {
                if(bw!=null)
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(br!=null)
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}

解密后文件 

转换流

1、属于字符流,处理流之二 

2、InputStreamReader:将字节的输入流转换为字符的输入流

      OutputStreamWriter:将字符的输出流转换为字节的输出流

3、解码:字节、字节数组 --> 字符数组、字符串

     编码:字符数组、字符串 --> 字节、字节数组

4、字符集

例如:InputStreamReader利用字符集,实现字节输入流到字符输入流的转换

public static void main(String[] args) {
        InputStreamReader isr= null;
        try {
            //1、造文件
            FileInputStream fis=new FileInputStream("hello.txt");

            //2、造流
            //参数2指明了字符集,具体使用哪个字符集,取决于文件保存时使用的字符集
            isr = new InputStreamReader(fis,"UTF-8");

            //3、读取操作
            char[] cbuf=new char[20];
            int len;
            while ((len=isr.read(cbuf))!=-1){
                String s=new String(cbuf,0,len);
                System.out.print(s);hello中国
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
             //4、关闭流
            if(isr!=null) {
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

综合测试:InputStreamReader、OutputStreamWriter

 以UTF-8的字符集读取文件,以gbk的字符集写入数据(会出现乱码,读写字符集要保持相同才可以不乱码)

public static void main(String[] args) {
        InputStreamReader isr= null;
        OutputStreamWriter osw=null;

        try {
            FileInputStream fis=new FileInputStream("hello.txt");
            FileOutputStream fos=new FileOutputStream("hello_gbk.txt");
            //参数2指明了字符集,具体使用哪个字符集,取决于文件保存时使用的字符集
            isr = new InputStreamReader(fis,"UTF-8");
            osw = new OutputStreamWriter(fos,"gbk");

            char[] cbuf=new char[20];
            int len;
            while ((len=isr.read(cbuf))!=-1){
               osw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(isr!=null) {
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            try {
                if(osw!=null)
                osw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

字符集

ASCII:美国标准信息交换码。(英文够用)
           用一个字节的7位可以表示

ISO8859-1:拉丁码表。欧洲码表
           用一个字节的8位表示。

GB2312: 中国的中文编码表。最多两个字节编码所有字符

GBK: 中国的中文编码表升级,融合了更多的中文文字符号(包含简体繁体)。最多两个字节编码

          如何分辨两个字节存储的是一个字符还是两个字符?如果字节首位为0,表示该字节单独                存储一个字符,如果字节首位为1,表示两个字节存储一个字符

Unicode: 国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一 的字符码。所有文            字都可以用两个字节来完成。

          问题:1、英文用一个字节就够了

                     2、如何分辨两个字节存储的是一个字符还是两个字符?

                     3、如果和GBK一样的处理方式,字节首位被占用,那么就会少很多值来表示字符。

          互联网的出现解决了该问题:

           UTF-8的编码方式(Unicode字符集只是定义了字符的集合和位移编号,是对UTF_8等具体            编码方案的统称,不是具体的编码方案)

UTF-8: 变长的编码方式,可用1- 6个字节来表示一个字符。

          例:110xxxxx 10xxxxxxx,首位两个1代表要将两个个字节中的xxx拼凑到一起,然后按二进制方式拼成一个字符

         11110xxx 10xxxxxxx 10xxxxxx 10xxxxxx ,首位四个1代表要将四个字节中的xxx拼凑到一起,然后按二进制方式拼成一个字符

ANSI编码,通常指的是平台默认编码,英文操作系统默认是ISO8859-1,中文默认是GBK

标准输入输出流 \打印流\数据流

输入输出流

System.out:默认从控制台输出

System.in :默认从键盘输入

修改输入输出默认设备 

public static void setIn(InputStream in)

public static void setOut(OutputStream out)

打印流

PrintStream PrintWriter

提供了一系列重载的print、println等方法,用于多种数据类型的输出

不会抛IO异常

有自动flush功能

PrintStream打印的所有字符都使用平台的默认字符编码转换为字节,在需要写入字符的情况下,使用PrintWriter类

System.out返回的是类型

数据流

DataInputStream、DataOutputStream

用于读取或写出基本数据类型的变量或字符串

DatalnputStream 中的方法
boolean readBoolean()
byte readByte()
char readChar()
float readFloat()
double readDouble()
short readShort()
long readLong()
int readlnt()
String readUTF()
void readFully(byte[] b)

DataOutputStream中的方法,将上述方法read改为对应的write

将内存中的基本数据类型变量和字符串写入到文件

public static void main(String[] args) {
        dataWrite(); //写入
        dataread(); //读出
    }

    public static void dataWrite() {
        DataOutputStream dos = null;
        try {
            dos = new DataOutputStream(new FileOutputStream("hello.txt"));

            dos.writeUTF("老王");
            dos.flush();
            dos.writeInt(23);
            dos.flush();
            dos.writeBoolean(true);
            dos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                dos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void dataread() {
        DataInputStream dis = null;
        try {
            dis = new DataInputStream(new FileInputStream("hello.txt"));
            //按存储的顺序读取
            String name = dis.readUTF();
            int age = dis.readInt();
            boolean isMale = dis.readBoolean();
            System.out.println(name + " " + age + " " + isMale);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                dis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

对象流

ObjectInputStream ObjectOutputStream
存储和读取基本数据类型数据或对象的处理流,强大之处:可以把java对象写入数据源,也能把对象从数据源中还原回来

对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原来的Java对象

序列化:用ObjectOutputStream类保存基本类型数据或对象的机制

反序列化:ObjectInputStream类读取基本类型数据或对象的机制
不能序列化static 和transient修饰的成员变量

NotSerializableException异常:对象不可序列化
序列化的对象需满足以下要求:
1、必须实现两个接口之一:Serializable、Externalizable

      Serializable常用,且接口中没有方法,仅代表可序列化

2、必须声明一个全局常量public static final long seriaVersionUID=一个唯一的标识符

      如果没有显示声明,运行时根据类的内部自动生成,如果类做了改变,seriaVersionUID值会          修改,然后可能导致出现错误

3、除了序列化的类需要实现Serializable接口之外,还必须保证内部所有属性也必须是可序列化的      (默认情况下,基本数据类型可序列化,包括String)

       如果类内存在自定义类,则自定义类也需要实现Serializable接口和唯一标识符

对象的写入和读出

//序列化,将内存中的java对象写入文件中
    public  void objectOutputStreamTest() {
        ObjectOutputStream oos = null;
        try {
            //1、造文件
            FileOutputStream file = new FileOutputStream("java.dat");
            //2、造流
            oos = new ObjectOutputStream(file);
            //3、操作
            oos.writeObject(new String("我爱中国"));
            oos.flush();
            oos.writeObject(new Person("Tom", 22));
            oos.flush();
            oos.writeObject(new Person("Jerry", 22));
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、关闭流
            try {
                if (oos != null)
                    oos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public  void objectInputStreamTest() {
        ObjectInputStream ois = null;
        try {
            //1、造文件
            FileInputStream file = new FileInputStream("java.dat");

            //2、造流
            ois = new ObjectInputStream(file);

            //3、操作,按写入的顺序读取

            Object o1 = ois.readObject();
            String s = (String) o1;
            System.out.println(s);//我爱中国
            Object o2 = ois.readObject();
            Person p1 = (Person) o2;
            System.out.println(p1);Person{name='Tom', age=22}
            Object o3 = ois.readObject();
            Person p2 = (Person) o3;
            System.out.println(p2);Person{name='Jerry', age=22}
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            //4、关闭流
            try {
                if (ois != null)
                    ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

随机存取文件流

RandomAccessFile
java.io包下
1、实现了DataInput、DataOutput,两个接口,可以读也可以写,既可以作为输入流也可以作为输出流。
2、支持“随机访问”的方式,程序可以直接跳转到任意地方读写文件
    支持只访问文件的部分内容
    可以向已存在的文件后追加内容
    写文件时如果文件不存在可以自动创建文件
    如果文件已经存在,那么会从文件首部开始一个字符一个字符的覆盖

3、实例化需要制定一个mode参数,指定访问模式
   r:以只读方式打开
   rw:打开以便读取和写入
   rwd:打开以便读取和写入,同步文件内容的更新
   rws:打开以便读取和写入,同步文件内容和元数据的更新
4、内部存在指针,用来表示当前读写的位置,可以自由移动记录指针
   long getFilePointer():获取文件记录指针的当前位置
   void seek(long pos):将文件记录指针定位到pos位置

利用指针实现插入操作,先将指针移动到自己想插入数据的位置,再读取指针后面的内容存储到数组中,然后写入自己想插入的数据,再将保存在数组中的数据写入文件(比较费内存,因为要存储后面的内容)

public static void insertRandomAccessFileTest(){
         RandomAccessFile raf= null;
         try {
             //造文件、造流
             raf = new RandomAccessFile("hello.txt","rw");
             //操作
             //指针调整到索引为2的位置
             raf.seek(2);
             //指针后面的数据先保存在StringBuffer中
             StringBuffer sb=new StringBuffer("hello.txt".length());
             byte[] buf=new byte[20];
             int len;
             while((len=raf.read(buf))!=-1){
                 //StringBuffer的append不能添加byte类型,所以先用字符串封装
                  sb.append(new String(buf,0,len));
             }
             //指针再次移向2,开始写入
             raf.seek(2);
             raf.write("I love you".getBytes());
             //StringBuffer没有getBytes方法,所以先转换为String
             raf.write(sb.toString().getBytes());
         } catch (IOException e) {
             e.printStackTrace();
         } finally {
             //关闭流
             try {
                 if(raf!=null)
                 raf.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
    }

JDK9新特性 

InputStream的新方法tranferTo()
把输入流中的说有数据直接自动复制到输出流中

也就是将这一段代码


 //3、读数据
    byte[] buf=new byte[5];
    int len;
    while((len=fis.read(buf))!=-1){
          fos.write(buf,0,len);
    }

 替换为fis.transferTo(fos);

NIO.2中Path、Paths、Files类的使用

NIO.2在JDK1.7中发布,针对原有的文件IO操作进行了优化及封装,并支持Asynchronous IO。File类功能有限,大多数方法再出错时只返回失败但不提供异常信息
为了弥补这种不足,引入Path。
Paths包含两个返回Path的静态工厂方法
Path常用方法:

➢String toString():返回调用Path对象的字符串表示形式

➢boolean startsWith(String path) :判断是否以path路径开始

➢boolean endsWith(String path) :判断是否以path路径结束

➢boolean isAbsolute() :判断是否是绝对路径

➢Path getParent();返回Path对象包含整个路径,不包含Path对象指定的文件路径
➢Path getRoo():返回调用Path对象的根路径

➢Path getFileName(:返回与调用Path对象关联的文件名

➢int getNameCount( :返回Path根目录后面元素的数量

➢Path getName(int idx):返回指定索引位置idx的路径名称

➢Path toAbsolutePath():作为绝对路径返回调用Path对象

➢Path resolve(Path p):合并两个路径,返回合并后的路径对应的Path对象

➢File toFile():将Path转化为File类的对象

Paths类提供的静态get()方法用来获取Path对象:

➢static Path get(String first, String ... more):用于将多个字符串串连成路径➢static Path get(URI uri);返回指定uri对应的Path路径

java.nio.file.Files用于操作文件或目录的工具类

Files常用方法:

➢Path copy(Path src, Path dest, CopyOption ... how):文件的复制
➢Path createDirectory(Path path, FileAttribute<?> ... attr): 创建-一个目录➢Path createFile(Path path, FileAtribute<?> ... arr):创建一个文件
➢void delete(Path path):删除个文件/目录, 如果不存在, 执行报错
➢void deletelfExists(Path path): Path对应的文件/目录如果存在,执行删除➢Path move(Path src, Path dest, CopyOption..how):将src移动到dest位置➢long size(Path path):返回path指定文件的大小

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值