10-IO流

先修

  • 文件分割符:

        Linux操作系统,文件分隔符号是"/"

        windows操作系统,文件分隔符号是" \ ",路径分隔符在代码中的体现必须是 "\\",windows还支持 "/"

  • 相对路径和绝对路径:

        绝对路径是从盘符开始的一个路径 :"C:\Demo1\test.txt"

        相对路径:不从盘符开始的路径 :"\test.txt"   (必须有一个参考路径,多用于工程项目中)


File

        在 java 程序中,对磁盘文件进行描述的类。文件和目录路径名的抽象表示形式

  • File 基本方法练习:
package practice.io;

import java.io.File;
import java.io.IOException;

/**
 * prudence
 * 2020/5/7 9:30 上午
 */
public class IOTest {

    public static void main(String[] args) throws IOException {
        //分号 与系统有关的路径分隔符
        System.out.println(File.pathSeparator);
        System.out.println(File.pathSeparatorChar);
        // 反斜杠 与系统有关的默认名称分隔符
        System.out.println(File.separator);
        System.out.println(File.separatorChar);

        System.out.println("===================================================");

        //创建一个文件对象,表示桌面的的abc.txt文件
        File file = new File(File.separatorChar + "Users" + File.separatorChar + "prudence" + File.separatorChar + "Desktop" + File.separatorChar + "abc.txt");
        System.out.println(file.getPath());//   /Users/prudence/Desktop/abc.txt
        file.createNewFile();

        System.out.println(file.canExecute());//false
        System.out.println(file.canWrite());//true
        System.out.println(file.canRead());//true
        System.out.println(file.isHidden());//false

        System.out.println("===================================================");

        File file2 = new File("/Users/prudence/Desktop/a.txt");
        System.out.println(file.compareTo(file2));
        //exists方法:判断文件抽象路径表示的文件或目录是否存在
        System.out.println(file2.exists());
        // createNewFile方法:创建一个新的空文件(若存在则创建失败)
        System.out.println(file2.createNewFile());
        // delete方法:只能删除文件和空文件夹,非空文件夹不能使用delete方法删除
        System.out.println(file2.delete());
        System.out.println(file.delete());
    }
}

        运行结果:

  • 在相同路径下新建文件:
    public static void main(String[] args) throws IOException {
        //在hello.txt相同的目录下创建出一个world.txt文件
        File f1 = new File("/Users/prudence/Desktop/hello.txt");
        System.out.println(f1.getPath());//  /Users/prudence/Desktop/hello.txt
        System.out.println(f1.getParent());//   /Users/prudence/Desktop
        System.out.println(f1.getName());//  hello.txt
        System.out.println(f1.toPath());//  /Users/prudence/Desktop/hello.txt
        System.out.println(f1.toURI());//   file:/Users/prudence/Desktop/hello.txt
//         fun(f1);
    }

    public static void fun(File file) throws IOException {
        //获取父路径
        String parent = file.getParent();
        // 创建File对象
        File f = new File(parent, "新建文本文档.txt");
        // 创建新文件
        f.createNewFile();
    }
  • 文件和文件夹:
    public static void main(String[] args) throws IOException {

//        File file = new File("/Users/prudence/Desktop/333");
        File file = new File("/Users/prudence/Desktop/test");
        System.out.println(file.exists());

        //判断一个File对象是否是文件夹
        System.out.println(file.isDirectory());
        // 判断一个File对象是否是文件
        System.out.println(file.isFile());
        // 获取文件夹中所有子文件夹和文件的名称(字符串形式)
        String[] files = file.list();

        System.out.println("===================================================");
        System.out.println(files.length);
        for (String s : files) {
            System.out.println(s);
        }

        System.out.println("===================================================");
        File[] fs = file.listFiles();
        // 获取文件件中所有子文件夹和文件的抽象路径(File对象)
        System.out.println(fs.length);
        for (File f : fs) {
            System.out.println(f);
        }

    }

        运行结果:

  • 创建文件与重命名:
    public static void main(String[] args) throws IOException {

        File file = new File("/Users/prudence/Desktop/test/a.txt");
//        //在创建一个文件时,需要先判断父目录是否存在,若不存在则创建父目录
        File parent = file.getParentFile();
        if (!parent.exists()) {
            System.out.println(parent.mkdirs());//创建一个新的空文件夹
        }
        System.out.println(file.createNewFile());

        //对文件重命名
        File file1 = new File("/Users/prudence/Desktop/333");
        File file2 = new File("/Users/prudence/Desktop/test/444.txt");
        System.out.println(file1.renameTo(file2));// 将file表示文件重命名为f时,必须保证file是存在的文件

    }
  • 文件遍历与查找:
    public static void main(String[] args) throws IOException {
        String string = "/Users/prudence/Desktop/test";
        method1(string);
        System.out.println("===================================================");
        method2(string);
        System.out.println("===================================================");
        method3(string);
    }

    //列出指定目录下所有子文件夹以及子文件
    public static void method1(String path) {
        File file = new File(path);
//     子文件或者子文件夹的名称
        String[] arr = file.list();
        for (String str : arr) {
            System.out.println(str);
        }
    }

    //列出指定目录下所有子文件夹以及子文件
    public static void method2(String path) {
        File file = new File(path);
        //获取指定路径下所有File对象
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isFile()) {
                System.out.println("子文件:");
                // 获取每个文件的名字
                System.out.println(f.getName());
            } else if (f.isDirectory()) {
                System.out.println("子文件夹:");
                System.out.println(f.getName());
            }
        }
    }

    //列出指定目录下所有后缀为.java的文件
    public static void method3(String path){
        File file = new File(path); String[] arr = file.list(); for(String str:arr) {
            if (str.endsWith(".java")) {
                System.out.println(str);
            }
        }
    }

        运行结果:


