22-java学习-IO流-数据输入输出流、内存操作流、打印流、序列化流、随机访问流、Properties&案例代码

22-java学习-IO流-数据输入输出流、内存操作流、打印流、序列化流、随机访问流、Properties&案例代码

目录:

数据输入输出流
内存操作流
打印流
序列化流
随机访问流
Properties

1.数据输入输出流的概述和使用

A:数据输入输出流的概述
	通过API查看
	 数据输入和输出流:
数据输入流: DataInputStream
数据输出流: DataOutputStream
特点: 可以写基本数据类型,可以读取基本数据类型
//B:案例演示:	数据输入输出流的使用
public class MyTest {
    public static void main(String[] args) throws IOException {
        /*数据输入流:
        DataInputStream
        数据输出流:
        DataOutputStream
        特点:
        可以写基本数据类型, 可以读取基本数据类型*/
        //注意:你怎么写的就怎么读取,顺序不要乱。
        //writeData();
        DataInputStream dis = new DataInputStream(new FileInputStream("a.txt"));
        boolean b = dis.readBoolean();
        double v = dis.readDouble();
        int i = dis.readInt();
        String s = dis.readUTF();
        System.out.println(b);
        System.out.println(v);
        System.out.println(i);
        System.out.println(s);
        dis.close();


    }

    private static void writeData() throws IOException {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("a.txt"));
        dos.writeBoolean(true);
        dos.writeDouble(3.14);
        dos.writeInt(2000);
        dos.writeUTF("字符串");
        dos.close();
    }
}

2.内存操作流的概述和使用

A:内存操作流的概述
	a:操作字节数组
		ByteArrayOutputStream
		ByteArrayInputStream
		此流关闭无效,所以无需关闭
	b:操作字符数组
		CharArrayWrite
		CharArrayReader
	c:操作字符串
		StringWriter
		StringReader		
//B:案例演示:内存操作流的使用,构造方法: public ByteArrayOutputStream()
public class MyTest2 {
    public static void main(String[] args) throws IOException {
        //内存操作流:不直接关联文件,只在内存中操作。
       /* a:
        操作字节数组
        ByteArrayOutputStream
        ByteArrayInputStream*/


      //  ByteArrayOutputStream
      // 1.此类实现了一个输出流,其中的数据被写入一个 byte 数组。
      // 2.  缓冲区会随着数据的不断写入而自动增长。
      // 3. 可使用 toByteArray () 和 toString () 获取数据。
      //  4.关闭 ByteArrayOutputStream 无效。
      //  此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。

      /*  ByteArrayOutputStream()
        创建一个新的 byte 数组输出流。*/
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //我们把数据写入内存操作流中
        bos.write("好好学习".getBytes());
        bos.write("天天向上".getBytes());
        bos.write("爱生活".getBytes());
        bos.write("爱Java".getBytes());
        //取出bos 所维护的字节数
        byte[] maxBytes= bos.toByteArray();
        String s = new String(maxBytes);
        //String s = bos.toString();
        System.out.println(s);
        //bos.close(); 此流无需关闭

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

        //ByteArrayInputStream( byte[] buf)
        //创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。
        ByteArrayInputStream bis = new ByteArrayInputStream(maxBytes);
        int len=0;
        byte[] bytes = new byte[1024*8];
        int len2 = bis.read(bytes);
        String s1 = new String(bytes, 0, len2);
        System.out.println(s1);

    }
}

3.打印流的概述和特点以及作为Writer的子类使用

A:打印流的概述
	通过API查看
	字节流打印流
	字符打印流
B:打印流的特点
	a: 打印流只能操作目的地,不能操作数据源(不能进行读取数据)
	- b: 可以操作任意数据类型的数据 调用print() 方法可以写任意数据类型

- c: 如果我们启用自动刷新,那么在调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新
  		/**
  		通过以下构造创建对象 能够启动自动刷新  然后调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新
  	 * public PrintWriter(OutputStream out,  boolean autoFlush)	 启动 自动刷新
  	 * public PrintWriter(Writer out,  boolean autoFlush)		启动自动刷新
  	 */

