Java小记——IO流

目录

字节流

字节流的继承关系

OutPutStream

FileOutputStream

InputStream

复制文件

BufferedInputStream和BufferedOutputStream

字符流

OutputStreamWriter

InputStreamReader

复制

便捷字符流

高效的字符输入输出流

数据输入输出流

内存操作流

ByteArrayOutputStream

ByteArrayInputStream

打印流

字节打印流

字符打印流

复制文件

二种方式键盘录入

随机访问流

序列化流和反序列化流

Properties

顺序流

构造方法


字节流

字节流的抽象基类:

InputStream 读 ,OutputStream 写

字节流的继承关系

 

字节流:可以读写任意类型的文件,比如音频 视频  文本文件

OutPutStream

FileOutputStream

文件输出流是用于将数据写入 File

构造方法

FileOutputStream(File file)

FileOutputStream(String name)

       /*  File file = new File("a.txt");
        if (!file.exists()) {
            file.createNewFile();
        }*/

        //输出流所关联的文件,如果不存在,会自动帮你创建
        FileOutputStream out = new FileOutputStream("a.txt");

        //一次写入一个字节
        out.write(97); //a
        out.write(98); //b
        out.write(99); //c
        out.write(100);//d
        //超过了一个字节,会丢弃掉多余字节
        out.write(300);



        byte[] bytes = {101, 102, 103, 104, 127};
        //一次写入一个字节数组。
        out.write(bytes);



        //一次写入字节 数组的一部分
        fos.write("你好啊!".getBytes(), 0, 6);



        out.write("你好".getBytes());


        //写入回车换行符
        windows下的换行符是 \r\n
        Linux		\n
        Mac		\r

        out.write("\r\n".getBytes());

        //流使用完毕之后,记得释放资源
        out.close();

注意事项:

创建字节输出流对象了做了几件事情?

a:调用系统资源创建a.txt文件

b:创建了一个fos对象

c:把fos对象指向这个文件

为什么一定要close()?

a: 通知系统释放关于管理a.txt文件的资源

b: 让Io流对象变成垃圾,等待垃圾回收器对其回收

       File file = new File("a.txt");
        //true 表示追加写入  false 覆盖
        FileOutputStream out = new FileOutputStream(file, true);

        out.write("春有百花秋有月".getBytes());
        out.write("\r\n".getBytes());
        out.write("夏有凉风冬有雪".getBytes());
        out.write("\r\n".getBytes());
        out.write("若无闲事挂心头".getBytes());
        out.write("\r\n".getBytes());
        out.write("便是人生好时节".getBytes());
        out.write("\r\n".getBytes());

        out.close();

InputStream

输入流所关联的文件如果不存在,就会报错。

       //一次读取一个字节
        int zj = in.read();
        System.out.println(zj);
       /* char ch = (char) zj;
        System.out.println(ch);*/
        zj = in.read();
        System.out.println(zj);
        zj = in.read();
        System.out.println(zj);
        zj = in.read();
        System.out.println(zj);
        zj = in.read();
        System.out.println(zj);
        zj = in.read();
        System.out.println(zj);
        zj = in.read();
        System.out.println(zj);
        //如果读取不到返回 -1 我们要使用-1判断文件是否读取完毕
        zj = in.read();
        System.out.println(zj);

        in.close();

