InputStreamReader
是 Java 中的一个类,它可以将字节输入流转换为字符输入流。它可以读取字节输入流,并使用指定的字符集将字节解码为字符。
InputStreamReader继承了Reader类
Scanner scanner = new Scanner(System.in);//这是一个控制台输入的一个类,但是用的不多
String s = scanner.next();//读取一个单词,遇到空格就会停止
scanner.nextInt();//能够获取指定类型的数据
String s2 = scanner.nextLine();//读取一行,读取的效率是比较高的。
System.in的返回值是InputStream类型的数据。
其缺点是只能读取字符 !
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String data = inputStreamReader.readLine();
上面这段代码和Scanner的nextLine()有异曲同工之妙!
Java开发语言中,输入输出流是非常重要的一部分,可以用于与文件、网络等各种资源进行交互。其中BufferedReader
类是Java的输入流类之一,主要用于从字符输入流中读取文本,并将文本缓存到缓冲区中,从而提高读取文本的效率。BufferedReader继承了Reader类
BufferedReader是Java I/O中的一个类,它是一个带缓冲区的字符输入流,用于从字符输入流中读取字符。它提供了一种逐行读取文本文件的方法,可以轻松地读取大量文本数据,并且可以通过使用缓冲区来提高读取效率。它的主要作用是读取文本文件中的字符数据,可以读取文件中的每一行数据,是Java I/O中常用的数据读取类之一。BufferedReader类只能读取字符类型的数据,如果需要读取其他类型的数据需要进行类型转换。
优点:
- 数据缓存:通过BufferedReader类的缓存机制,可以在读取文本数据时,提高读取效率。
- 读取方式:BufferedReader类提供以行为单位读取数据的方法,可以方便地逐行解析文本数据。
缺点:
- 由于
BufferedReader
是基于字符流的,对于读取二进制文件并不适用,不适合处理字节流。 - 缓冲区的大小是固定的,如果输入流的内容超过了缓冲区大小,会导致缓冲区溢出。
- 当BufferedReader类读取数据时,如果发生异常或读取过程中程序意外终止,可能会导致数据丢失
在java网络编程,shutdownOutput,shutdownInput可以表示和控制台说一次标记结束,表示input或者output结束。但是用这种方式会导致此套接字被禁用,只能执行一次。
需要自己close的东西,一般都是用了虚拟机之外的资源,例如端口,显存,文件等,虚拟机无法通过垃圾回收释放这些资源,只能你显式调用close方法来释放。
你读一个文件,忘记关闭了流,你在操作系统里对这个文件的写,删除等操作就会报错,告诉你这个文件被某个进程占用。
ByteArrayOutputStream 对byte类型数据进行写入的类 相当于一个中间缓冲层,将类写入到文件等其他outputStream。它是对字节进行操作,属于内存操作流
ServerSocket serverSocket = new ServerSocket(9999); Socket socket = serverSocket.accept(); InputStream is = socket.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while((len=is.read(buffer)) != -1){ baos.write(buffer,0,len); System.out.println(new String(buffer,0,len)); } System.out.println(baos.toString()); baos.close(); is.close(); socket.close();
扩容方式:
ByteArrayOutputStream是byte类型的数组进行自动扩容的。当写入长度大于数组原有长度时,就会自动调用grow()方法, buf数组是动态增长的 先扩容为2倍,如果size还是不够 就让数组f的sieze等于minCapacity
Tcp的Server端:(Tomcat也是一个服务端,服务器一般使用的都是别人的)
ServerSocket serverSocket = new ServerSocket(9991);
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
int len;
byte[] bytes = new byte[1024];
while((len = inputStream.read(bytes)) != -1) {
System.out.println(new String(bytes,0,len));
}
inputStream.close();
socket.close();
Tcp的Client端:
Socket socket = new Socket("127.0.0.1",9991);
OutputStream outputStream = socket.getOutputStream();//FileOutputStream("文件名");能将文件发送给对方
outputStream.write("Hello World".getBytes());
outputStream.close();
socket.close();
UDP不需要建立连接:
是需要使用InetAddress的
DatagramSocket也是比较陌生的
DatagramPackage是比较陌生的!
Udp的server端:
DatagramSocket socket = new DatagramSocket(8088);
byte[] bytes = new byte[1024];
DatagramPackage package = new DatagramPackage(bytes,0,bytes.length);
socket.receive(package);
sout(new String(package.getData(),0,package.getLength()));
socket.close();
Udp的Client端:
DatagramSocket socket = new DatagramSocket(2999);
InetAddress inetAddress = InetAddress.getLocalhost();
DatagramPackage package = new DatagramPackage("Hello World".getBytes(),0,"Hello World".length(),"127.0.0.1",8088);
socket.send(package);
socket.close();
Sealed类:
在 Java 中,类继承是一个非常强大的特性,它允许我们创建一个类(子类)来扩展另一个类(父类)。然而,这种自由的继承机制有时也会导致问题,比如不可控的继承层次结构,这可能会使得代码难以维护和理解。
密封类就是为了解决这个问题而设计的。它使用 sealed
关键字来限制哪些类可以继承一个特定的类。这意味着你可以明确指出,只有特定的几个类可以作为某个类的子类。
sealed class Shape permits Circle, Square, Rectangle {}
在这个例子中,Shape
是一个密封类,它只允许 Circle
、Square
和 Rectangle
作为其子类。
子类的声明
当你继承一个密封类时,你必须指定这个子类是 sealed
、non-sealed
还是 final
:
sealed
:表示这个子类也可以有其他密封的或非密封的子类。non-sealed
:表示这个子类不能有子类,但它可以被其他类继承。final
:表示这个类不能被继承。
密封类的主要好处是它们可以帮助我们创建一个有限且可确定的类层次结构。这不仅使得我们的代码更加安全,防止了不受控制的继承,而且也使得我们的代码更加易于理解和维护。
IP:每个连接到Internet上的主机都会分配一个IP地址,此ip是该计算机在互联网上的逻辑地址的唯一标识,计算机之间的访问就是通过IP地址来进行的。
URL:统一资源定位符(英语UniformResourceLocator的缩写)俗称为网址(链接)。网址格式为:协议://域名或IP[:端口]/路径/文件名[参数=值]。结构中,协议://域名或IP是必需的,[]部分是可选的。如果端口与协议默认值不同,则需包含端口,省略则默认80端口。路径有时可省略。
查询域名对应的IP:以百度为例
在cmd中,输入:ping www.baidu.com,回车即可
在一个局域网中,每台机器都有一个主机名,用于主机与主机之间的便于区分,就可以为每台机器设置主机名,以便于以容易记忆的方法来相互访问。比如我们在局域网中可以为根据每台机器的功用来为其命名。
在局域网内,主机名是可以代替ip地址的。
主机名:即计算机名,给一台计算机取的名字(局域网)
在公网环境下,不要去理解主机名,它只是在局域网这个环境下的概念。而我们又可以把公网理解成较大的局域网。这样子想的话,其实域名和主机名就是指同一个东西。在实际场景中,我们可以通过域名解析获得IP地址,而主机名其实就是给计算机取了个名字。
局域网是一种用于连接处于相对狭小地理区域内计算机设备的网络。它是在较小的范围内实现连接和数据共享的计算机网络。局域网的范围可大可小,两台电脑也可以组建一个小的局域网,几百台电脑也可以通过高端设备组建成一个大型局域网。
局域网(Local Area Network)是指一个有限范围内的网络,通常包括一组相互连接的计算机、服务器、网络设备和通信媒介等。这些设备可以通过有线或无线方式进行连接,并通过网络协议进行通信和数据传输。局域网一般都是通过一些硬件设备组建的,需要有路由器、交换机、电脑等终端。
局域网的概念源于满足限定地理范围内的信息共享和资源共享的需求。它的范围通常局限于一个建筑物、办公室、校园或公司等小范围内。局域网的核心目标是提供高效、可靠且安全的通信环境,以满足用户之间进行信息传输和资源共享的需求。
局域网相比于广域网(Wide Area Network)来说,更为局限和专注于较小的范围。由于范围相对较小,局域网通常能够提供更高的传输速度和更低的延迟。这是因为局域网的设备相对靠近,传输的距离较短,可使用高速技术和设备进行通信。
局域网的基本概念之一是共享资源。局域网内的各个设备可以共享不同类型的资源,如打印机、扫描仪、存储设备等。这种资源共享使得用户能够更加方便地访问和利用这些设备,提高了工作效率和便利性。
对于计算机来说,远程通信依赖操作系统提供的Socket接口和互联网,所以调用Socket接口实现两台计算机通信就是计算机之间的远程通信方式。
Socket接口其实就是在计算机中提供了一个通信端口,两台具有Socket接口的计算机可以通过对应端口进行通信。
Socket被作为TCP/IP通信的实现基础,更是整个网络世界通信的基石。
一次简单的TCP通信就是调用Socket接口中的一些API完成的。但是在很多情况下,Socket接口并不是用于网络编程API的最佳选择。因为用Socket接口实现网络编程既复杂又繁琐,所以一些高级语言在此之上对这些API进行了封装,主要是为了简化Socket编程的复杂度,让开发人员无须关心底层的Socket细节,也无须花大量的时间去学习C语言的Socket库。
Java的Socket底层是使用C语言实现的。在Java中,Socket类是对底层操作系统提供的网络套接字接口的封装。Java通过JNI(Java Native Interface)技术调用了C语言编写的底层库来实现Socket功能。这样可以充分利用操作系统提供的网络功能,并且提高了性能和可移植性。
科大讯飞
不管是底层的Socket库,还是高级语言封装的Socket API,或者是网络应用程序框架(例如Netty),他们底层的原理都是一样的,他们只是一种远程通信的实现方案。
端口:可以认为是设备与外界通信交流的出口,所有的数据都是通过该出口与其他计算机或设备相连。
端口是一个假想的连接装置。
套接字(Socket):用于将应用程序与端口连接起来。
Java将套接字抽象化为类,程序设计者只需要创建Socket类对象,即可使用套接字。
IP地址是每个计算机在网络中的唯一标识。
1. IP地址封装:
Java提供了IP地址的封装类InetAddress,主要用于封装IP地址。
InetAddress类常用方法及其说明:
getByName(String host) | InetAddress | 获取host相对应的InetAddress对象 |
getHostAddress() | String | 获取InetAddress对象所含的IP地址 |
getHostName() | String | 获取InetAddress对象的主机名 |
getLocalHost() | InetAddress | 返回本地主机的InetAddress对象 |
isReachable(int timeOut) | boolean | 在其时间内,测试是否可以到达该地址 |
InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
InetAddress inetAddress = InetAddress.getLocalHost();
2. TCP程序设计
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP程序设计是指利用ServerSocket类和Socket类编写的网络通信程序。
服务器端程序创建一个ServerSocket(服务器套接字),调用accept()方法等待客户端来连接。
客户端程序创建一个Socket,请求与服务器建立连接。
服务器接收客户端的连接请求,同时创建一个新的Socket与客户端建立连接。服务器继续等待新的请求。
ServerSocket(int port): 创建绑定到特定端口的服务器套接字。
方法 | 返回值 | 说明 |
accept() | Socket | 等待客户端的连接。若连接,则创建一个套接字 |
isBound() | boolean | 判断ServerSocket的绑定状态 |
getInetAddress() | InetAddress | 返回此服务器套接字的本地地址 |
isClosed() | boolean | 返回服务器套接字的关闭状态 |
close() | void | 关闭服务器套接字 |
bind(SocketAddress endpoint) | void | 将ServerSocket绑定到特定地址(IP地址和端口号) |
getLocalPort() | int | 返回服务器套接字等待的端口号 |
ServerSocket类的常用方法及其说明
Socket(InetAddress address , int port): 创建一个套接字并将其连接到指定IP地址的指定端口。
方法 | 返回值 | 说明 |
bind(SocketAddress bindpoint) | void | 将套接字绑定到本地地址 |
close() | void | 关闭此套接字 |
connect(SocketAddress endpoint) | void | 将此套接字连接到服务器 |
connect(SocketAddress endpoint, int timeout) | void | 将此套接字连接到服务器,并指定一个超时值 |
getInetAddress() | InetAddress | 返回套接字连接的地址 |
getInputStream() | InputStream | 返回此套接字的输入流 |
getOutputStream() | OutputStream | 返回此套接字的输出流 |
Socket类的常用方法及其说明
开发TCP网络程序时,使用服务器端套接字的accept()方法生成的Socket对象使用getOutputStream()方法获得的输出流将指向客户端Socket对象使用getInputStream()方法获得的对应输入流;
...也可以用getInputStream()...
未完待续>>>
3. UDP程序设计
UDP是User Datagram Protocol的缩写,中文名是用户数据报协议,它是网络信息传输的另一种形式。基于UDP的信息传递速度更快,但不提供可靠的保证。