zoukankan      html  css  js  c++  java
  • Java基础-day19

    Java 提供了许多实现文件输入 / 输出的类。 这些类可以分为文本 I/O 类二进制 I/O 类

    在Java中如何处理文本I/O

    使用Scanner类读取文本数据,使用PrintWriter类写文本数据

    为了将文本写入一个名为temp.txt的文件中,可以使用PrintWriter类创建一个对象:

    PrintWriter output = new PrintWriter("temp.txt");
    

    可以调用该对象的print方法向文件写入一个字符串

    output.print("Java 101");
    

    之后关闭文件

    output.close();
    

    从文件temp.txt中读入数据:

    Scanner input = new Scanner(new File("temp.txt"));
    System.out.println(input.nextLine());
    

    Snipaste_2020-05-04_20-04-53

    文本I/O 与 二进制I/O

    二进制 I / O 不涉及编码和解码 , 因此比文本 I / O 更加高效

    Snipaste_2020-05-04_20-14-06

    为了保持一致性,使用扩展名.txt来命名文本文件,使用.dat来命名二进制文件

    二进制I/O类

    抽象类 InputStream 是读取二进制数据的根类 , 抽象类 OutputStream 是写入二进制数据的根类

    Snipaste_2020-05-04_20-17-31

    Snipaste_2020-05-04_20-22-35

    **二进制 I / O 类 中 的 所 有 方 法 都 声 明 为 抛 出java.io.IOException java.io. IOException的子类 **

    FileInputStream FileOutputStream

    FileInputStream : 从文件读取字节

    FileOutputStream :向文件写入字节

    1. 构造一个FileInputStream对象
    Snipaste_2020-05-04_20-31-18

    如果试图为一个不存在的文件创建 FilelnputStream 对象 , 将会发生java.io.FileNotFoundException 异常

    1. 构造一个FileOutputStream对象
    Snipaste_2020-05-04_20-33-41
    • 如果这个文件不存在 , 就会创建一个新文件 。 如果这个文件已经存在 , 前两个构造方法将会删除文件的当前内容 。 为了既保留文件现有的内容又可以给文件追加新数据 , 将最后两个构造方法中的参数 append 设置为 true 。

    • 几乎所有的I/O类中的方法都会抛出异常java.io.IOException

    使用二进制 I / O 将从 1 到 10 的 10 个字节值写入一个名为 temp . dat 的文件 , 再把它们从文件中读出来

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class TestFileStream {
        public static void main(String[] args) throws IOException {
            try(            // 利用try-with-resources来声明和创建输入流
                FileOutputStream output = new FileOutputStream("temp.dat");
                    ){
                for (int i = 1; i <= 10; i++)
                    output.write(i);    // 也可以写成 output.write((byte)i)
            }
    
            try(            // 利用try-with-resources来声明和创建输出流
                    FileInputStream input = new FileInputStream("temp.dat");
                    ){
                int value;
                while((value = input.read()) != -1) // -1意味着文件结束
                    System.out.print(value + " ");
            }
        }
    }
    
    1 2 3 4 5 6 7 8 9 10
    

    java.io.InputStreamjava.io.OutputStream实现了AutoClosable接口,该接口中定义了close()方法,用于关闭资源。任何AutoClosable类型的对象可以用于try-with-resources语法中实现自动关闭。

    FileInputStream类的实例可以作为参数去构造一个Scanner对象,而FileOutputStream类的实例可以作为参数构造一个PrinterWriter对象

    new PrintWriter(new FileOutputStream("temp.txt", true));
    

    FilterInputStreamFilterOutputStream

    Snipaste_2020-05-04_20-59-58

    DataInputStreamDataOutputStream

    DataInputStream从数据流读取字节,并且将他们转换为合适的基本类型值或字符串

    DataOutputStream将基本类型的值或字符串转换为字节,并且将字节输出到数据流

    Snipaste_2020-05-04_21-59-51Snipaste_2020-05-04_21-59-57

    Snipaste_2020-05-04_21-59-57

    二进制I/O中的字符与字符串

    — 个统一码由两个字节构成。

    1. writeChar(char c)方法将字符c的统一码写入输出流
    2. writeChars(String s)方法将字符串s中所有字符的统一码写到输出流中
    3. writeBytes(String s)方法将字符串s中每个字符统一码的低字节写到输出流,统一码的高字节被丢弃,该方法适用于由ASCII码字符构成的字符串(因为ASCII码仅仅存储统一码的低字节)
      • 如果一个字符串包含非ASCII码的字符,必须使用writeChars方法实现写入这个字符串
    4. writeUTF(String s)方法将两个字节的长度信息写入输出流,后面紧跟的是字符串s中每个字符的改进版UTF-8的形式
      • readUTF()方法读取一个使用writeUTF方法写入的字符串
      • UTF-8格式具有存储每个ASCII码就节省一个字节的优势

    writeUTF("ABCDEF")写入文件的8个字节(00 06 41 42 43 44 45 46),头两个字节存储的是字符串中的字符个数

    创建DataInputStream类和DataOutputStream

    根据上面的UML图,通过下面构造方法来创建DataInputStream类和DataOutputStream

    public DataInputStream(InputStream instream);
    public DataOutputStream(OutputStream outStream);
    
    DataInputStream input = new DataInputStream(new FileInputStream("in.dat")); // 为文件in.dat创建一个输入流
    DataOutputStream output = new DataOutputStream(new FileOutputStream("out.dat"));	// 为文件out.dat创建一个输出流
    

    例子:将学生的名字和分数写入名为temp.dat的文件中

    import java.io.*;
    
    public class TestDataStream {
        public static void main (String[] args) throws IOException {
            try (
                    DataOutputStream output = 
                new DataOutputStream(new FileOutputStream("temps.dat"));
            ){
                output.writeUTF("yzy");
                output.writeDouble(89.0);
                output.writeUTF("wjy");
                output.writeDouble(90.2);
            }
    
            try(
                    DataInputStream input = 
                new DataInputStream(new FileInputStream("temps.dat"));
             ){
                for (int i = 1; i <= 2; i++)
                    System.out.println(input.readUTF() + " " + input.readDouble());
            }
        }
    }
    
    yzy 89.0
    wjy 90.2
    
    Snipaste_2020-05-05_09-34-34

    检测文件的末尾

    如果到达InputStream 的末尾之后还继续从中读取数据 , 就会发生 EOFException 异常 。
    这个异常可以用来检査是否已经到达文件末尾

    import java.io.*;
    
    public class TestEOF {
        public static void main(String[] args) throws IOException {
            try {
                try (
                        DataOutputStream output =
                                new DataOutputStream(new FileOutputStream("testEOF.dat"));
                ) {
                    output.writeDouble(1.1);
                    output.writeDouble(2.2);
                    output.writeDouble(3.3);
                }
    
                try(
                        DataInputStream input =
                                new DataInputStream(new FileInputStream("testEOF.dat"));
                        ){
                    while(true){
                        System.out.println(input.readDouble());
                    }
                }
            }
            catch (EOFException ex){
                System.out.println("All data were read");
            }
            catch (IOException ex){
                ex.printStackTrace();
            }
        }
    }
    
    1.1
    2.2
    3.3
    All data were read
    

    BufferedInputStreamBufferedOutputStream

    这两个类可以通过减少磁盘读写次数来提高输入和输出速度

    Snipaste_2020-05-05_09-42-59

    这两个类没有包含新的方法,所有方法继承自InputStream类和OutputStream

    Snipaste_2020-05-05_09-46-58

    Snipaste_2020-05-05_09-47-07

    如果没有指定缓冲区大小 , 默认的大小是 512 个字节

    DataOutputStream output = new DataOutputStream(
    	new BufferedOutputStream(new FileOutputStream("temp.dat")));
    
    DataInputStream input = new DataInputStream(
        new BufferedInputStream(new FileInputStream("temp.dat")));
    

    实例学习:复制文件

    import java.io.*;
    
    public class Copy {
        public static void main(String[] args) throws IOException {
            if (args.length != 2){
                System.out.println(" Usage : java Copy sourceFile targetfile");
                System.exit(1);
            }
    
            File sourceFile = new File(args[0]);
            if (!sourceFile.exists()){
                System.out.println("sourceFile does not exist");
                System.exit(2);
            }
    
            File targetFile = new File(args[1]);
            if (targetFile.exists()){
                System.out.println("targetFile already exist");
                System.exit(3);
            }
    
            try(
                    BufferedInputStream input = new BufferedInputStream(
                            new FileInputStream(sourceFile));
                    BufferedOutputStream output = new BufferedOutputStream(
                            new FileOutputStream(targetFile));
                    ){
                int r, numberOfByteCopied = 0;
                while ((r = input.read()) != -1){
                    output.write((byte)r);
                    numberOfByteCopied++;
                }
                System.out.println("number of copied : " + numberOfByteCopied);
            }
    
        }
    }
    
    D:JAVA_IDEAJavaProjectsChapter05src>java Copy testCopy.txt target.txt
    number of copied : 23
    
    Snipaste_2020-05-05_10-39-08

    对象I/O

    ObjectInputStream类和ObjectOutputStream类可以用于读/写可序列化的对象,也可以实现基本数据类型与字符串的输人和输出,包含了DataInputStream类和DataOutputStream类的所有功能

    Snipaste_2020-05-05_10-45-18

    public ObjectInputStream(InputStream in)	// 创建一个对象输入流
    public ObjectOutputStream(OutputStream out) // 创建一个对象输出流
    
    1. 姓名 、 分数和当前日期写入名为 object.dat 的文件
    import java.io.*;
    public class TestObjectOutputStream{
        public static void main(String[] args) throws IOException{
            try(
                ObjectOutputStream output = 
                    new ObjectOutputStream(new FileOutputStream("object.dat"));
            ){
                output.writeUTF("John");
                output.writeDouble(33.3);
                outout.writeObject(new java.util.Date());	// 将对象写入文件
            }
        }
    }
    

    可以添加缓冲区:

    ObjectOutputStream output = new ObjectOutputStream(
    new BufferedOutputStream(new FileOutputStream("object.dat")));
    
    1. 读回这些对象:按照写入时的类型和顺序。为了得到所需的类型 , 必须使用 Java 安全的类型转换
    import java.io.*;
    public class TestObjectOUtputStream{
        public static void main(String[] args)
        throws ClassNotFoundException, IOException{
            try(
                ObjectInputStream input = 
                new ObjectInputStream(new FileInputStream("object.dat"));
            ){
                String name = input.readUTF();
                double score = input.readDouble();
                java.util.Date date = (java.util.Date)(input.readObject());
                // readObject()方法可能会拋出异常java.lang.ClassNotFoundException
                // readObject()读入的是Object对象,所以应将他转换为Date类型
                System.out.println(name + " " + score + " " + date);
            }
        }
    }
    

    Serializable接口

    Snipaste_2020-05-05_11-15-41

    Snipaste_2020-05-05_11-16-42

    序列化数组

    如果数组中的所有元素都是可序列化的 , 这个数组就是可序列化的 。 一个完整的数组可以用 writeObject 方法存入文件 , 随后用 readObject 方法恢复

    import java.io.*;
    
    public class TestObjectStreamWithArray {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            int[] num = {1, 2, 3, 4, 5};
            String[] str = {"shang", "shan", "da", "lao", "hu"};
    
            try (
                    ObjectOutputStream output =
                            new ObjectOutputStream(new FileOutputStream("testOb.dat", true));
                    ){
                output.writeObject(num);
                output.writeObject(str);
            }
    
            try (
                    ObjectInputStream input =
                            new ObjectInputStream(new FileInputStream("testOb.dat"));
                    ){
                int[] number = (int[])(input.readObject());
                String[] strings = (String[])(input.readObject());
    
                for (int i = 0; i < number.length; i++){
                    System.out.print(number[i] + " ");
                }
                System.out.println();
    
                for (int i = 0; i < strings.length; i++){
                    System.out.print(strings[i] + " ");
                }
            }
        }
    }
    
    1 2 3 4 5 
    shang shan da lao hu 
    

    随机访问文件

    Java 提供了RandomAccessFile类 , 允许从文件的任何位置进行数据的读写

    1. 上面学习的都是只读的和只写的,这称为顺序流, 使用顺序流打开的文件称为**顺序访问文件 **。 顺序访问文件的内容不能更新 。

    2. Java 提供了RandomAccessFile类 , 允许在文件的任意位置上进行读写 。 使用 RandomAccessFile 类打开的文件称为随机访问文件

    Snipaste_2020-05-05_11-36-05

    RandomAccessFile raf = new RandomAccessFile("test.dat", "rw"); 	// rw为可读写的
    
    • 如果文件 test.dat 已经存在 , 则创建raf以便访问这个文件
    • 如果test.dat不存在,则创建一个名为 test.dat 的新文件,再创建 raf 来访问这个新文件

    随机访问文件是由字节序列组成的。一个称为文件指针 的特殊标记定位这些字节中的某个字节的位置

    Snipaste_2020-05-05_11-40-52
    import java.io.*;
    
    public class TestRandomAccessFile {
        public static void main(String[] args) throws IOException {
            try(
               RandomAccessFile inout = new RandomAccessFile("inout.dat", "rw");
            ){
                inout.setLength(0); // 清空文件
                for (int i = 0; i < 200; i++){  // 写入200个数字
                    inout.writeInt(i);
                }
    
                System.out.println("目前文件长度为:" + inout.length());
    
                inout.seek(0);  // 将文件指针移动到头位置
                System.out.println("第一个数:" + inout.readInt());
    
                inout.seek(9 * 4);  // 将文件指针移到第10个数位置
                System.out.println("第10个数:" + inout.readInt());
    
                inout.seek(inout.length()); // 将文件指针移动末尾
                inout.writeInt(999);
    
                System.out.println("现在文件长度为:" + inout.length());
            }
        }
    }
    
    目前文件长度为:800
    第一个数:0
    第10个数:9
    现在文件长度为:804
    

    Write by Gqq

  • 相关阅读:
    如何使用phantomJS来模拟一个HTML元素的鼠标悬停
    nodejs中使用cheerio爬取并解析html网页
    Node.js 动态网页爬取 PhantomJS 使用入门(转)
    一口一口吃掉Hibernate(五)——一对多单向关联映射
    开源 免费 java CMS
    [WinForm]dataGridView导出到EXCEL
    关键帧和动画
    uva 696
    uva 11181
    IE下target获得焦点时存在虚线的问题
  • 原文地址:https://www.cnblogs.com/zgqcn/p/12830090.html
Copyright © 2011-2022 走看看