如果不要一个字节一个字节地读取

       //定义一个字节数组,充当缓冲区
        byte[] bytes = new byte[1024];
        //会把读取字节数放到缓冲区
        //int len = in.read(bytes); //返回的是读取到的有效字节个数

        //一次读取9个字节到缓冲区中
        int len = in.read(bytes, 0, 9); //返回的是读取到的有效字节个数

        for (byte aByte : bytes) {
            System.out.println(aByte);
        }
        System.out.println(len);

        String s = new String(bytes, 0, len);
        System.out.println(s);

        in.close();
        FileInputStream in = null;
        try {
            in = new FileInputStream("c.txt");
            //定义一个字节数组,充当缓冲区
            byte[] bytes = new byte[1024];
            //会把读取字节数放到缓冲区
            //int len = in.read(bytes); //返回的是读取到的有效字节个数

            //一次读取9个字节到缓冲区中
            int len = in.read(bytes, 0, 9); //返回的是读取到的有效字节个数
            for (byte aByte : bytes) {
                System.out.println(aByte);
            }
            System.out.println(len);
            String s = new String(bytes, 0, len);
            System.out.println(s);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

复制文件

//读取一个字节,写出一个字节,来复制文件  很显然效率太低
        FileInputStream in = new FileInputStream("唱歌的孩子 - 王峥嵘.mp3");
        FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\aa.mp3");

      /*  while (true) {
            int zj = in.read();
            if (zj == -1) {
                break;
            }
            out.write(zj);
        }*/

        int zj = 0; //定义一个变量,记录读取到的字节
        while ((zj = in.read()) != -1) {
            out.write(zj);
        }
        in.close();
        out.close();
FileInputStream in = new FileInputStream("唱歌的孩子 - 王峥嵘.mp3");
        FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\bb.mp3");
        byte[] bytes = new byte[1024 * 8];
        int len = 0; //定义一个变量,记录读取到有效字节个数
        int i = 0;
        while ((len = in.read(bytes)) != -1) {
            System.out.println(len);
            out.write(bytes, 0, len);
        }
        in.close();
        out.close();

BufferedInputStream和BufferedOutputStream

高效的输入输出流

构造方法

BufferedOutputStream(OutputStream out)

public class MyTest {
    public static void main(String[] args) throws IOException {
        // new BufferedInputStream()
        // new BufferedOutputStream()


        long start = System.currentTimeMillis();
        //copyFile1();
        //copyFile2(); //耗时:154毫秒
        //copyFile3(); //15
        copyFile4(); //耗时:14毫秒
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - start) + "毫秒");  //耗时:32054毫秒

    }

    private static void copyFile2() throws IOException {
        BufferedInputStream bri = new BufferedInputStream(new FileInputStream("许巍 - 曾经的你.mp3"), 1024 * 1024);

        BufferedOutputStream brw = new BufferedOutputStream(new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\b.mp3"));

        int by = 0;
        while ((by = bri.read()) != -1) {
            brw.write(by);
        }

        bri.close();
        brw.close();
    }

    private static void copyFile1() throws IOException {
        FileInputStream in = new FileInputStream("许巍 - 曾经的你.mp3");
        FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\a.mp3");

        int by = 0;
        while ((by = in.read()) != -1) {
            out.write(by);
        }
        in.close();
        out.close();
    }

    private static void copyFile3() throws IOException {
        FileInputStream in = new FileInputStream("许巍 - 曾经的你.mp3");
        FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\a.mp3");
        byte[] bytes = new byte[1024 * 8];
        int len = 0;
        while ((len = in.read(bytes)) != -1) {
            out.write(bytes, 0, len);
        }
        in.close();
        out.close();
    }

    private static void copyFile4() throws IOException {
        BufferedInputStream bri = new BufferedInputStream(new FileInputStream("许巍 - 曾经的你.mp3"), 1024 * 1024);

        BufferedOutputStream brw = new BufferedOutputStream(new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\b.mp3"));

        byte[] bytes = new byte[1024 * 8];
        int len = 0;
        while ((len = bri.read(bytes)) != -1) {
            brw.write(bytes, 0, len);
        }
        bri.close();
        brw.close();
    }

}

字符流

字符流出现的原因:由于字节流操作中文不是特别方便,所以,java就提供了字符流。

继承关系

       //编解码,要使用同一个码表,不然就会后乱码问题
        //编码:把字符串转换为字节数组
        //解码:把字节数组转换为字符串

        String str = "好好学习,天天向上";
        //编码,GBK
        byte[] bytes = str.getBytes("GBK"); //

        //解码
        String s = new String(bytes, "GBK"); //
        System.out.println(s);

OutputStreamWriter

字符转换流

构造方法

OutputStreamWriter(OutputStream out):根据默认编码(GBK)把字节流的数据转换为字符流

OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流

        writer.write('a');
        writer.write("\r\n");
        char[] chars = {'a', 'b', 'c', '你', '好'};
        writer.write(chars);
        writer.write("\r\n");

        writer.write(chars, 3, 2);
        writer.write("\r\n");

        writer.write("一段字符串");
        writer.write("\r\n");
        writer.write("一段字符串", 0, 3);
        writer.write("\r\n");
        writer.flush();
        writer.close();

InputStreamReader

构造方法

InputStreamReader(InputStream is):用默认的编码(GBK)读取数据

InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据

方法

public int read() 一次读取一个字符,如果没有读到 返回-1

public int read(char[] cbuf) 一次读取一个字符数组 如果没有读到 返回-1

        InputStreamReader reader = new InputStreamReader(new FileInputStream("b.txt"));
        int ch = reader.read();
        //char c = (char) ch;
        System.out.println(ch);
        ch = reader.read();
        //char c = (char) ch;
        System.out.println(ch);
        ch = reader.read();
        //char c = (char) ch;
        System.out.println(ch);
        ch = reader.read();
        //char c = (char) ch;
        System.out.println(ch);
        ch = reader.read();
        //char c = (char) ch;
        System.out.println(ch);
        ch = reader.read();
        //char c = (char) ch;
        System.out.println(ch);
        //如读取不到,返回-1 我们可以使用-1来判断文件是否读取完
        ch = reader.read();
        //char c = (char) ch;
        System.out.println(ch);

        reader.close();
        InputStreamReader reader = new InputStreamReader(new FileInputStream("b.txt"));
        //定义一个字符数组,充当容器
        char[] chars = new char[1000];
        //一次可以读取一个字符数组,返回的是实际读取到的字符个数
        // int len = reader.read(chars);
        int len = reader.read(chars, 0, 2); //一次读取几个字符,填充到容器中
        System.out.println(len);
        for (char aChar : chars) {
            System.out.println(aChar);
        }
        String s = String.valueOf(chars, 0, len);
        System.out.println(s);
        reader.close();

复制

 //使用字符流来复制文本文件
        InputStreamReader in = new InputStreamReader(new FileInputStream("MyTest.java"));
        OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Desktop\\a.java"));

        int ch = 0;
        while ((ch = in.read()) != -1) {
            out.write(ch);
            out.flush();
        }
        in.close();
        out.close();





//使用字符流来复制文本文件
        InputStreamReader in = new InputStreamReader(new FileInputStream("MyTest.java"));
        OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\a.java"));
        //定义一个字符数组充当缓冲区
        char[] chars = new char[1024 * 8];
        int len = 0;
        int i = 0;
        while ((len = in.read(chars)) != -1) {
            System.out.println("循环:" + (++i));
            out.write(chars, 0, len);
            out.flush();
        }
        in.close();
        out.close();

便捷字符流

因为转换流的名字太长了,并且在一般情况下我们不需要制定字符集,于是java就给我们提供转换流

对应的便捷类

OutputStreamWriter    -------    FileWriter

InputStreamReader    -------        FileReader

只是换个名字

不用包装

高效的字符输入输出流

构造方法

public BufferedWriter(Writer w)

public BufferedReader(Reader e)

BufferedReader in = new BufferedReader(new FileReader("MyTest.java"));
        BufferedWriter out = new BufferedWriter(new FileWriter("C:\\Users\\Desktop\\c.java"));
        char[] chars = new char[1024 * 8];
        int len = 0;
        int i = 0;
        while ((len = in.read(chars)) != -1) {
            System.out.println("循环:" + (++i));
            out.write(chars, 0, len);
            out.flush();
        }
        in.close();
        out.close();
BufferedReader in = new BufferedReader(new FileReader("MyTest.java"));
        BufferedWriter out = new BufferedWriter(new FileWriter("C:\\Users\\Desktop\\c.java"));

        String s = in.readLine(); //一次读取一行,读取不到返回null
        System.out.println(s);

        out.newLine(); //写出一个换行符,具有平台兼容性。
 //一次读取一行,写入一行来进行复制
        BufferedReader in = new BufferedReader(new FileReader("MyTest.java"));
        BufferedWriter out = new BufferedWriter(new FileWriter("C:\\Users\\ShenMouMou\\Desktop\\ee.java"));
        String line = null;
        while ((line = in.readLine()) != null) {
            out.write(line);
            out.newLine();
            out.flush();
        }
        in.close();
        out.close();

练习

 需求:把ArrayList集合中的字符串数据存储到文本文件*/
        ArrayList<String> list = new ArrayList<>();
        list.add("11");
        list.add("22);
        list.add("33");
        list.add("44");
        //把集合中的数据存储到文件中
        //遍历集合,把数据写到文件中
        //ctrl+Q 可以查看文档
        BufferedWriter writer = new BufferedWriter(new FileWriter("studentName.txt"));
        for (String name : list) {
            writer.write(name);
            writer.newLine();
            writer.flush();
        }
        writer.close();
// 需求:
        // 复制D:\\course这文件夹到E:\\course

        //封装源文件夹
        File srcFolder = new File("C:\\Users\\ShenMouMou\\Desktop\\demo");

        //封装目标文件夹
        File targetFolder = new File("F:\\demo");
        if (!targetFolder.exists()) {
            targetFolder.mkdirs();
        }
        //封装方法
        copyFolder(srcFolder, targetFolder);

        System.out.println("复制完毕!");
    }

    private static void copyFolder(File srcFolder, File targetFolder) throws IOException {
        File[] files = srcFolder.listFiles();
        for (File file : files) {
            if (file.isFile()) {
                //开始复制文件
                copyFiles(file, targetFolder);
            } else {
                //递归
                //封装目标子文件夹
                File mbFolder = new File(targetFolder, file.getName());
                if (!mbFolder.exists()) {
                    mbFolder.mkdirs();
                }
                //递归
                copyFolder(file, mbFolder);
            }
        }
    }

    //复制文件的方法
    private static void copyFiles(File file, File targetFolder) throws IOException {
        //封装源文件
        //修改文件名
        String fileName = file.getName();
        if (fileName.endsWith(".png")) {
            fileName = fileName.substring(0, fileName.lastIndexOf(".")) + ".jpg";
        }
        System.out.println(fileName);
        FileInputStream in = new FileInputStream(file);
        //封装目标文件
        FileOutputStream out = new FileOutputStream(new File(targetFolder, fileName));
        byte[] bytes = new byte[1024 * 8];
        int len = 0;
        while ((len = in.read(bytes)) != -1) {
            out.write(bytes, 0, len);
            out.flush();
        }
        in.close();
        out.close();
    }

数据输入输出流

数据输入流: DataInputStream

数据输出流: DataOutputStream

特点: 可以写基本数据类型,可以读取基本数据类型

//writeData();

        DataInputStream in = new DataInputStream(new FileInputStream("a.txt"));
        //你怎么写的就怎么读,顺序不要乱
        boolean b = in.readBoolean();
        double v = in.readDouble();
        long l = in.readLong();
        String s = in.readUTF();
        System.out.println(b);
        System.out.println(v);
        System.out.println(l);
        System.out.println(s);

        in.close();

    }

    private static void writeData() throws IOException {
        DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt"));
        out.writeBoolean(true);
        out.writeDouble(3.52);
        out.writeLong(6000);
        out.writeUTF("你好");

        out.close();
    }