- d: 这个流可以直接对文件进行操作(可以直接操作文件的流: 就是构造方法的参数可以传递文件或者文件路径)
// C:案例演示:	PrintWriter作为Writer的子类使用
public class MyTest3 {
    public static void main(String[] args) throws IOException {
        //内存操作 流,他底层维护的缓冲区是字符数组
       /* CharArrayWrite
          CharArrayReader*/
        CharArrayWriter out = new CharArrayWriter();
        out.write("abc");
        out.write("dcccc");
        out.write("eeeee");
        /*char[] chars = out.toCharArray();
        String s = String.valueOf(chars);*/
        String string = out.toString();
        System.out.println(string);

        CharArrayReader charArrayReader = new CharArrayReader(out.toCharArray());
        int read = charArrayReader.read();
        System.out.println(read);
    }
}

4.PrintWriter实现自动刷新和换行

A:案例演示:PrintWriter实现自动刷新和换行
	PrintWriter pw = new PrintWriter(new FileWriter("printWriter2.txt") , true) ;
	pw.println(true) ;
	pw.println(100) ;
	pw.println("中国") ;

public class MyTest2 {
    public static void main(String[] args) throws FileNotFoundException {
        //字符打印流
        //PrintWriter(File file)
        //使用指定文件创建不具有自动行刷新的新 PrintWriter。
        //PrintWriter(String fileName)
        //创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
        PrintWriter printWriter = new PrintWriter("c.txt");
        printWriter.write("abc");
        printWriter.flush();
        printWriter.close();
    }
}

5.打印流复制文本文件

A:案例演示:	打印流复制文本文件
分析:
- 这个打印流只能进行写数据,不能进行读取数据,
  	那么我们应该找一个可以读取文本文件中的的数据的流对象进行读取操作.
- 而我们非常喜欢高效的流对象,于是我们可以使用BufferedReader进行读取数据.

public class MyTest4 {
    public static void main(String[] args) throws IOException {
        //利用打印流跟其他流配合来复制文本文件
        BufferedReader bfr = new BufferedReader(new FileReader("MyTest.java"));
        PrintWriter printWriter = new PrintWriter(new FileOutputStream("MyTestCopy.java"),true);
        String line=null;
        while ((line=bfr.readLine())!=null){
            printWriter.println(line);
        }
        bfr.close();
        printWriter.close();

        InputStream in = System.in;
        System.out.println(in);
    }
}

6.标准输入输出流概述和输出语句的本质

A:标准输入输出流概述
	在System这个类中存在两个静态的成员变量:
- public static final InputStream in: 标准输入流, 对应的设备是键盘

- public static final PrintStream out: 标准输出流 , 对应的设备就是显示器
  	System.in的类型是InputStream.
  	System.out的类型是PrintStream是OutputStream的孙子类FilterOutputStream 的子类.

7.二种方式实现键盘录入

A:Scanner
B:BufferedReader的readLine方法。
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public class MyTest {
    public static void main(String[] args) throws IOException {
       // BufferedReader 里面有个方法 readLine()
        //这个时候他关联的是键盘了
        BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
        //就能从键盘录入数据了
        while (true){
            System.out.println("请输入数据");
            String s = bfr.readLine();
            if(s.equals("886")){ //自定义一个结束标记
                break;
            }
            System.out.println(s);
        }
    }
}

8.输出语句用字符缓冲流改进

A:案例演示:	输出语句用字符缓冲流改进
/**
	 * 获取System下的in成员变量
	 */
	InputStream in = System.in ;
	
	/**
	 * in是一个字节输入流对象,那么我们就可以通过这个字节输入流对象进行读取键盘录入的数据.
	 * 那么我们既然要读取数据,之前我们讲解了两种读取数据的方式:
	 * 	 1. 一次读取一个字节
	 * 	 2. 一次读取一个字节数组
	 * 那么我们在这个地方使用那种读取方式. 经过分析,这两种读取方式都不太合适.因为数据是客户通过键盘录入
	 * 进来的,而我们希望直接读取一行数据. 而既然要读取一行数据,那么我们就需要使用readLine方法,而这个方法
	 * 是属于BufferedReader的方法,而我们就需要创建一个BufferedReader对象进行读取数据.而我们这in有属于
	 * 字节流,而创建BufferedReader对象的时候需要一个字符流,而我们就需要将这个字节流转换成字符流,那么既然
	 * 要对其进行转换,那么就需要使用转换流. 需要使用InputStreamReader
	 */

9.随机访问流概述和写出数据

A:随机访问流概述
	RandomAccessFile概述 最大特点 能读能写
	RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。
	支持对随机访问文件的读取和写入。

	 RandomAccessFile的父类是Object , 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据.
