java基础——IO流——20200616

尚硅谷_Java零基础教程-java入门必备-初学者基从入门到精通全套完整版(宋红康主讲) P577-619

(*)表示仅需了解

文章目录

  • 1. File类的使用
    • File类的实例化
      • *路径分隔符
    • File类的常用方法
  • 2. IO流原理及流的分类
    • 流的分类
  • 3. 节点流(或文件流)
    • FileReader类
      • read()每次读一个字符
      • read() 每次读多个字符
    • FileWriter
      • 复制文件:字符流
    • FileInputStream、FileOutputStream
      • 复制文件:字节流
  • 4. 缓冲流
    • BufferedInputStream 、BufferedOutputStream
      • 复制文件:有缓冲字节流包裹
    • BufferedReader、BufferedWriter
      • 复制文件:缓冲字符流
    • 缓冲流练习
  • 5. 转换流
      • 复制文件:改变编码方式
    • *字符集
      • 常见的编码表
  • 6. 标准输入、输出流(*)
      • 练习键盘输入字符串,进行操作
  • 7. 打印流(*)
    • PrintStream、 PrintWriter
      • 把标准输出流改成文件
  • 8. 数据流(*)
  • 9. 对象流
    • 对象的序列化
      • 序列化的过程
  • 10. 随机存取文件流(*)
    • RandomAccessFile类
      • 插入操作实现(无)
      • 多线程断点下载(无)
  • 11. NIO.2中Path、Paths、Files类的使用 (*)
    • Java NIO
    • Path、Paths、Files核心API

1. File类的使用

  • java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关。
  • File能新建、删除、重命名文件和目录,但File不能访问文件内容本身。如果要访问文件内容本身,则需要使用输入/输出流。
  • 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
  • File对象可以作为参数传递给流的构造器。

File类的实例化

// 构造器1
        String dir = "D:\\web\\IdeaProjects\\chunzhao\\";
        File file = new File("hello.txt");
        File file1 = new File(dir+"src\\learn\\others\\io\\hello.txt");

        System.out.println(file);//hello.txt
        System.out.println(file1);//D:\web\IdeaProjects\chunzhao\src\learn\others\io\hello.txt

        //构造器2
        File file2 = new File(dir , "src\\learn\\others\\io");
        System.out.println(file2);//D:\web\IdeaProjects\chunzhao\src\learn\others\io

        //构造器3
        File file3 = new File(file2, "hello.txt");
        System.out.println(file3);//D:\web\IdeaProjects\chunzhao\src\learn\others\io\hello.txt

*路径分隔符

  • 路径中的每级目录之间用一个路径分隔符隔开。
  • 路径分隔符和系统有关:
    • windows和DOS系统默认使用""
    • UNIX和URL默认使用"/"
    • Java程序支持跨平台,因此路径分隔符要慎用。
    • 为了解决这个隐患,File类提供了一个常量: public static final String separator。根据操作系统动态的提供分隔符。例如
new File("d:"+File.separator+"java"+File.separator+"demo1"+File.separator+"hello.txt")

File类的常用方法

  • File类的获取功能
    • getAbsolutePath
    • getPath
    • getParent
    • getName
    • length:文件长度(字节数)
    • lastModified:毫秒值。可以用时间相关类转化为显示时间
    • list:获取名称
    • listFiles:获取文件
System.out.println(file1.getAbsolutePath());
        //D:\web\IdeaProjects\chunzhao\world.txt   --创建文件之后-->  不变
        System.out.println(file1.getPath()); //world.txt  --创建文件之后-->  不变
        System.out.println(file1.getParent()); //null  ---> null
        System.out.println(file1.getName()); //world.txt  ---> world.txt
        System.out.println(file1.length()); //0  ---> 12
        System.out.println(file1.lastModified()); //0  ---> 1592209152962

File file = new File(this.dir);
        String[] list = file.list();

        for (String s:list) {
            System.out.println(s);
        }
//        .idea
//        chunzhao.iml
//        out
//        src
//        world.txt
        File[] files = file.listFiles();
        for (File f:files         ) {
            System.out.println(f);
        }