内存操作流

a:操作字节数组

ByteArrayOutputStream

ByteArrayInputStream

此流关闭无效,所以无需关闭

ByteArrayOutputStream

此类实现了一个输出流,其中的数据被写入一个 byte 数组。

缓冲区会随着数据的不断写入而自动增长。

可使用 toByteArray () 和 toString () 获取数据。

// ByteArrayOutputStream 自己在内存中维护了一个字节数组,充当缓冲区,你可以往他维护的字节数组中,不断的去写入数据,让后在把数据统一取出来

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        bos.write("爱生活".getBytes());
        bos.write("爱Java".getBytes());
        bos.write("好好学习".getBytes());
        bos.write("天天向上".getBytes());

        //我要取出 ByteArrayOutputStream 他自己维护的那个字节数组
        byte[] bytes = bos.toByteArray();

        String s = new String(bytes);

        System.out.println(s);

        String s1 = bos.toString();
        System.out.println(s1);

ByteArrayInputStream

// ByteArrayInputStream
        //ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节.

      /*  ByteArrayInputStream( byte[] buf)
        创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。*/

        byte[] bytes = "包含一个内部缓冲区,该缓冲区包含从流中读取的字节".getBytes();

        ByteArrayInputStream in = new ByteArrayInputStream(bytes);

        byte[] bytes1 = new byte[1024];
        int len = in.read(bytes1);
        System.out.println(len);
        String s = new String(bytes1, 0, len);
        System.out.println(s);

