输入输出流、网络编程

对象序列化机制

1. 对象流

ObjectInputStream 和 ObjectOutputStream

2. 作用:

ObjectInputStream: 内存中的对象 --> 存储中的文件、通过网络传输出去

ObjectOutputStream:存储中的文件、通过网络接收过来 --> 内存中的对象

3. 对象的序列化机制

序列化:可以把内存中的 Java 对象转换成二进制流,从而实现 Java 对象的持久化存储或通过网络发送。

反序列化:从本地存储或网络中获取的二进制流恢复成 Java 对象。

4. 序列化代码实现:
	ObjectOutputStream oos = null;
	/**
     * 测试ObjectOutputStream流,也就是对象的序列化机制
     */
    @Test
    public void testObjectOutputStream() {
        try {
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));

            // 向流中添加三组数据
            oos.writeObject(new String("我爱北京天安门"));
            oos.flush(); // 刷新流

            oos.writeObject(new Person("香芋",21));
            oos.flush();

            oos.writeObject(new Person("芳旭",19,111,new Account(1000)));
            oos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
5. 反序列化代码实现
	ObjectInputStream ois = null; // 对象输入流
	/**
     * 测试 ObjectInputStream 反序列化
     * 注意读的时候 readObject() 的顺序不能变
     */
    @Test
    public void testObjectInputStream() {
        try {
            ois = new ObjectInputStream(new FileInputStream("object.dat"));
            String str = (String) ois.readObject();
            Person p1 = (Person) ois.readObject();
            Person p2 = (Person) ois.readObject();

            System.out.println(str);
            System.out.println(p1);
            System.out.println(p2);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (ois != null) {
                    ois.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
6. 实现序列化的对象所属的类需要满足:
  1. 实现序列化接口 Serializable
  2. 当前类提供一个全局常量: serialVersionUID
  3. 除了当前类需要实现 Serializable 接口外,类中的其他属性也必须是可序列化的(基本数据类型默认可序列化)

RandomAccessFile 随机存取文件流

1. 随机存取文件流
  1. RandomAccessFile 直接继承于 java.lang.Object 类,实现了 DataInput 和 DataOutput 接口。
  2. RandomAccessFile 既可以作为一个输出流,也可以作为一个输入流(既可读又可写)。
  3. 如果 RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。如果写出到的文件已存在,则会对原有文件的内容进行覆盖(默认从头覆盖)。
  4. 可以通过相关的操作,实现 RandomAccessFile “插入”数据的效果。也就是 seek(int position) 方法。
2. 代码实现
	RandomAccessFile raf1 = null;
    RandomAccessFile raf2 = null;

    /**
     * 使用 RandomAccessFile 随机存取文件流实现复制一个文件重命名的效果
     */
    @Test
    public void test1() {
        try {
            raf1 = new RandomAccessFile(new File("test.jpg"),"r");
            raf2 = new RandomAccessFile(new File("test1.jpg"),"rw");
            byte[] buffer = new byte[1024];
            int len;
            while ((len = raf1.read(buffer)) != -1) {
                raf2.write(buffer,0,len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (raf1 != null) {
                try {
                    raf1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (raf2 != null) {
                try {
                    raf2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    RandomAccessFile raf1 = null;
	/**
     * 使用 RandomAccessFile 实现数据的插入效果
     */
    @Test
    public void test2() {
        try {
            raf1 = new RandomAccessFile("hello.txt","rw");
            raf1.seek(3); // 将指针调到角标为3的位置
            // 保存指针3后面的数据到 StringBuilder 中
            StringBuilder builder = new StringBuilder((int) (new File("hello.txt").length()));
            byte[] buffer = new byte[20];
            int len;
            while((len = raf1.read(buffer)) != -1) {
                builder.append(new String(buffer,0,len)); // 读到的内容追加到builder后面
            }
            // 回调指针,写入xyz
            raf1.seek(3);
            raf1.write("xyz".getBytes(StandardCharsets.UTF_8));

            // 将 StringBuilder 中的数据写回文件中
            raf1.write(builder.toString().getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                raf1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

NIO

1.是什么?

Java NIO (New IO , Non-Blocking IO 非阻塞式IO),Java1.4引入,Java1.7优化(NIO.2)。实际开发中并不常用。

Path、Paths 和 Files

1. Path

  • 替换原有的 File 类
1.1. 如何实例化
  • static Path get(String first, String … more) 用于将多个字符串连成路径
  • static Path get(Url url) 返回指定 url 对应的 Path 路径
1.2. 常用方法:
  • String toString(); 返回调用 Path 对象的字符串表示形式
  • boolean startsWith(String path); 是否以 path 路径开始
  • boolean endsWith(String path); 是否以 path 路径结束
  • boolean isAbsolute(); 是否是绝对路径
  • Path getParent(); 返回 Path 对象包含整个路径,不包含 Path 对象指定的文件路径
  • Path getRoot(); 返回调用 Path 对象的根路径
  • Path getFileName(); 返回调用 Path 对象关联的文件名
  • int getNameCount(); 返回 Path 根目录后面元素的数量
  • Path getName(int index); 返回指定索引位置 index 的路径名称
  • Path toAbsolutePath(); 作为绝对路径返回调用 Path 对象
  • Path resolve(Path p); 合并两个路径,返回合并后的路径对应的 Path 对象
  • File toFile(); 将Path 转化为 File 类的对象

2. Files 工具类

2.1. 作用
  • 操作文件或文件目录
2.2. 常用方法
  1. 常用方法
    • Path copy (Path src, Path dest, CopyOption … how); 文件的复制
    • Path createDirectory(Path path, FileAttribute<?> … attr); 创建一个目录
    • Path createFile(Path path, FileAttribute<?> … arr); 创建一个文件
    • void delete(Path path); 删除一个目录/文件,如果不存在,则执行报错
    • void deleteIfExists(Path path); Path 对应的目录/文件如果存在,执行删除
    • Path move(Path src, Path dest, CopyOption … how); 将 src 移动到 dest 的位置
    • long size(Path path); 返回 Path 指定文件的大小
  2. 用于判断的方法
    • boolean exists(Path path, LinkOption … opts); 文件是否存在
    • boolean isDirectory(Path path, LinkOption … opts); 是否是目录
    • boolean isRegulaFile(Path path, LinkOption … opts); 是否是文件
    • boolean isHidden(Path path); 文件是否隐藏
    • boolean isReadable(Path path); 文件是否可读
    • boolean isWritable(Path path); 文件是否可写
    • boolean notExists(Path path, LinkOption … opts); 判断文件是否不存在
  3. 用于操作内容的方法
    • SeekableByteChannel newByteChannel(Path path, OpenOption … how); 获取与指定文件的链接,how 指定打开方式
    • DirectoryStream newDirectoryStream(Path path); 打开 Path 指定的目录
    • InputStream newInputStream(Path path, OpenOption … how); 获取 InputStream 对象
    • OutputStream newOutputStream(Path path, OpenOption … how); 获取 OutputStream对象

网络编程

一、实现网络通信需要解决的两个问题

  1. 如何准确的定位网络上一台或多台主机,定位主机上特定的应用

    使用TCP/IP协议,端口号定位应用

  2. 找到主机后如何高效的进行数据传输

    依据协议发送报文

二、网络通信的两个要素

  1. IP和端口号
  2. 提供网络通信协议:TCP/IP参考模型(应用层、传输层、网络层、物理+数据链路层)

三、通信要素一:IP和端口号

1. IP的理解
  1. IP是在 Internet 网络中计算机(通信实体)的唯一标识
  2. 在 Java 中使用 InetAddress 类代表 IP
  3. IP 的分类:IPv4 和 IPv6;万维网和局域网
  4. 域名:www.baidu.com
  5. 本地回环:127.0.0.1 也就是 localhost
2. InetAddress 类

此类的一个对象就代表着一个具体的IP地址

  1. 如何实例化 InetAddress?
    1. getByName(String host)
    2. getLocalHost()
  2. InetAddress 类的两个常用方法
    1. getHostName()
    2. getHostAddress()
3. 端口号

用来区分某个 IP 下不同的进程

要求:不同的进程有不同的端口号

范围:被规定为一个 16 位的整数 0 ~ 65536

端接口号和IP地址组合在一起成为一个 Socket 套接字

四、网络通信协议

1. 分层模型

img

2. TCP 和 UDP 的区别?
  1. TCP 使用前必须先采用 “三次握手”的方式建立连接否则会报错;UDP 则不需要,服务端只管发送消息,不关心客户端是否收到,客户端也无需确认消息,所以是不可靠的。
3. TCP 的三次握手和四次挥手

img

5536

端接口号和IP地址组合在一起成为一个 Socket 套接字

四、网络通信协议

1. 分层模型

[外链图片转存中…(img-5cNu3NcZ-1656560858437)]

2. TCP 和 UDP 的区别?
  1. TCP 使用前必须先采用 “三次握手”的方式建立连接否则会报错;UDP 则不需要,服务端只管发送消息,不关心客户端是否收到,客户端也无需确认消息,所以是不可靠的。
3. TCP 的三次握手和四次挥手

[外链图片转存中…(img-zSjBnhSu-1656560858438)]

img

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值