栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

三、AVA IO流 中的功能性质的流(可以理解为根据核心部分拓展出来的功能流)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

三、AVA IO流 中的功能性质的流(可以理解为根据核心部分拓展出来的功能流)

文章目录
  • 一、操作基本数据类型的流
  • 二、内存操作流(处理临时文件的流)
  • 三、打印流(不能操作数据源的流)
  • 四、随机访问流:RandomAccessFile(速度和效率超级快的流)
  • 五、合并流(可以将多个数据源一起写入同一个封装地文件中的流)
  • 六、序列化流 (操作对象的流)



一、操作基本数据类型的流
       在我们使用 IO 流中的字符流和字节流实现数据的读取和写入操作时会发现,我们可以操作的其实只有字节、字符以及byte数组,无法操作基本数据类型的数据。
       JAVA 提供了操作基本数据类型的流,使用这个流就可以操作基本数据类型的数据了。使用的方式和之前的字节流字符流是一样的,只是提供了一些方法专门读取和写入基础类型的数据。
       这里需要注意一点:因为文本不能识别基础数据类型,所以打开文本会乱码。
       并且这个流其实我没 get 到点,如果只是作为文本来使用的话不需要使用基础数据类型,文本无法编译。而如果作为数据传输通道完全可以使用集合或者数组来代替。(个人感觉,如果有人有不同的看法欢迎讨论)
  • 操作基本数据类型的流
    • DataInputStream 类:可以操作基本数据类型的输入流

    • DataOutputStream 类:可以操作基本数据类型的输出流

      • Demo代码示例:
        public class DataStreamDemo {
        
            public static void main(String[] args) throws IOException{
        
                //写入数据
                write();
                //读取数据
                read();
        
            }
        
            private static void write() throws IOException {
                // DataOutputStream(OutputStream out)
                // 创建数据输出流对象
                DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt"));
        
                // 写入整数
                dos.writeByte(100);
                dos.writeShort(10000);
                dos.writeInt(1000000000);
                dos.writeLong(1000000000000000000L);
        
                // 写入小数
                dos.writeFloat(10.12F);
                dos.writeDouble(10.10789D);
        
                // 写入字符
                dos.writeChar('s');
        
                // 写入字符串
                dos.writeChars("今年是2022年");
        
                // 写入Boolean类型
                dos.writeBoolean(true);
        
                // 释放资源
                dos.close();
            }
        
        
            private static void read() throws IOException {
                // DataInputStream(InputStream in)
                // 创建数据输入流对象
                DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt"));
        
                // 读数据
                // 读取整数
                byte b = dis.readByte();
                short s = dis.readShort();
                int i = dis.readInt();
                long l = dis.readLong();
                
                // 读取小数
                float f = dis.readFloat();
                double d = dis.readDouble();
        
        		// 读取字符
                char c = dis.readChar();
                
                //读取 boolean 值
                boolean bo = dis.readBoolean();
        
                // 释放资源
                dis.close();
        
                System.out.println("byte:"+b);
                System.out.println("short:"+s);
                System.out.println("int:"+i);
                System.out.println("long:"+l);
                System.out.println("float:"+f);
                System.out.println("double:"+d);
                System.out.println("char:"+c);
                System.out.println("boolean:"+bo);
            }
        
        }
        
        运行结果:



