23.对象流及其他流的使用、网络编程

/**
 * File类与IO流
 *
 * 1. 掌握File类的实例化的方式、熟悉常用的方法
 * 2. IO的概述:① 流的分类 ② 4个抽象基类 ③ 常见的流
 * 3. 文件流:FileReader\FileWriter :处理文本文件
 *           FileInputStream\FileOutputStream : 处理非文本文件
 * 4. 缓冲流:提高数据读写的效率
 *           BufferedReader \ BufferedWriter
 *           BufferedInputStream \ BufferedOutputStream
 * 5. 转换流:实现字节流与字符流之间的转化。
 *           InputStreamReader \ OutputStreamWriter
 *           编码的过程  vs 解码的过程
 *           如何保证不出现文本文件的乱码? 解码使用的字符集要与编码使用的字符集相同!
 * 6.其它流:(了解)
 *   6.1        System.in:标准的输入流,从键盘输入
 *              System.out:标准的输出流,从屏幕输出
 *   6.2        打印流 PrintStream \ PrintWriter
 *   6.3        数据流:DataInputStream \ DataOutputStream
 *
 * 7. 对象流: 传输对象的流。 ObjectInputStream \ ObjectOutputStream
 *          对象的序列化机制!
 * 8. 随机存取文件流:RandomAccessFile
 *
 * 流处理数据的流程:
 * ① 创建流(包括File文件的创建)
 * ② 数据的读取或写出操作
 * ③ 关闭流资源
 *
 * 凡是涉及到资源关闭的操作,一定需要使用try-catch-finally处理异常。否则可能会出现内存泄漏。
 *
 */

1. 其它流的使用

1.1 标准的输入、输出流

@Test
public void test1(){
    Scanner scanner = new Scanner(System.in);

    int i = scanner.nextInt(); //阻塞式的方法
    System.out.println("hello");

    scanner.close();

}

在这里插入图片描述

1.2 打印流

@Test
public void test2(){
    PrintStream ps = null;
    try {
        FileOutputStream fos = new FileOutputStream(new File("D:\\io\\text.txt"));
        // 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
        ps = new PrintStream(fos, true);
        if (ps != null) {// 把标准输出流(控制台输出)改成文件
            System.setOut(ps);
        }
        for (int i = 0; i <= 255; i++) { // 输出ASCII字符
            System.out.print((char) i);
            if (i % 50 == 0) { // 每50个数据一行
                System.out.println(); // 换行
            }
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        if (ps != null) {
            ps.close();
        }
    }
}

在这里插入图片描述

1.3 数据流

//使用DataOutputStream
@Test
public void test3() throws IOException {
    DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("data.dat")));

    dos.writeInt(123);
    dos.writeInt(456);

    dos.writeBoolean(true);

    dos.writeUTF("武汉,你好!");

    dos.close();
}

//使用DataInputStream读取数据文件
@Test
public void test4() throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(new File("data.dat")));

    int num = dis.readInt();
    int num1 = dis.readInt();
    boolean b = dis.readBoolean();
    String info = dis.readUTF();

    System.out.println(num);
    System.out.println(num1);
    System.out.println(b);
    System.out.println(info);

    dis.close();
}

在这里插入图片描述

2. 对象流

2.1 使用对象流

public class ObjectInputOutputStreamTest {

    //序列化过程:将内存中的java对象保存在文件中。使用ObjectOutputStream实现
    @Test
    public void test1() throws IOException {
        //1.
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));
        //2.
        oos.writeObject(new String("Tom"));
        oos.flush();//刷新

        oos.writeObject(new String("Jerry"));
        oos.flush();//刷新

        oos.writeObject(new Person("荣鹏",23,new Pet("大黄")));
        oos.flush();//刷新

        //3.
        oos.close();

    }
    //反序列化过程:将磁盘文件中的数据还原为内存中的java对象。 使用ObjectInputStream实现
    @Test
    public void test2() throws IOException, ClassNotFoundException {
        //1.
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"));
        //2.
        String str1 = (String) ois.readObject();
        String str2 = (String) ois.readObject();
        Person p = (Person) ois.readObject();

        System.out.println(str1);
        System.out.println(str2);
        System.out.println(p);

        //3.
        ois.close();
    }

}