关联文件

//先关联三个文件
        FileInputStream in1 = new FileInputStream("许巍 - 蓝莲花.mp3");
        FileInputStream in2 = new FileInputStream("许巍 - 曾经的你.mp3");
        FileInputStream in3 = new FileInputStream("新上海滩 - 上海滩.mp3");

        ArrayList<FileInputStream> list = new ArrayList<>();
        list.add(in1);
        list.add(in2);
        list.add(in3);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        byte[] bytes = new byte[1024 * 8];
        int len = 0;
        for (FileInputStream in : list) {
            while ((len = in.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }
            in.close(); //关闭流
        }
        //取出三首歌的所有字节
        byte[] allBytes = bos.toByteArray();

        ByteArrayInputStream bis = new ByteArrayInputStream(allBytes);

        FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\歌曲大连唱.mp3");

        byte[] bytes2 = new byte[1024 * 8];
        int len2 = 0;
        while ((len2 = bis.read(bytes2)) != -1) {
            out.write(bytes2, 0, len2);
        }
        out.close();
 //先关联三个文件
        FileInputStream in1 = new FileInputStream("许巍 - 蓝莲花.mp3");
        FileInputStream in2 = new FileInputStream("许巍 - 曾经的你.mp3");
        FileInputStream in3 = new FileInputStream("新上海滩 - 上海滩.mp3");

        ArrayList<FileInputStream> list = new ArrayList<>();

        list.add(in1);
        list.add(in2);
        list.add(in3);

        FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\歌曲大连唱2.mp3");
        byte[] bytes = new byte[1024 * 8];
        int len = 0;
        for (FileInputStream in : list) {
            while ((len = in.read(bytes)) != -1) {
                out.write(bytes, 0, len);
            }
            in.close();
        }
        out.close();

操作字符数组

CharArrayWrite

CharArrayReader

CharArrayWriter writer = new CharArrayWriter();
        writer.write("abc");
        writer.write(new char[]{'j', 'a', 'v', 'a'});

        String s = writer.toString();
        System.out.println(s);

        char[] chars = writer.toCharArray();


       /* StringWriter
                StringReader*/

        StringWriter sw = new StringWriter();
        sw.write("abc");
        sw.write("abc");
        sw.write("abc");
        sw.write("abc");
        sw.write("abc");

        String s1 = sw.toString();
        System.out.println(s1);

练习

LinkedHashMap<String, String> hm = new LinkedHashMap<>();
        hm.put("username", "zhangsan");
        hm.put("password", "123456");
        hm.put("email", "xingyun@163.com");
        hm.put("pone", "13985854525");

        //遍历集合,配合流把集合中的 数据保存到配置 文件中
        BufferedWriter writer = new BufferedWriter(new FileWriter("user.properties"));
        Set<Map.Entry<String, String>> entries = hm.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            String value = entry.getValue();
            writer.write(key + "=" + value);
            writer.newLine();
            writer.flush();
        }

        writer.close();






 //读取配置文件里面的配置 键=值  用双列集合
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        BufferedReader reader = new BufferedReader(new FileReader("user.properties"));
        while (true) {
            String line = reader.readLine();
            if (line == null) {
                break;
            }
            String[] data = line.split("=");
            map.put(data[0], data[1]);
        }

        System.out.println(map);