我们可以通过getFilePointer方法获取文件指针,并且可以通过seek方法设置文件指针

10.序列化流和反序列化流的概述和使用

A:序列化流的概述
	所谓的序列化:就是把对象通过流的方式存储到文件中.注意:此对象 要重写Serializable 接口才能被序列化
	反序列化:就是把文件中存储的对象以流的方式还原成对象
	序列化流:	ObjectOutputStream
	反序列化流:	ObjectInputStream
	 
	 像这样一个接口中如果没有方法,那么这样的接口我们将其称之为标记接口(用来给类打标记的,相当于猪肉身上盖个章)
 一个对象可以被序列化的前提是这个对象对应的类必须实现Serializable接口
// B:案例演示:	对象序列化和反序列化的基本使用
public class MyTest2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        writeObj();
    }

    private static void readObj() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt"));
        Student student = (Student) in.readObject();
        System.out.println(student.getName());
        System.out.println(student.getAge());
    }

    private static void writeObj() throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.txt"));
        Student student = new Student("张三", 23);
        //将对象写入到文本文件中保存起来。
        //NotSerializableException 不能序列化的异常。
        out.writeObject(student);
        out.close();
    }
}

11.如何解决序列化时候的黄色警告线问题

解决序列化时候的黄色警告线问题

- 我们的一个类可以被序列化的前提是需要这个类实现Serializable接口,就需要给这个类添加一个标记.
- 在完成序列化以后,序列化文件中还存在一个标记,然后在进行反序列化的时候,
  会验证这个标记和序列化前的标记是否一致,如果一致就正常进行反序列化,如果
- 不一致就报错了. 而现在我们把这个类做了修改,将相当于更改了标记,而导致这两个标记不一致,就报错了.
- 
- 解决问题: 只要让这个两个标记一致,就不会报错了 
- 怎么让这两个标记一致呢? 	不用担心,很简单,难道你们没有看见黄色警告线吗? alt+enter, 生成出来
private static final long serialVersionUID = -7602640005373026150L;

12.如何让对象的成员变量不被序列化

A:如何让对象的成员变量不被序列化
	使用transient关键字声明不需要序列化的成员变量
	private transient int age ;// 可以阻止成员变量的序列化使用transient

13.Properties的概述和作为Map集合的使用

A:Properties的概述
	查看API
	Properties 类表示了一个持久的属性集。
	Properties 可保存在流中或从流中加载。
	属性列表中每个键及其对应值都是一个字符串。
	Properties父类是Hashtable
	- 属于双列集合,这个集合中的键和值都是字符串 Properties不能指定泛型

14.Properties的特殊功能使用

A:Properties的特殊功能
	public Object setProperty(String key,String value)
	public String getProperty(String key)
	public Set stringPropertyNames()

15.Properties的load()和store()功能

A:Properties的load()和store()功能
	 Properties和IO流进行配合使用:
	 - public void load(Reader reader): 读取键值对数据把数据存储到Properties中

- public void store(Writer writer, String comments)把Properties集合中的键值对数据写入到文件中, comments注释
//B:案例演示 Properties的load()和store()功能
public class MyTest3 {
    public static void main(String[] args) throws IOException {
       Properties properties = new Properties();
        properties.setProperty("username", "张三");
        properties.setProperty("password", "123456");
        //这个属性集合有特有的方法,可以把集合中的键值数据存到文件中 键值之间以 =拼接
        properties.store(new FileWriter("user.properties"),null);
        System.out.println("=======================================================");
        //我们可以把文件中的键值数据读取回集合
        //Properties 属性集合类 读取文件,对文件有要求,1,键值是以=拼接的。2.文件的后缀名是 .properties
        Properties properties2 = new Properties();
        properties2.load(new FileReader("user.properties"));
        System.out.println(properties2);
    }
}

16.判断文件中是否有指定的键如果有就修改值的

    //需求:我有一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。
	      //请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100”
    //分析:
	//- a:  把文本文件中的数据加载到Properties集合中
	//- b:  判断这个集合中是否有"lisi"这个键
	//- 如果有直接修改其值为100
	//- c:  把集合中的数据再次存储到文本文件中
public class MyTest5 {
    public static void main(String[] args) throws IOException {
        //把文本文件中的数据读取到集合中
        Properties properties = new Properties();
        properties.load(new FileInputStream("demo.properties"));
        if(properties.containsKey("lisi")){
        properties.setProperty("lisi","100"); //键相同,值覆盖
        //再写道文件中覆盖掉旧数据
        properties.store(new FileWriter("demo.properties"),null);
        }
    }
}