其中,要求读写的对象对应的类,需要是可序列化的。

import java.io.Serializable;

/**
 *
 * 自定义类要想实现序列化机制,需要满足:
 * 1. 实现接口:Serializable
 * 2. 内部声明一个全局常量:serialVersionUID
 * 3. 要求此类的属性都必须是可序列化的
 *
 * 说明:
 * 1. 默认情况下,基本数据类型的变量可序列化。
 * 2. ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
 *
 */
public class Person implements Serializable {
    private static final long serialVersionUID = -6849794667710L;
    private  String name;
    private  int age;
    private Pet pet;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    public Person(String name, int age, Pet pet) {
        this.name = name;
        this.age = age;
        this.pet = pet;
    }

    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 +
                ", pet=" + pet +
                '}';
    }
}

class Pet implements Serializable{
    String name;
    private static final long serialVersionUID = -684967710L;
    @Override
    public String toString() {
        return "Pet{" +
                "name='" + name + '\'' +
                '}';
    }

    public Pet(String name) {
        this.name = name;
    }

    public Pet() {
    }
}

2.2 对象的序列化机制

/* 什么是对象的序列化机制?
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
*/

3. 随机存取文件流

/**
 * RandomAccessFile:随机存取文件流
 *
 * 1. 既是一个输入流,又是一个输出流 (因为实现了DataInput、DataOutput接口)
 * 2. 作为输出流,要输出的文件不存在,则可以在执行过程中,自动创建此文件。
 * 3. 作为输出流,要输出的文件存在,则执行过程中会覆盖原有文件中的内容,而且默认从文件开始的位置覆盖.
 *    我们也可以从指定的位置开始写入数据。
 *
 */
public class RandomAccessFileTest {

    @Test
    public void test1() throws Exception {
        //1.
        RandomAccessFile raf1 = new RandomAccessFile("yangm.png","r");
        RandomAccessFile raf2 = new RandomAccessFile("yangm1.png","rw");
        //2.
        byte[] buffer = new byte[1024];
        int len;
        while((len = raf1.read(buffer)) != -1){
            raf2.write(buffer,0,len);
        }
        //3.
        raf1.close();
        raf2.close();
    }

    @Test
    public void test2() throws IOException {
        RandomAccessFile raf = new RandomAccessFile("hello.txt","rw");

        raf.seek(5);
        raf.write("hello".getBytes());

        raf.close();
    }
}

4. 网络编程概述

/**
 * 一、要想实现网络通信,需要解决的两个问题:
 * 1. 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
 * 2. 找到主机后如何可靠高效地进行数据传输
 *
 * 二、实现网络传输的两个要素:
 * 要素一:IP地址、端口号
 * 要素二:TCP/IP协议
 *
 * 三、IP地址:使用InetAddress类表示
 *   3.1 IP地址分类方式1:IPV4 和 IPV6
 *      IPV4:4个字节组成,4个0-255。
 *      IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,
 *            如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
 *
 *    IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。
 *              192.168.开头的就是私有址址,范围即为192.168.0.0--192.168.255.255
 *
 *    3.2 本地回路地址:127.0.0.1
 *    3.3 域名
 *     www.atguigu.com   www.baidu.com   www.360.com  www.vip.com
 *     www.mi.com   www.jd.com
 *  四、端口号:标识正在计算机上运行的进程(程序)
 *    > 不同的进程有不同的端口号
 *    > 被规定为一个 16 位的整数 0~65535
 *
 */

在这里插入图片描述

5. InetAddress的使用