打印流

打印流只能操作目的地,不能操作数据源(不能进行读取数据)

可以操作任意数据类型的数据 调用print() 方法可以写任意数据类型

字节打印流

        //字节打印流
        PrintStream ps = new PrintStream(new File("bb.txt"));
        ps.println("abc");
        ps.println(false);
        ps.println(3.5);
        ps.close();

        //字节打印流  System.out 获取的是字节打印流

        //“标准”输出流。此流已打开并准备接受输出数据。通常,此流对应于显示器输出
        PrintStream out = System.out;
        out.println(200);
        out.println(true);
        out.println(false);

        System.out.println("hello");

字符打印流

手动刷新 flush()

自动刷新

public PrintWriter(OutputStream out,  boolean autoFlush)     启动 自动刷新

public PrintWriter(Writer out,  boolean autoFlush)        启动自动刷新

通过现有的 OutputStream 创建新的 PrintWriter。*/
        //   PrintWriter pw = new PrintWriter(new File("cc.txt"));

        PrintWriter pw = new PrintWriter(new FileOutputStream("dd.txt"), true);
        pw.println("aaaa");
        pw.println("bbbbb");
        pw.println("ccccc");
        //pw.write("abc"); 自动刷新,对这个方法没有用

        pw.close();

复制文件

public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader("user.properties"));

        PrintWriter writer = new PrintWriter(new FileOutputStream("user2.properties"), true);

        while (true) {
            String s = reader.readLine();
            if (s == null) {
                break;
            }
            writer.println(s);
        }
        reader.close();
        writer.close();
    }