二、内存操作流(处理临时文件的流)
       内存操作流一般用于处理临时信息,因为临时信息不需要保存,使用后就可以删除。
  • 内存操作流 - 操作字节数组

    • ByteArrayOutputStream:输出流

    • ByteArrayInputStream : 输入流

      • Demo代码示例:

           public class ByteArrayDemo {
                public static void main(String[] args) throws IOException {
                    // 写数据 --字节数组输出流:相当于创建了一个临时空间
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
        
                    // 写数据,将数据放到临时空间中
                    for (int x = 0; x < 10; x++) {
                        baos.write(("HelloWord"+"t" + x).getBytes());
                        baos.write("n".getBytes());
                    }
        
                    // 释放资源
                    // 通过查看源码我们知道这里什么都没做,所以根本需要close()
                    // baos.close();
        
                    // 将临时空间转换成byte数组
                    byte[] bys = baos.toByteArray();
        
                    // 读数据: 只能读取byte数组的数据
                    // ByteArrayInputStream(byte[] buf)
                    ByteArrayInputStream bais = new ByteArrayInputStream(bys);
        
                    int by = 0;
                    while ((by = bais.read()) != -1) {
                        System.out.print((char) by);
                    }
        
                    // bais.close();
                }
            }
        

        运行结果:


  • 内存操作流 - 操作字符数组

    • CharArrayReader:输出流

    • CharArrayWrite: 输入流

      • Demo代码示例:

            public class CharArrayDemo {
                public static void main(String[] args) throws IOException {
                    // 写数据 --字节数组输出流:相当于创建了一个临时空间
                    CharArrayWriter caw = new CharArrayWriter();
        
                    // 写数据,将数据放到临时空间中
                    for (int x = 0; x < 10; x++) {
                       caw.write("HelloWord"+"t"+ x);
                       caw.write("n");
                    }
        
                    // 释放资源
                    // 通过查看源码我们知道这里什么都没做,所以根本需要close()
                    // baos.close();
        
                    // 将临时空间转换成byte数组
                    char[] chars = caw.toCharArray();
        
                    // 读数据: 只能读取char数组的数据
                    // CharArrayInputStream(byte[] buf)
                    CharArrayReader car = new CharArrayReader(chars);
        
                    int by = 0;
                    while ((by = car.read()) != -1) {
                        System.out.print((char) by);
                    }
        
                    // bais.close();
                }
            }
        

        运行结果:





三、打印流(不能操作数据源的流)
  • 打印流一共分为两种

    • 字节打印流:PrintStream
    • 字符打印流: PrintWriter

  • 打印流的特点:

    • 只有输出流,没有输入流,所以打印流只能写入数据不能读取数据。但是可以和其他流搭配使用,以此来实现复制功能。方法是一样的,用打印流代替原本的输出流即可。
    • 可以操作任意类型的数据。
    • 该流可以直接操作文本文件。


  • 打印流独有的方法:

    • print() 不会换行,不会自动刷新数据。
    • println() 不仅仅自动刷新了数据,还实现了数据的换行。
      • Demo代码示例:
      public class PrintWriterDemo {
      	
         	public static void main(String[] args) throws IOException {
              // 创建打印流对象
              PrintWriter pw = new PrintWriter("pw2.txt");
      
              pw.print(true);
              pw.print(100);
              pw.print("hello");
              
              //println()方法,等价于: bw.write(); bw.newLine(); bw.flush();三个方法
              pw.println("hello");
              pw.println(true);
              pw.println(100);
              pw.close();
      
          }
      }
      
      运行结果:

字符打印流和字节打印流使用方法一样。




四、随机访问流:RandomAccessFile(速度和效率超级快的流)

RandomAccessFile 概述:

       RandomAccessFile类并不在 Java.IO 包下,所以严格意义上讲,这个类其实不属于流,该类是Object类的子类。但它融合了InputStream和OutputStream的功能,同时还支持对随机访问文件的读取和写入。

       其实这个类和其他流的使用方式和功能都差不多,但是随机访问流和其他流相比更有优先级,比缓冲流还快。
  • 构造方法 :

    • public RandomAccessFile(String name,String mode);
      • 第一个参数是文件路径,第二个参数是操作文件的模式。
        模式有四种,我们最常用的一种叫”rw”,这种方式表示我既可以写数据,也可以读取数据

  • Demo代码示例:

public class RandomAccessFileDemo {
   public static void main(String[] args) throws IOException {

       write();//写
       read();//读

   }

   public static void write() throws IOException{
       try {
           // 创建随机访问流对象
           RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");

           // 写入数据
           raf.writeInt(100);
           raf.writeChar('a');
           raf.writeUTF("华夏");

           raf.close();
       } catch (IOException e) {
           e.printStackTrace();
       }

   }