//        D:\web\IdeaProjects\chunzhao\.idea
//        D:\web\IdeaProjects\chunzhao\chunzhao.iml
//        D:\web\IdeaProjects\chunzhao\out
//        D:\web\IdeaProjects\chunzhao\src
//        D:\web\IdeaProjects\chunzhao\world.txt
  • File类的重命名功能
    • renameTo:重命名(可以移动路径)
File file1 = new File("world.txt");
        File file2 = new File(dir+"src\\learn\\others\\io\\world.txt");

        //移动文件路径:需要file1存在,file2不存在
        boolean renameTo = file1.renameTo(file2);
        System.out.println(renameTo);
  • File类的判断功能
    • isDirectory
    • isFile
    • isHidden
    • exists
    • canRead
    • canWrite
File file2 = new File("world.txt");
        File file1 = new File(dir+"src\\learn\\others\\io\\world.txt");


        //默认值(如果文件不存在)都为false
        System.out.println(file1.isAbsolute());
        System.out.println(file1.isDirectory());
        System.out.println(file1.isFile());
        System.out.println(file1.isHidden());
        System.out.println(file1.canRead());
        System.out.println(file1.canWrite());
        System.out.println(file1.canExecute());

  • File类的创建功能

    • createNewFile
    • mkdir:如果此文件目录存在或上层目录不存在,不创建。
    • mkdirs:多级目录
    • 如果没有写盘符,默认在项目路径下
  • File类的删除功能

    • delete:不走回收站,要注意目录下是否有文件