二种方式键盘录入

1.Scanner

2.BufferedReader的readLine方法

InputStream in = System.in;

        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        while (true) {
            System.out.println("请输入数据");
            String s = reader.readLine();
            //自定义结束标记
            if ("886".equals(s)) {
                break;
            }
            System.out.println(s);
        }

        reader.close();
    }

随机访问流

RandomAccessFile

最大特点 能读能写

RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的

功能。

 RandomAccessFile in = new RandomAccessFile("demo.txt", "rw");
        double v = in.readDouble();
        //获取文件指针的位置
        long filePointer = in.getFilePointer(); //8
        System.out.println(filePointer);
        boolean b = in.readBoolean();
        filePointer = in.getFilePointer(); //9
        System.out.println(filePointer);
        int i = in.readInt();
        filePointer = in.getFilePointer(); //13
        System.out.println(filePointer);
        String s = in.readUTF();
        filePointer = in.getFilePointer(); //21
        System.out.println(filePointer);

        //设置这个指针位置
        in.seek(13);
        String s2 = in.readUTF();
        System.out.println(s2);

序列化流和反序列化流

所谓的序列化:就是把对象通过流的方式存储到文件中.注意:此对象 要重写Serializable 接口才能

被序列化

反序列化:就是把文件中存储的对象以流的方式还原成对象

序列化流:    ObjectOutputStream

反序列化流:    ObjectInputStream

public class MyTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //只要我们对内存中的对象进行持久化或网络传输, 这个时候都需要序列化和反序列化. **
        Student student = new Student("张三", 23);
        writeData(student);
        readData();
    }

    private static void readData() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt"));
        //反序列化
        Student object = (Student) in.readObject();
        System.out.println(object.getName());
        System.out.println(object.getAge());
    }

    private static void writeData(Student student) throws IOException {
        //序列化:把Java对象转换成字节序列存储到文件中。
        //反序列化:把文件中的Java对象的字节序列在读取回内存中。
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.txt"));
        //序列化
        //1.需要这个对象对应的那个类,实现一个标记接口 Serializable
        out.writeObject(student);
        out.close();
    }
}



//Serializable 标记接口
public class Student implements Serializable {
    //自己指定一个序列化版本号
    private static final long serialVersionUID = -4973608126061399332L;
    public String name;

    public transient int age;

    public Student() {
    }

    public Student(String name, int age) {
        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 "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class MyTest2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student student1 = new Student("张三", 23);
        Student student2 = new Student("李四", 24);
        Student student3 = new Student("王五", 25);

        //writeData(student1, student2, student3);
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("student2.txt"));
        //反序列化
        Student object = (Student) in.readObject();
        System.out.println(object);
        object = (Student) in.readObject();
        System.out.println(object);
        object = (Student) in.readObject();
        System.out.println(object);

    }

    private static void writeData(Student student1, Student student2, Student student3) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student2.txt"));
        //序列化
        //1.需要这个对象对应的那个类,实现一个标记接口 Serializable
        out.writeObject(student1);
        out.writeObject(student2);
        out.writeObject(student3);
        out.close();
    }

    private static Student readData() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("student2.txt"));
        //反序列化
        Student object = (Student) in.readObject();
        return object;
    }
}

Properties

Properties 类表示了一个持久的属性集。

Properties 可保存在流中或从流中加载。

属性列表中每个键及其对应值都是一个字符串。

Properties父类是Hashtable

属于双列集合,这个集合中的键和值都是字符串 Properties不能指定泛型