   public static void read() throws IOException{
       try {
           // 创建随机访问流对象
           RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");

           int i = raf.readInt();
           System.out.println(i);
           // 该文件指针可以通过 getFilePointer方法读取,并通过 seek 方法设置。
           System.out.println("当前文件的指针位置是:" + raf.getFilePointer());

           char ch = raf.readChar();
           System.out.println(ch);
           System.out.println("当前文件的指针位置是:" + raf.getFilePointer());

           String s = raf.readUTF();
           System.out.println(s);
           System.out.println("当前文件的指针位置是:" + raf.getFilePointer());

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

           // 我就要读取a,怎么办呢? 
           raf.seek(4);
           ch = raf.readChar();
           System.out.println(ch);
       } catch (IOException e) {
           e.printStackTrace();
       }
   }

}

运行结果:

文件指针:

       在Java开发中用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。



五、合并流(可以将多个数据源一起写入同一个封装地文件中的流)

概述:

        SequenceInputStream 类可以将多个输入流串流在一起,合并为一个输入流,因此,该流也被称为合并流。
       通俗点讲就是在实现文件复制功能的时候,可以将多个数据源的数据一起存储到同一个封装地文件中。
  • SequenceInputStream 的构造方法
    • SequenceInputStream(InputStream s1, InputStream s2)
    • SequenceInputStream(Enumeration < ? extends InputStream> e)

  • Demo代码示例:

    public class SequenceInputStreamDemo {
    
        public static void main(String[] args) throws IOException {
            //设置多数据源
            InputStream s1 = new FileInputStream("aaa.txt");
            InputStream s2 = new FileInputStream("bbb.txt");
    
            // 将多个数据源存储进合并流对象中
            SequenceInputStream sis = new SequenceInputStream(s1, s2);
            
            // 设置文件封装地
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.txt"));
    
            // 读写操作
            byte[] bys = new byte[1024];
            int len = 0;
            while ((len = sis.read(bys)) != -1) {
                bos.write(bys, 0, len);
            }
    
            bos.close();
            sis.close();
        }
    }
    

    运行结果:




六、序列化流 (操作对象的流)

概述:

        序列化流是 JAVA IO 中专门操作对象的流。 有序列化流和反序列化流两种。
  • 序列化流 :ObjectOutputStream
    • 把对象按照流一样的方式存入文本文件或者在网络中传输。对象 –> 流数据
      • 成员方法:public final void writeObject(Object obj) :将对象转换成流数据,并写入序列化流中(文本或者网络等等地方,俗称封装地文件)

  • 反序列化流:ObjectInputStream
    • 把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 –>对象
      • 成员方法:readObject():用这个方法就可以将流中的对象重新还原成对象

既然是对象转换流,那首先整个实体类,咱 new 个对象(程序猿从不缺对象!!!)

  • 实体类 Demo 代码示例:
//创建实体类
public class Person implements Serializable {

    private String name;//姓名

    private int age;//年龄

    // 构造1
    public Person() {
        super();
    }

    // 构造2
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
  • 将对象转换成流数据 Demo 代码示例:
//序列化流写入数据
public class ObjectOutputStreamDemo{
    public static void main(String[] args) throws IOException {
        // 创建序列化流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("copy.txt"));

        // 创建实体类对象
        Person p = new Person("小丸子", 23);

		//将对象写入流中
        oos.writeObject(p);

        // 释放资源
        oos.close();
    }
}

运行结果:


根据结果可以看不来,这个数据并不能直接使用,呈现乱码状态,因为文本并不能编译 Java 的对象。但是可以看出来对象的路径和对象中存储的部分内容。

  • 将流中的对象数据转换回对象 Demo 代码示例:
//反序列化流 读取数据
public class ObjectInputStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException{

        // 创建反序列化对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                "copy.txt"));

        // 将流中的对象重新还原成对象
        Object obj = ois.readObject();

        // 释放资源
        ois.close();

        // 输出对象
        System.out.println(obj);
    }
}

运行结果:

        这里需要注意一点:当我们在使用反序列化流转换对象时,需要保证正在反序列化的文件中的对象是没被动过的,这里必须要保证该文件中的对象是被序列化过的,否则报错。
        具体的报错信息会根据情况的不同而产生变化,出现此类问题,请联系一下度妈,886。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1031657.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号