@Test
    public void test6(){
        File file = new File("newFile.txt");
        if (file.exists()){
            file.delete();
            System.out.println("删除文件成功");
            return;
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("创建文件成功");

    }
    @Test
    public void test7(){

        //目录
        File directory = new File("D:\\web\\IdeaProjects\\chunzhao\\src\\learn\\others\\io","newDir");
        if (directory.exists()){
            boolean delete = directory.delete();
            if (delete) {
                System.out.println("删除目录成功");
            }else {
                System.out.println("删除目录失败");
            }
            return;
        }

        boolean mkdir = directory.mkdir();
        if (mkdir){
            System.out.println("创建目录成功");
        }else {
            System.out.println("创建目录失败");
        }

例题1:计算指定目录所占的空间

@Test
    public void test1(){
        File file = new File("D:\\web\\IdeaProjects\\chunzhao\\src\\learn\\others\\io");
        System.out.println(calDirSize(file));
    }
    public long calDirSize(File dir){
        if (dir.isFile()) return dir.length();
        long len = 0;
        for (File f:dir.listFiles()) {
            len+=calDirSize(f);
        }
        return len;
    }

例题2:删除指定目录下的所有文件和目录。

2. IO流原理及流的分类

  • IO是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读写文件,网络通讯等。
  • java程序中,对数据的输入/输出操作以“流”的方式进行
  • java.io包下提供了各种“流”类和接口,用以获取不同种类 的数据,并通过标准的方法输入或输出数据。

输入输出是站在程序的角度来看:

  • 输入:读取外部数据(磁盘等存储设备的数据)到程序(内存)中。
  • 输出:将程序(内存)数据发送到外部设备中。

流的分类

  • 按操作数据单位分:字节流(8bit),字符流(16bit)
  • 按照流的流向分:输入流,输出流
  • 按流的角色分:节点流(作用在文件上的),处理流(包装流,在已有的流上包裹的流)
(抽象基类) 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
  • Java的IO流共涉及40多个类,主要是从4个抽象基类派生的。
  • 由这四个类派生出的子类名称都是以其父类名作为后缀的。(图中蓝色为常用类)
    java基础——IO流——20200616_第1张图片

3. 节点流(或文件流)

FileReader类

  1. read()的理解:返回读入的一个字符。如果到达文件末尾,返回-1
  2. 异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally
  3. 读入的文件一定要存在,否则就会报FileNotFoundException

read()每次读一个字符

对异常的不同处理,有3种写法:

@Test
    public void test1() throws IOException {
        //1. 实例化 File
        File file1 = new File("src\\learn\\others\\io\\world.txt");
        boolean exists = file1.exists();
        System.out.println(exists);
        if (!exists) return;

        //2. 提供具体的流
        FileReader fileReader = new FileReader(file1);
        //3. 数据读入(方式一)
//        int data = fileReader.read();
//        while (data!=-1){
//            System.out.println((char)data);
//            data = fileReader.read();
//        }
        //3. 数据读入(方式一 修改)
        int data;
        while ((data = fileReader.read()) != -1) {
            System.out.println((char) data);
        }


        //4.流的关闭
        fileReader.close();
    }

    @Test
    public void test2() {
        //1. 实例化 File
        File file1 = new File("src\\learn\\others\\io\\world.txt");

        //2. 提供具体的流
        FileReader fileReader = null;
        try {
            fileReader = new FileReader(file1);
            //3. 数据读入(方式一 修改)
            int data;
            while ((data = fileReader.read()) != -1) {
                System.out.println((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.流的关闭
            if (fileReader != null) {
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Test
    public void test3() {
        //1. 实例化 File
        File file1 = new File("src\\learn\\others\\io\\world.txt");
        //2. File流的实例化
        try (FileReader fileReader = new FileReader(file1)) {
            //3. 数据读入(方式一 修改)
            int data;
            while ((data = fileReader.read()) != -1) {
                System.out.println((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

read() 每次读多个字符

public void testRead1() {
        //1. File类实例化
        File file1 = new File("src\\learn\\others\\io\\world.txt");
        //2. File流的实例化
        try (FileReader fileReader = new FileReader(file1)) {
            //3. 读入操作
            char[] cbuf = new char[5];//每次读数据存到data空间。长度为5表示一次最多可读5个字符
            int len;
            while ((len = fileReader.read(cbuf)) != -1) {
                //正确方式一
                for (int i = 0; i < len; i++) {
                    System.out.print(cbuf[i]); //hello world!
                }
                //错误方式一
//                for (int i = 0; i < cbuf.length; i++) {
//                    System.out.print(cbuf[i]); //hello world!orl
//                }
                //错误方式二
//                String str = new String(cbuf);
//                System.out.print(str); //hello world!orl
                //正确方式二
                String str = new String(cbuf,0,len);
                System.out.print(str); //hello world!
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

FileWriter

  1. 输出操作,对应的File可以不存在,会自动创建。
  2. 如果流使用的构造器是FileWriter fileWriter = new FileWriter(file1,true); 不覆盖原有文件
  3. 如果流使用的构造器是FileWriter fileWriter = new FileWriter(file1,false);FileWriter fileWriter = new FileWriter(file1); 覆盖原有文件
//写出数据到文件
    @Test
    public void testFileWriter(){
        //1.File类
        File file1 = new File("src\\learn\\others\\io\\world.txt");
        //2. File流的实例化
        //FileWriter fileWriter = new FileWriter(file1,true)  不覆盖原有文件
        //FileWriter fileWriter = new FileWriter(file1,false) 覆盖原有文件
        try (FileWriter fileWriter = new FileWriter(file1,false)) {
            //3. 写出操作
            fileWriter.append("到此一游!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

复制文件:字符流

//复制一个文件的内容到另一个文件
    @Test
    public void copyContentBetweenFiles(){
        //1.File类
        File outFile = new File("src\\learn\\others\\io\\hello.txt");
        File inFile = new File("src\\learn\\others\\io\\world.txt");
//2. File流的实例化
        try (FileWriter fileWriter = new FileWriter(outFile,true);
             FileReader fileReader = new FileReader(inFile)) {
            //3. 读写操作
            fileWriter.write("\ncopy from "+inFile.getName());
            char[] buf = new char[5];
            int len ;
            while ((len=fileReader.read(buf))!=-1){
                String string = new String(buf,0,len);
                fileWriter.write(string);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

FileInputStream、FileOutputStream

  • 对于文本文件,使用字符流
  • 对于非文本文件,使用字节流

复制文件:字节流

从一个文件读取内容,复制到另一个文件

@Test
    public void testCopyFileStream(){
        // 1.造文件
        File file1 = new File(curPath, "杨慎.png");
        File file2 = new File(curPath, "hello.txt");

        File inFile = file2;
        File outFile = new File(curPath,"copy of-"+inFile.getName());
        // 2. 流类
        try(FileInputStream inputStream = new FileInputStream(inFile);
            FileOutputStream outputStream = new FileOutputStream(outFile)){
            //3. 读写数据
            byte[] buf = new byte[10];
            int len;
            while ((len = inputStream.read(buf)) != -1) {
                outputStream.write(buf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4. 缓冲流

  • 缓冲流是为了提高文件读写效率:内部提供了一个缓冲区。
  • 逻辑上,先关缓冲流,再关文件流。操作中,关闭外层流的同时,内层流也会自动进行关闭,因此不用再手动关闭。
  • 内部有缓冲器,不用在外部写了: bos.write(bis.readAllBytes())
  • flush:刷新

BufferedInputStream 、BufferedOutputStream

复制文件:有缓冲字节流包裹

@Test
    public void testCopyFileStream(){
        // 1.造文件
        File file1 = new File(curPath, "杨慎.png");
        File file2 = new File(curPath, "hello.txt");

        File inFile = file1;
        File outFile = new File(curPath,"copy of-"+inFile.getName());
        // 2. 流类
        try(
                // 2.1造节点流
                FileInputStream inputStream = new FileInputStream(inFile);
            FileOutputStream outputStream = new FileOutputStream(outFile);
                // 2.2造缓冲流
            final BufferedInputStream bis = new BufferedInputStream(inputStream);
            final BufferedOutputStream bos = new BufferedOutputStream(outputStream)){
            //3. 读写数据
//            byte[] buf = new byte[1024];
//            int len;
//            while ((len = bis.read(buf)) != -1) {
//                bos.write(buf,0,len);
//            }
            //内部有缓冲器,不用在外部写了
            bos.write(bis.readAllBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

BufferedReader、BufferedWriter

复制文件:缓冲字符流

BufferedReader和BufferedWriter的按行读数据


            String data;
            while ((data= bf.readLine())!=null){
                bw.write(data);
                bw.newLine();//提供换行操作
            }

缓冲流练习

  1. 实现图片加密:write(read()^5)
  2. 获取文本上每个字符出现的次数:用map

5. 转换流

  • 转换流提供了在字节流和字符流之间的转换
  • InputStreamReader:将一个字节的输入流转换为字符的输入流
  • OutputStreamWriter:将一个字节的输出流转换为字符的输出流

复制文件:改变编码方式

  • 把字节输入流转换成字符输入流,按照编码方式1;
  • 把字节输出流转换成字符输出流,按照编码方式2;
  • 输入流读取数据,写入输出流。
@Test
    public void test1(){
        String str1 = curPath+"hello.txt";
        String str2 = curPath+"杨慎.txt";
        try (
            final InputStreamReader isr = new InputStreamReader(new FileInputStream(str1),"UTF-8");
            final OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(str2),"GBK");
            )
        {
            char[] cbug = new char[1024];
            int len;
            while ((len=isr.read(cbug))!=-1){
                osw.write(cbug,0,len);
            }
        }catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

*字符集

常见的编码表

  • ASCII:美国标准信息交换码(一个字节的7位)

  • ISO8859-1:拉丁码表,欧洲码表(一个字节的8位)

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

  • GBK:中国的中文编码表升级。最多两个字节编码所有字符

  • Unicode:国际标准码,融合了目前人类使用的所有字符。位每个字符分配唯一的字符码。两个字节来表示。

  • UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。(修正的UTF-8编码最多可能需要6个字节)

  • Unicode不完美,有三个问题:1. 英文字母一个字节表示就够了, 2.如何才能区分Unicode和ASCII? 计算机怎么知道两个字节表示一个符号,而不是分别表示两个符号?3. 如果和GBK等双字节编码方式一样,用最高位是1或0来表示两个字节和一个字节,就少了很多可用的值,两个字节不够表示所有字符。Unicode在很长一段时间内无法推广,直到互联网的出现。

  • 面向传输的众多UTF(UCS Transfer Format)标准出现了。UTF-8就是每次8个位传输数据,UTF-16就是每次16位。这是为传输而设计的编码,并使编码无国界,这样就可以显示全世界所有文化的字符了。

  • Unicode只是定义了一个庞大的、全球通用的字符集,并为每个字符规定了唯一确定的编号,具体存储成什么样的字节流,取决于字符编码方案。推荐的Unicode编码是UTF-8和UTF-16。

java基础——IO流——20200616_第2张图片

  • ANSI编码,通常指的是平台的默认编码。例如英文操作系统中是ISO-8859-1,中文系统是GBK
  • Unicode编码,是对UTF-8、UCS-2/UTF-16等具体编码方案的统称,并不是具体的编码方案。

6. 标准输入、输出流(*)

System.in、System.out

练习键盘输入字符串,进行操作

从键盘输入字符串,要求将读到的整行字符转化为大写输出,然后继续输入,知道输入"e" 或"exit"退出

try(final InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);)
        {
            System.out.println("请输入字符串:");
            while (true) {
                String data = br.readLine();
                if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) {
                    System.out.println("程序结束");
                    break;
                }
                System.out.println(data.toUpperCase());
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }

7. 打印流(*)

  • 实现将基本数据类型的数据格式转化为字符串输出
  • 打印流:PrintStream和 PrintWriter
    • 提供了一系列重载的print()和println()方法,用于多种数据类型的输出
    • PrintStream和 PrintWriter的输出不会抛出IOException异常
    • PrintStream和 PrintWriter有自动flush功能
    • PrintStream打印的所有字符都默认使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter。
    • System.out返回的是PrintStream的实例。

PrintStream、 PrintWriter

把标准输出流改成文件

@Test
    public void test2(){
//        PrintStream ps = null;
        String str = "src\\learn\\others\\io\\PrintStream.txt";
        try (final FileOutputStream fos = new FileOutputStream(new File(str));
             PrintStream ps = new PrintStream(fos,true)){
            if (ps!=null){//把标准输出流改成文件
                System.setOut(ps);
            }

            for (int i = 0; i < 256; i++) {
                System.out.print((char) i );
                if (i%10==0){
                    System.out.println();//换行
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

8. 数据流(*)

  • 为了方便地操作java语言的基本数据类型和String的数据,可以使用数据流
  • 数据流有两个类(用于读取和写出基本数据类型、String类的数据):
    • DataInputStream和DataOutputStream
    • 分别“套接”在InputStream和OutputStream子类的流上
  • DataInputStream的方法:
    • readBoolean()
    • readChar()
    • readByte()
  • DataOutputStream的方法:
    • writeBoolean()
    • writeChar()
    • writeByte()

输入输出测试

@Test
    public void test3() throws IOException {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
        dos.writeUTF("数据输出流");
        dos.flush();
        dos.writeInt(23);
        dos.flush();
        dos.writeBoolean(true);
        dos.flush();

        dos.close();
    }

    @Test
    public void test4() throws IOException {
        DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
        System.out.println(dis.readUTF());
        System.out.println(dis.readInt());
        System.out.println(dis.readBoolean());

        dis.close();
    }

9. 对象流

  • ObjectInputStream和ObjectOutputStream
  • 用于存储和读取基本数据类型和对象的处理流。它的强大之处就是可以把java中的对象写入到数据源中,还能把对象还原回来。
  • 序列化:用ObjectOutputStream类保存基本数据类型或对象的机制。
  • 凡序列化:用ObjectInputStream类读取基本数据类型或对象的机制
  • ObjectInputStream和ObjectOutputStream不能序列化statictransient修饰的成员变量。

对象的序列化

  • 对象序列化机制允许把内存中的java对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在硬盘上(序列化),或通过网络把这种二进制流传输到另一个网络节点。当其他程序获取了这种二进制流,就可以恢复成原来的java对象(反序列化)
  • 序列化的好处是可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原
  • 序列化是RMI(Remote Method Invoke——远程方法调用)过程的参数和返回值都必须实现的机制,而RMI是JavaEE的基础。因此序列化机制 是JavaEE平台的基础。
  • 如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现以下两个接口之一。
    • Serializable
    • Externalizable
  • 凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量
    • private static final long serialVersionUID
    • serialVersionUID用来表明类的不同版本间的兼容性。其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容
    • 如果类没有显式定义这个静态变量,它的值是java运行时环境根据类的内部细节自动生成的。若类的实例变量做了改变,serialVersionUID可能会发生变化,因此,建议显式声明。
  • 简单来说,java的序列化机制是通过在运行时判断类serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID和本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会报InvalidCastException异常。

序列化的过程

  1. 需要实现接口Serializable
  2. 当前类需要一个全局常量private static final long serialVersionUID
  3. 当前类内部所有属性也必须是可序列化的。(默认情况下,基本数据类型和String是可序列化的)
  4. static和transient修饰的不会被序列化

10. 随机存取文件流(*)

RandomAccessFile类

  • RandomAccessFile声明在java.io包下,但直接继承于Object类。并且它实现了DataInput、DataOutput这两个接口,也就意味着这个类既可以读也可以写。
  • RandomAccessFile类支持“随机访问”的方式,程序可以直接跳到文件的任意地方来读、写文件
    • 支持只访问文件的部分内容
    • 可以向已存在的文件后追加内容
  • RandomAccessFile对象包含一个记录指针,用以标示当前读写处的位置。
  • RandomAccessFile类对象可以自由移动记录指针:
    • accessFile.getFilePointer(); 获取指针当前位置
    • accessFile.seek(long pos); 指定指针当前位置
  • 构造器:
    • new RandomAccessFile(new File(str),“rw”);
  • 创建类实例需要指定一个mode参数,该参数决定访问模式:
    • r / rw /
    • rwd :同步文件内容的更新
    • rws :同步文件内容和元数据的更新。
  • 如果为r,则不会创建文件,而是去读取一个已经存在的文件,如果读取的文件不存在则会出现异常。如果模式为rw,如果文件不存在则会创建文件,存在就不创建。

输入输出测试:

String str = "src\\learn\\others\\io\\world.txt";
        try(final RandomAccessFile accessFile = new RandomAccessFile(new File(str),"rw");){
            accessFile.write("xyz".getBytes());
            System.out.println(accessFile.getFilePointer());
            long pos = 10l;
            accessFile.seek(pos);
            accessFile.write("TEN".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }

插入操作实现(无)

用RandomAccessFile实现“插入”操作:
因为write()会覆盖文件原内容,可以先把内容读取出来保存起来(用StringBuilder或ByteArrayOutputStream保存),覆盖之后再append这部分内容。

多线程断点下载(无)

可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能:
下载时建立两个临时文件,一个是与被下载文件大小相同的空文件,一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后下次继续下载,从而实现断点下载或上传的功能。

11. NIO.2中Path、Paths、Files类的使用 (*)

Java NIO

  • Java NIO(New IO/ Non-Blocking IO)是从java1.4开始引入的一套新的IO API。可以替代标准的java IO API。 NIO与原本的IO有相同的作用和目的,但使用的方式完全不同,NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。
  • Java API中提供了两套NIO,一套针对标准输入输出流NIO,另一套就是网络编程NIO
    |---- java.nio.channels.Channel
      |----FileChannel:处理本地文件
      |----SocketChannel:TCP网络编程的客户端的Channel
      |----ServerSocketChannel:TCP网络编程的服务端的Channel
      |----DatagramChannel:UDP网络编程的发送端和接收端的Channel
  • NIO.2
  • JDK7,对NIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持

Path、Paths、Files核心API

  • 早期的java只提供一个File类来访问文件系统,但File的功能比较有限,所提供的方法性能也不高。并且,大多数方法在出错时,仅返回失败,并不能提供异常信息。
  • NIO.2 为了弥补这种不足,引入了Path接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。Path可以看成是File类的升级版本,实际引用的资源也可以不存在。
  • Paths类提供的静态get方法用来获取Path对象: Path path = Paths.get("index.html")
  • java.nio.file.Files用于操作文件或目录的工具类。
  • 使用第三方jar包(例如commons.io-2.5.jar)实现数据读写

你可能感兴趣的:(随记)