public class MyTest {
    public static void main(String[] args) throws IOException {
        // Properties 默认约定好 键和值的泛型是String
        Properties properties = new Properties();
       /* properties.put()
        properties.get()*/
        properties.setProperty("username", "张三");
        properties.setProperty("password", "123456");
        properties.setProperty("email", "xingyun@163.com");
        properties.store(new FileWriter("myUser.properties"), null);

    }
}
public class MyTest2 {
    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        //键和值是用=号隔开的
        properties.load(new FileReader("myUser.properties"));
        System.out.println(properties);
        String username = properties.getProperty("username");
        System.out.println(username);
    }
}

顺序流

SequenceInputStream

表示其他输入流的逻辑串联。

它从输入流的有序集合开始,

并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,

依次类推,直到到达包含的最后一个输入流的文件末尾为止

构造方法

SequenceInputStream(InputStream s1, InputStream s2)   先读取 s1,然后读取 s2

public class MyTest {
    public static void main(String[] args) throws IOException {
        FileInputStream in1 = new FileInputStream("许巍 - 蓝莲花.mp3");
        FileInputStream in2 = new FileInputStream("许巍 - 曾经的你.mp3");

       /* SequenceInputStream(InputStream s1, InputStream s2)
        通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。*/

        SequenceInputStream in = new SequenceInputStream(in1, in2);


        FileOutputStream out = new FileOutputStream("C:\\Users\\Desktop\\歌曲大连唱6.mp3");

        byte[] bytes2 = new byte[1024 * 8];
        int len2 = 0;
        while ((len2 = in.read(bytes2)) != -1) {
            out.write(bytes2, 0, len2);
        }
        out.close();
    }

接入第三方登录是让用户方便快捷地使用已有账号登录你的网站或应用程序,提高用户体验的一种方式。本文将介绍如何使用 PHP 实现微信公众号第三方登录。 1. 获取微信授权 首先,需要获取微信用户的授权。具体步骤如下: 1)引导用户打开微信授权页面: ```php $appid = 'your_appid'; $redirect_uri = urlencode('http://yourdomain.com/callback.php'); $scope = 'snsapi_userinfo'; $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirect_uri&response_type=code&scope=$scope&state=STATE#wechat_redirect"; header("Location: $url"); ``` 其中,`$appid` 是你的微信公众号的 AppID,`$redirect_uri` 是授权后回调的 URL,`$scope` 是授权作用域,可以是 `snsapi_base` 或 `snsapi_userinfo`,`$state` 是自定义参数,用于防止 CSRF 攻击。 2)获取授权码: 用户同意授权后,会重定向到 `$redirect_uri` 指定的 URL,带上授权码 `code` 和 `state` 参数。 ```php $code = $_GET['code']; $state = $_GET['state']; ``` 3)获取 access_token 和 openid: 使用授权码 `code` 获取 `access_token` 和 `openid`。 ```php $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code=$code&grant_type=authorization_code"; $response = file_get_contents($access_token_url); $result = json_decode($response, true); $access_token = $result['access_token']; $openid = $result['openid']; ``` 其中,`$secret` 是你的微信公众号的 AppSecret。 2. 获取用户信息 获取到 `access_token` 和 `openid` 后,可以使用以下代码获取用户信息: ```php $userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN"; $response = file_get_contents($userinfo_url); $userinfo = json_decode($response, true); ``` 其中,`$userinfo` 包含用户的昵称、头像等信息。 3. 将用户信息保存到数据库 最后,将获取到的用户信息保存到数据库中,以便下次使用时快速登录。 ```php // 连接数据库 $con = mysqli_connect('localhost', 'username', 'password', 'database'); mysqli_set_charset($con, "utf8"); // 查询用户是否已存在 $sql = "SELECT * FROM users WHERE openid='$openid'"; $result = mysqli_query($con, $sql); if (mysqli_num_rows($result) == 0) { // 用户不存在,插入新用户信息 $nickname = mysqli_real_escape_string($con, $userinfo['nickname']); $headimgurl = mysqli_real_escape_string($con, $userinfo['headimgurl']); $sql = "INSERT INTO users (openid, nickname, headimgurl) VALUES ('$openid', '$nickname', '$headimgurl')"; mysqli_query($con, $sql); } // 保存用户登录状态 $_SESSION['openid'] = $openid; ``` 以上就是使用 PHP 实现微信公众号第三方登录的步骤。需要注意的是,为了确保安全性,应该对用户输入的数据进行过滤和验证,防止 SQL 注入和 XSS 攻击等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jmh-Ethereal

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值