public class InetAddressTest {
    public static void main(String[] args) {

        try {
            InetAddress inetAddress = InetAddress.getByName("192.168.13.57");
            System.out.println(inetAddress);
			//方式1:getByName(String host)
            InetAddress inetAddress1 = InetAddress.getByName("www.atguigu.com");
            System.out.println(inetAddress1);//www.atguigu.com/36.156.81.239

            //常用方法
            //getHostName():获取主机名
            System.out.println(inetAddress1.getHostName());
            //getHostAddress():获取主机地址
            System.out.println(inetAddress1.getHostAddress());
			
            //方式2:getLocalHost()
            InetAddress inetAddress2 = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

6. TCP网络编程

  • TCP和UDP编程协议的对比:

在这里插入图片描述

  • 例题1:
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 例题1:客户端发送内容给服务端,服务端将内容打印到控制台上。
 *
 */
public class TCPTest1 {
    @Test
    public void client()  { //客户端
        Socket socket = null;
        OutputStream os = null;
        try {
            //1. 封装Socket对象
            //1.1 指名对方的ip地址
            InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
            //1.2 指名对方的端口号
            int port = 8989;

            socket = new Socket(inetAddress,port);
            //2. 通过socket获取输出流,并写出数据
            os = socket.getOutputStream();
            os.write("你好,我是客户端".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3. 关闭相应的资源
            try {
                if(os != null)
                    os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void server()  { //服务器端
        ServerSocket serverSocket = null;
        Socket socket = null;//accept():是一个阻塞式的方法。
        InputStream is = null;
        try {
            //1. 封装ServerSocket的对象
            int port = 8989;
            serverSocket = new ServerSocket(port);
            //2. 接收来自于客户端的socket
            socket = serverSocket.accept();

            //3. 获取客户端发送过来的流数据
            is = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int len;
            while((len = is.read(buffer)) != -1){
                String str = new String(buffer,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            try {
                if(is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            //通常服务器端不会关闭
            try {
                if(serverSocket != null)
                    serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 例题2
import com.sun.deploy.trace.SocketTraceListener;
import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 例题2.客户端发送文件给服务端,服务端将文件保存在本地。
 *
 */
public class TCPTest2 {

    //注意:异常的处理还是应该使用try-catch-finally
    @Test
    public void client() throws IOException {
        //1. 创建Socket
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 8989);
        //2. 提供输入流、输出流
        FileInputStream fis = new FileInputStream(new File("yangm.png"));
        OutputStream os = socket.getOutputStream();
        //3. 读取和写出的过程
        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer)) != -1){
            os.write(buffer,0,len);
        }

        //4.关闭资源
        os.close();
        fis.close();
        socket.close();

    }

    @Test
    public void server() throws IOException {

        //1. 创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(8989);
        //2. 通过ServerSocket,接收来自于客户端的socket
        Socket socket = serverSocket.accept();

        System.out.println("接收到了来自于" + socket.getInetAddress().getHostAddress() + "的数据");

        //3. 创建输入流、输出流
        InputStream is = socket.getInputStream();
        FileOutputStream fos = new FileOutputStream(new File("yangm4.png"));
        //4. 数据的读取和写出的过程
        byte[] buffer = new byte[1024];
        int len;
        while((len = is.read(buffer)) != -1){
            fos.write(buffer,0,len);
        }
        //5. 关闭资源
        fos.close();
        is.close();
        socket.close();

        serverSocket.close();

    }
}
  • 例题3
import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 例题3.从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。并关闭相应的连接。
 *
 */
public class TCPTest3 {

    //注意:异常的处理还是应该使用try-catch-finally
    @Test
    public void client() throws IOException {
        //1. 创建Socket
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 8989);
        //2. 提供输入流、输出流
        FileInputStream fis = new FileInputStream(new File("yangm.png"));
        OutputStream os = socket.getOutputStream();
        //3. 读取和写出的过程
        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer)) != -1){
            os.write(buffer,0,len);
        }

        System.out.println("图片发送完成");
        //显式执行数据发送完成,告知服务器端
        socket.shutdownOutput();

        //4.接收来自于服务器端的数据
        InputStream is = socket.getInputStream();
        byte[] newBuffer = new byte[1024];
        int newLen;
        while((newLen = is.read(newBuffer)) != -1){
            String str = new String(newBuffer,0,newLen);
            System.out.print(str);
        }

        //5.关闭资源
        os.close();
        fis.close();
        socket.close();

    }

    @Test
    public void server() throws IOException {

        //1. 创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(8989);
        //2. 通过ServerSocket,接收来自于客户端的socket
        Socket socket = serverSocket.accept();

        System.out.println("接收到了来自于" + socket.getInetAddress().getHostAddress() + "的数据");

        //3. 创建输入流、输出流
        InputStream is = socket.getInputStream();
        FileOutputStream fos = new FileOutputStream(new File("yangm7.png"));
        //4. 数据的读取和写出的过程
        byte[] buffer = new byte[1024];
        int len;
        while((len = is.read(buffer)) != -1){
            fos.write(buffer,0,len);
        }

        System.out.println("Server:图片接收完成");

        //5.服务器端发送“接收成功"给客户端
        OutputStream os = socket.getOutputStream();
        os.write("接收成功".getBytes());

        //6. 关闭资源
        fos.close();
        is.close();
        socket.close();

        serverSocket.close();
    }
}

7. UDP网络编程

import org.junit.Test;

import java.io.IOException;
import java.net.*;

public class UDPTest {

    @Test
    public void sender() throws IOException {//发送端
        //创建socket的实例
        DatagramSocket socket = new DatagramSocket();
        //封装数据、目的地到数据报中
        byte[] buffer = "hello,I am sender!".getBytes();
        DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length, InetAddress.getLocalHost(),9090);
        //发送数据报
        socket.send(packet);
        //关闭资源
        socket.close();

    }

    @Test
    public void receiver() throws IOException {//接收端
        //创建socket的实例
        DatagramSocket socket = new DatagramSocket(9090);
        //封装一个数据报
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
        //接收数据到数据报中
        socket.receive(packet);
        //读取数据并显示到控制台上
        String str = new String(packet.getData(),0,packet.getLength());
        System.out.println(str);
        //关闭资源
        socket.close();
    }
}

8.URL编程

/**
 * URL: 统一资源定位符,它表示 Internet 上某一资源的地址。
 *
 * 比如:http://192.168.13.136:8080/examples/wbb.png?keyword=apple
 *      协议    ip地址         端口号  资源地址        参数列表
 *
 */
public class URLTest {

    public static void main(String[] args) {
        try {

            URL url = new URL("http://192.168.13.136:8080/examples/wbb.png?keyword=apple");
//            public String getProtocol(  )     获取该URL的协议名
//            public String getHost(  )           获取该URL的主机名
//            public String getPort(  )            获取该URL的端口号
//            public String getPath(  )           获取该URL的文件路径
//            public String getFile(  )             获取该URL的文件名
//            public String getQuery(   )        获取该URL的查询名

            System.out.println(url.getProtocol());
            System.out.println(url.getHost());
            System.out.println(url.getPort());
            System.out.println(url.getPath());
            System.out.println(url.getFile());
            System.out.println(url.getQuery());

        } catch (MalformedURLException e) {
            e.printStackTrace();

        }
    }
}
  • 例题:将数据从服务器端下载到本地
public class URLTest1 {

    public static void main(String[] args) {


        HttpURLConnection urlConnection = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            URL url = new URL("http://192.168.13.136:8080/examples/wbb1.png");

            urlConnection = (HttpURLConnection) url.openConnection();

            is = urlConnection.getInputStream();
            fos = new FileOutputStream(new File("wbb.png"));
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            System.out.println("下载完成");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (urlConnection != null)
                urlConnection.disconnect();//断开连接
        }
    }
}
w File("wbb.png"));
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            System.out.println("下载完成");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (urlConnection != null)
                urlConnection.disconnect();//断开连接
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值