IO流

  • 什么是IO流:

        操作磁盘上资源时需要实现数据的输入和输出操作,磁盘上的文件和内存之间进行交互,数据的交互需要有一个媒介或者管道,把这个媒介或者管道称为IO流,也称为输入输出流。

        流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

  • 分类:

        按照流向分:

                输入流:表示将数据读取到java程序(内存)中使用的流

                输出流:表示从java程序(内存)向外传输使用的流

        按照数据单位分:

                字节流:一次性传输一个字节数据,将数据以字节的形式传输

                字符流:一次性传输一个字符数据,将数据以字符的形式传输

        按照层次分:

                节点流:可以从或向一个特定的地方(节点)读写数据

                处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写


字节流

  • 字节输入流

        InputStream --> FileInputStream

    public static void main(String[] args) {
        //创建被操作文件:此文件必须存在,否则读取时,抛出文件找不到异常
        File file = new File("/Users/prudence/Desktop/abc.txt");
        //声明流,不初始化
        FileInputStream fis = null;

        try {
            // 初始化流
            fis = new FileInputStream(file);
            // 准备数组用来存储数据
            byte[] b = new byte[3];
            // 先定义一个变量,初始值是‐1
            int i = -1;
            // 定义一个计数循环的变量
            int count = 0;
            // while循环读取
            while ((i = fis.read(b)) != -1) {
                count++;
                for (int j = 0; j < i; j++) {
                    System.out.print((char) b[j]);//读中文乱码
                }
            }
            //计算循环读取的次数
            System.out.println("count:" + count);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

        运行结果:

                                        

  • 字节输出流:

        OutputStream --> FileOutputStream

    public static void main(String[] args) {
        //向文件中写入数据
        //在工程中创建一个test文件夹,向test\\hello.txt中写入hello world
        //第一步:创建被操作文件对象(当向一个文件中写入数据时,若文件不存在,程序会自动创建)
        File file = new File("/Users/prudence/Desktop/test/ccc.txt");
        FileOutputStream fos = null;
        try {
            // 第二步:创建流对象
            fos = new FileOutputStream(file, true);
            // 第三步:准备数据
            String str = "hello world!";
            byte[] b = str.getBytes();
            System.out.println(b.length);//12
            // 第四步:使用流写入
            fos.write(b);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    // 第五步:刷新流,关闭流
                    fos.flush();
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

字符流 

  • 字符输入流:

        Reader --> InputStreamReader --> FileReader

        FileReader:便利类,使用系统默认编码格式(Mac:utf-8),若要指定使用InputStreamReader

        Reader:是所有字符输入流的父类,为一个抽象类,不能实例化对象,使用它的子类 FileReader
        
    public static void main(String[] args) {
        //1.将文件的路径转换为File对象
        File file = new File("/Users/prudence/Desktop/abc.txt");
        Reader reader = null;
        try {
            //2.实例化一个FileReader的对象
            reader = new FileReader(file);
            //3.定义一个数组
            char[] arr = new char[8];//GBK乱码,Utf-8不乱码
            //4.定义一个int的变量
            int hasRead = 0;
            //5.循环读取
            while ((hasRead = reader.read(arr)) != -1) {
                String result = new String(arr, 0, hasRead);
                System.out.print(result);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

        运行结果: 

                                

  •  字符输出流:

        Writter --> OutputStreamWritter --> FileWritter

        FileWritter:便利类,使用系统默认编码格式(Mac:utf-8),若要指定使用OutputStreamWritter

    public static void main(String[] args) throws IOException {
        File file = new File("/Users/prudence/Desktop/test/ccc.txt");
        Writer writer = new FileWriter(file);
        //区别于字节流,可以直接传字符串
        writer.write("从前有座山,山上有座庙");
        writer.flush();
        writer.close();
    }

转换流 

        1、实现字节流到字符流的转换

        2、解决中文乱码的问题:GBK、UTF-8

        3、只有转换流可指定读取和写入的字符集

  • 字节字符转换输入流:

        InputStreamReader,将字节输入流转换为字符输入流

    public static void main(String[] args) throws IOException {
        //1.实例化File的对象
        File file = new File("/Users/prudence/Desktop/aaa");
        // 2.实例化输入流和转换输入流的对象
        // 注意:当一个流的存在的意义是为了实例化另外一个流,则这个流不需要手动进行关闭
        InputStream input = new FileInputStream(file);
        InputStreamReader reader = new InputStreamReader(input);

        // 使用默认的字符集【UTF-8】进行实例化转换流
        //注:eclipse默认gbk,idea默认utf-8
//         InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("/Users/prudence/Desktop/aaa")));
        // 使用指定字符集进行实例化转换流
        // 字符集一般使用字符串直接传参,不区分大小写,如果字符集书写有误:java.io.UnsupportedEncodingException
//         InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("/Users/prudence/Desktop/aaa")),"GBK");//文件为utf-8编码则中文乱码

        // 3.读取
        char[] arr = new char[16];
        int len = 0;
        while ((len = reader.read(arr)) != -1) {
            String string = new String(arr, 0, len);
            System.out.print(string);
        }

        reader.close();
    }
  • 字节字符转换输出流:

        OutputStreamWritter,将字节输出流转换为字符输出流

    public static void main(String[] args) throws IOException {
        //需求:将一段文本以utf-8的格式写入到文件中【注,文件格式为默认格式】
        // 1.实例化File对象
        // 注意:对于所有的输出流而言,文件可以不存在,在进行写入的过程中可以自动进行创建
        //      但是,对于所有的输入流而言,文件必须先存在,然后才能操作,否则,会抛出 FileNotFoundException
         File file = new File("/Users/prudence/Desktop/test/ccc.txt");
        // 2.实例化转换输出流
        // 如果不想覆盖源文件中的内容时,则在传参的时候,设置一个参数为true
        //OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file,true));//idea默认"utf-8"
         OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file,true), "utf-8");
        // 3.写入
         writer.write("从前有座山,山上有座庙,庙里有个老和尚,老和尚对小和尚讲。。。");
        // 4.刷新
         writer.flush();
        // 5.关闭
         writer.close();
    }

 缓冲流 

        如果“字节流 - 转换流 - 字符流”主要是解决编码问题,缓冲流主要解决的就是流的速度问题,同时也增强了功能

Java flush()作用及适用场景 FileOutputStream BufferedOutputStream区别 缓冲区与字节数组的理解_myisam丶的博客-优快云博客

  • 字节输入缓冲流:

        InputStream --> BufferInputStream

        主要是为了增强基础流的功能而存在的,提高了流的工作效率(读写效率)

    public static void main(String[] args) throws IOException {
        
        //实例化一个File对象
        File file = new File("/Users/prudence/Desktop/test/ccc.txt");
        // 实例化一个缓冲字节输入流的对象
        BufferedInputStream input = new BufferedInputStream(new FileInputStream(file));

        //读取
//        byte[] arr = new byte[2 << 10];
//        int len = 0;
//        while ((len = input.read(arr)) != -1) {
//            String string = new String(arr, 0, len);
//            System.out.print(string);
//        }

        byte[] arr = new byte[6];
        int len = input.read(arr);
        String string = new String(arr, 0, len);
        System.out.println(string);

        input.mark(66);

        len = input.read(arr);
        string = new String(arr, 0, len);
        System.out.println(string);

        //实现了效果:覆水可收
        input.reset();

        len = input.read(arr);
        string = new String(arr, 0, len);
        System.out.println(string);

        input.close();
    }

        运行结果:

  •  字节输出缓冲流:

        OutpuStream --> BufferedOutputStream

    public static void main(String[] args) throws IOException {
        // 实例化File对象
        File file = new File("/Users/prudence/Desktop/test/ccc.txt");
        // 实例化转换字节输出流
        BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file, true));
        // 写
        output.write("有因必有果,你的报应就是我".getBytes());
        // 刷新
        output.flush();
        // 关闭
        output.close();
    }
  • 字符输入缓冲流:

        Reader --> BufferedReader

    public static void main(String[] args) throws IOException {
        //实例化File对象
        File file = new File("/Users/prudence/Desktop/test/ccc.txt");
        // 实例化缓冲字符流的对象
        BufferedReader reader = new BufferedReader(new FileReader(file));
        // 方式一:read循环读取
//        char[] arr = new char[8];
//        int len = 0;
//        while ((len = reader.read(arr)) != -1) {
//            String string = new String(arr, 0, len);
//            System.out.print(string);
//        }

        // 方式二:readLine循环读取
//        String result1 = reader.readLine();
//        System.out.println(result1);
//        String result2 = reader.readLine();
//        System.out.println(result2);

        //reader.mark(666);

        String result = "";
        while ((result = reader.readLine()) != null){
            System.out.println(result);
        }

        reader.close();
    }
  • 字符输出缓冲流:

        Writter --> BufferedWritter

    public static void main(String[] args) throws IOException {
        // 实例化FIle对象
        File file = new File("/Users/prudence/Desktop/test/ccc.txt");
        // 实例化缓冲字符输出流
        BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
        // 换行
        writer.newLine();
        // 写
        writer.write("奔涌吧,后浪!");
        // 刷新
        writer.flush();
        // 关闭
        writer.close();
    }

  字节流、转换流、缓冲流结合使用

BufferedReader reader = new BufferedReader(
        new InputStreamReader(
                new FileInputStream(
                        new File("/Users/prudence/Desktop/test")), "GBK"));
BufferedWriter writer = new BufferedWriter(
        new OutputStreamWriter(
                new FileOutputStream(
                        new File("/Users/prudence/Desktop/test"), true), "GBK"));

 内存流

        输入和输出都是从文件中来的,当然,也可将输出的位置设置在内存上,这就需需要ByteArrayInputStream和 ByteArrayOutputStream

        InputStream --> ByteArrayInputStream:将内容写入到内存中

        OutPutStream --> ByteArrayOutputStream:将内存中数据输出

    public static void main(String[] args) throws IOException {
        //定义一个字符串,全部由大写字母组成
        String string = "HELLOWORLD";

        // 内存输入流:向内存中输入内容,注意:跟文件读取不一样,不设置文件路径
        //InputStream bis = new ByteArrayInputStream(string.getBytes());
        ByteArrayInputStream bis = new ByteArrayInputStream(string.getBytes());
        // 内存输出流:准备从内存中读取内容,注意:跟文件读取不一样,不设置文件路径
        //OutputStream bos = new ByteArrayOutputStream();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        
        int temp = 0;
        // read()方法每次只读取一个字符
        while ((temp = bis.read()) != -1) {
            // 将读取的数字转为字符
            char c = (char) temp;
            // 将字符变为小写
            bos.write(Character.toLowerCase(c));
        }
        // 循环结束之后,所有的数据都在ByteArrayOutputStream中
        // 取出内容,将缓冲区内容转换为字符串
        String newString = bos.toString();

        //关闭流
        bis.close();
        bos.close();
        System.out.println(newString);//helloworld
    }

        以上的操作很好地体现了对象的多态。通过实例化其子类不同,完成的功能也不同,也就相当于输出的位置不同,如果是输入输出文件,则使用FileXxx,是内存则使用ByteArrayXxx

        1、内存操作流的操作对象,一定是以内存为准,不要以程序为准

        2、实际上此时可以通过向上转型,转换为OutputStream或InputStream

        3、内存输出流在开发中经常使用到,一定要重点掌握


 标准输入输出流

        流的位置可以为“文件”、“内存”,也可以为“系统的 键盘&显示器”

        Java的标准输入/输出分别通过 System.in 和 System.out 实现,默认情况下分别代表是键盘和显示器

  • 标准输入流:

        System.in ,默认情况下代表键盘

    public static void main(String[] args) throws IOException {
       FileInputStream inputStream = new FileInputStream(new File("/Users/prudence/Desktop/abc.txt"));
        System.setIn(inputStream);
        System.out.println("请输入内容:");
        // 默认情况下是从控制台获取内容
        // 但是如果使用setIn方法设置了重定向之后,将从指定文件中获取内容
        Scanner sc = new Scanner(System.in);
        String s1 = sc.next();
        System.out.println(s1);
        String s2 = sc.next();
        System.out.println(s2);

        // 功能上同 Scanner sc = new Scanner(inputStream);
//        Scanner sc2 = new Scanner(inputStream);
//        String s = sc2.next();
//        System.out.println(s);
    }
  • 标准输出流:

        System.out ,默认情况下代表显示器

    public static void main(String[] args) throws IOException {
        System.out.println("输出到控制台:hello world");
        //创建打印流的对象
        // 注意:默认打印到控制台,但是,如果采用setOut方法进行重定向之后,将输出到指定的文件中
        PrintStream print = new PrintStream(new FileOutputStream(new File("/Users/prudence/Desktop/abc.txt")));

        /** static void setErr(PrintStream err)
         * 重新分配“标准”错误输出流。
         * static void setIn(InputStream in)
         * 重新分配“标准”输入流。
         * static void setOut(PrintStream out)
         * 重新分配“标准”输出流。
         */
        //将标准输出重定向到print的输出流
        System.setOut(print);
        System.out.println("输出到文件:hello world");//每次运行都是对文件中已有内容的覆盖
    }

流的基准与位置

        普通流:以程序为准的输入输出

        内存流:以内存为准的输入输出

        系统(标准输入输出)流:以系统为准的输入输出,默认为键盘/显示器,可重定向

        流的位置:文件、程序、内存、系统

  • 将以内存为准的输入输出位置设为系统 System: 
    public static void main(String[] args) throws IOException {
        System.out.println("请输入内容:");
        Scanner scanner = new Scanner(System.in);
        String next = scanner.next();
        InputStream bis = new ByteArrayInputStream(next.getBytes());
        OutputStream bos = new ByteArrayOutputStream();

        int temp = 0;
        while ((temp = bis.read()) != -1) {
            char c = (char) temp;
            bos.write(Character.toLowerCase(c));
        }
        String newString = bos.toString();

        //关闭流
        bis.close();
        bos.close();
        System.out.println(newString);
    }

 对象流

        流中流动的数据是对象(流的单位:字节、字符、对象)

        如果将一个对象写入到本地文件中,被称为对象的序列化

        如果将一个本地文本中的对象读取出来,被称为对象的反序列化

        注:一个对象流只能操作一个对象,如果试图采用一个对象流操作多个对象的话,会出现Exception(文件意外达到了文件末尾)

        如果想将多个对象序列化到本地,可以借助集合(将多个对象添加到集合中,将集合的对象写入到本地文件中,再次读出来,获取到的仍然是集合对象,遍历集合)

  • 对象输入流:

        InputStream --> ObjectInputStream

        OutputStream --> ObjectOutputStream

public class IOTest {

    public static void main(String[] args) {
//        objOutputStreamUsage();
        objInputStreamUsage();
    }

    //写:将对象进行序列化
    public static void objOutputStreamUsage() {
        // 写:将对象进行序列化
        // 1.实例化一个Person的对象
        Person person = new Person("张三", 10, 'B');
        // 2.实例化一个对象输出流的对象
        ObjectOutputStream output = null;
        try {
            output = new ObjectOutputStream(new FileOutputStream(new File("/Users/prudence/Desktop/abc.txt")));
            // 3.将对象写入到流中
            output.writeObject(person);
            // 4.刷新
            output.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //读:反序列化
    public static void objInputStreamUsage() {
        try {
            //1.实例化对象输入流的对象
            ObjectInputStream input = new ObjectInputStream(new FileInputStream(new File("/Users/prudence/Desktop/abc.txt")));
            //2.读取
            Object object = input.readObject();
            //3.对象的向下转型
            if (object instanceof Person) {
                Person p = (Person) object;
                System.out.println(p);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

@Data
@AllArgsConstructor
class Person implements Serializable {

    private String name;
    private int age;
    private char score;
}

        运行结果:

         

        注意:在使用对象流的时候,用于初始化对象流的参数只能是字节流(将对象转换为二进制的形式,然后再把二进制写入文件)


RandomAccessFile

        RandomAccessFile 是用来访问那些保存数据记录的文件的,你就可以用seek方法来访问记录,并进行读写。这些记录的大小不必相同,但是其大小和位置必须是可知的。但是该类仅限于操作文件

        RandomAccessFile 不属于 InputStream 和 OutputStream 类系的,实际上除了实现 DataInput 和 DataOutput 接口之外(DataInputStream 和 DataOutputStream 也实现了这两个接口),他和这两个类系毫不相干,甚至不使用 InputStream 和 OutputStream 类中已经存在的任何功能;

        它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。这可能是因为 RandomAccessFile 能在文件里面前后移动,所以它的行为与其他的 I/O 类有些根本性的不同。总而言之,它是一个直接继承Object 的,独立的类

  • 基本方法:
    public static void main(String[] args) throws IOException {

        RandomAccessFile file = new RandomAccessFile("/Users/prudence/Desktop/test/bbb.txt", "rw");
        // 以下向file文件中写数据
        file.writeInt(20);// 占4个字节
        file.writeDouble(8.236598);// 占8个字节
        // 这个长度写在当前文件指针的前两个字节处,可用readShort()读取
        file.writeUTF("这是一个UTF字符串");
        file.writeBoolean(true);// 占1个字节
        file.writeShort(395);// 占2个字节
        file.writeLong(2325451L);// 占8个字节
        file.writeUTF("又是一个UTF字符串");
        file.writeFloat(35.5f);// 占4个字节
        file.writeChar('a');// 占2个字节
        // 把文件指针位置设置到文件起始处
        file.seek(0);


        // 以下从file文件中读数据,要注意文件指针的位置
        System.out.println("——————从file文件指定位置读数据——————");
        System.out.println(file.readInt());
        System.out.println(file.readDouble());
        System.out.println(file.readUTF());

        //将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。
        file.skipBytes(3);
        System.out.println(file.readLong());

        //跳过文件中"又是一个UTF字符串"所占字符
        //注意readShort()方法会移动文件指针,所以不用写具体字节数
        file.skipBytes(file.readShort());
        System.out.println(file.readFloat());

        //以下演示文件复制操作
        System.out.println("--------文件赋值(从file到copy)--------");
        file.seek(0);
        RandomAccessFile fileCopy = new RandomAccessFile("/Users/prudence/Desktop/test/ddd.txt", "rw");
        int len = (int) file.length();//取得文件长度(字节数)
        byte[] b = new byte[len];
        //全部选取
        file.readFully(b);
        fileCopy.write(b);
        System.out.println("复制完成!");
    }

        运行结果:

  •  向指定位置插入数据:
    public static void main(String[] args) throws IOException {
        try {
            insert(1, "java", "/Users/prudence/Desktop/test/bbb.txt");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param skip 跳过多少字节进行数据插入
     * @param str 要插入的字符串
     * @param fileName 文件路径
     * @throws Exception
     */
    public static void insert(long skip, String str, String fileName) throws Exception {
        RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
        if (skip < 0 || skip > raf.length()) {
            System.out.println("跳过字节数无效");
            return;
        }
        byte[] b = str.getBytes();
        raf.setLength(raf.length() + b.length);
        for (long i = raf.length() - 1; i > b.length + skip - 1; i--) {
            raf.seek(i - b.length);
            byte temp = raf.readByte();
            raf.seek(i);
            raf.writeByte(temp);
        }
        raf.seek(skip);
        raf.write(b);

        raf.close();
    }

Properties

        java.util 包中,Map 接口实现类,Hashtable<Object,Object> 子类

        Properties文件中元素也是以键值对的形式存在的

        1、注释内容由 # 或者! 开头, 如果# 或者!不在开头,则不作为注释

        2、key,value之间用 = 或者 : 分隔

                一行中既有 = 也有 : 时,第一个(或者=或者:)将作为key,value分隔符

        3、key 不能换行,value可以换行,换行符是\ ,且换行后的\t、空格都会忽略        

    public static void main(String[] args) throws IOException {
        //1.实例化一个Properties的对象
         Properties pro = new Properties();
         System.out.println(pro);

        // 2.把文件userlist.properties中的键值对同步到集合中
        // 实质:读取
        /**
         * void load(InputStream inStream)
         * 从输入流中读取属性列表(键和元素对)。
         */
        pro.load(new BufferedInputStream(new FileInputStream(new File("/Users/prudence/Desktop/test/test.properties"))));

        System.out.println(pro);

        //3.向集合中添加一对键值对
        /**
         * Object setProperty(String key, String value)
         * 调用 Hashtable 的方法 put。
         */
        pro.setProperty("address1", "china");
        System.out.println(pro);

        //4、store
        //实质:写入
        //comments:工作日志
        pro.store(new BufferedOutputStream(new FileOutputStream(new File("/Users/prudence/Desktop/test/test.properties"))), "add a pair of key and value");

    }

        运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值