17.SequenceInputStream

//A:案例需求:将a.txt和b.txt两个文本文件的内容合并到c.txt
public class MyTest {
    public static void main(String[] args) throws IOException {
        //A:
        //案例需求:
        //将a.txt和b.txt两个文本文件的内容合并到c.txt
        FileInputStream in1 = new FileInputStream("许巍 - 蓝莲花.mp3");
        FileInputStream in2 = new FileInputStream("许巍 - 曾经的你.mp3");

        //我们可以使用顺序流,把多个文件合并成一个文件。
       // SequenceInputStream
       // SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
       // SequenceInputStream(InputStream s1, InputStream s2)
       // 通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。

        SequenceInputStream in = new SequenceInputStream(in1, in2);
        FileOutputStream out = new FileOutputStream("许巍歌曲大联唱.mp3");
        int len=0;
        byte[] bytes=new byte[1024*8];

        while ((len=in.read(bytes))!=-1){
            out.write(bytes,0,len);
            out.flush();
        }
        in.close();
        out.close();
    }
}
//B:案例需求:采用SequenceInputStream来改进
public class MyTest2 {
    public static void main(String[] args) throws IOException {
        FileInputStream in1 = new FileInputStream("许巍 - 蓝莲花.mp3");
        FileInputStream in2 = new FileInputStream("许巍 - 曾经的你.mp3");
        FileInputStream in3 = new FileInputStream("许巍 - 蓝莲花.mp3");
        FileInputStream in4 = new FileInputStream("许巍 - 曾经的你.mp3");
        SequenceInputStream sequenceInputStream = new SequenceInputStream(in1, in2);
        SequenceInputStream sequenceInputStream2 = new SequenceInputStream(sequenceInputStream, in3);
        SequenceInputStream sequenceInputStream3 = new SequenceInputStream(sequenceInputStream2, in4);
    }
}
//C:将一个music.mp3文件,拆分成多个小文件,再将多个小文件,合并成一个mp3文件
public class MyTest3 {
    public static void main(String[] args) throws IOException {
        //SequenceInputStream(Enumeration < ? extends InputStream > e)
        //通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。


        FileInputStream in1 = new FileInputStream("许巍 - 蓝莲花.mp3");
        FileInputStream in2 = new FileInputStream("许巍 - 曾经的你.mp3");
        FileInputStream in3 = new FileInputStream("许巍 - 蓝莲花.mp3");
        FileInputStream in4 = new FileInputStream("许巍 - 曾经的你.mp3");
        Vector<FileInputStream> vector = new Vector<>();
        vector.add(in1);
        vector.add(in2);
        vector.add(in3);
        vector.add(in4);

        Enumeration<FileInputStream> elements = vector.elements();
        //while (elements.hasMoreElements()) {
        //    FileInputStream fileInputStream = elements.nextElement();
        //}
        SequenceInputStream in = new SequenceInputStream(elements);
        FileOutputStream out = new FileOutputStream("许巍歌曲大联唱.mp3");
        int len = 0;
        byte[] bytes = new byte[1024 * 8];

        while ((len = in.read(bytes)) != -1) {
            out.write(bytes, 0, len);
            out.flush();
        }
        in.close();
        out.close();
    }
}
D:SequenceInputStream 
	表示其他输入流的逻辑串联。
	它从输入流的有序集合开始,
	并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,
	依次类推,直到到达包含的最后一个输入流的文件末尾为止
	a:构造方法
	SequenceInputStream(InputStream s1, InputStream s2) 
	通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),
	以提供从此 SequenceInputStream 读取的字节。
	b:构造方法
	SequenceInputStream(Enumeration e) 
	 通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。

18.压缩流ZipOutputStream和解压流ZipInputStream

ZipOutputStream  压缩流
      void putNextEntry(ZipEntry e) 
          开始写入新的 ZIP 文件条目并将流定位到条目数据的开始处。 
ZipInputStream  解压流
     ZipEntry getNextEntry() 
          读取下一个 ZIP 文件条目并将流定位到该条目数据的开始处。 
  
类 ZipEntry  此类用于表示 ZIP 文件条目。
	String getName() 返回条目名称。 
	boolean isDirectory() 如果为目录条目,则返回 true。 

你可能感兴趣的:(学习笔记)