Java_IO流、网络编程

IO流的四大类:
字节输入流InputSream
字节输出流OutputStream
字符输入流Reader
字符输出流Writer

flush()刷新流
ByteArrayOutputStream:字节数组输出流的toByteArray()方法
getBytes():字符串转换成字节数组
read什么就write什么:读取字节就写出字节,读取数组就写出数组

管道流:通过线程之间的管道对接
PipedInputStream和PipedOutputStream
connect连接两个线程in.connect(out);
两个线程都要调用join方法,使得线程按顺序执行

print和write的区别?
write是把数据转换成char类型进行操作。
print/println是把数据转换成String类型再打印(print输出的是包装类或者String类的valueOf()方法)。

文件流:File–文件、目录
绝对路径和相对路径?
相对路径默认在src包目录下,绝对路径就是路径的全部描述。

网络编程
toCharArray()–>Arrays.copyOf()方法

控制台:
PrintStream:打印流,有自动换行、自动刷新

字节流
字符流:读取写出时,都要先把字符读写到字节数据,再转成字符。适合用于读取文本时。字符流都有缓存区。
为什么要有缓冲流?效率更快

节点流:
数组
管道
文件

以字节读取效率低–>包装
数据流:方便操作基本数据类型、String类型数据。
可以包裹的流有:管道,文件,字节…

//增强的功能:
writeXxx(Byte,Short,Int,Long,Char,Float,Double,Boolean)writeUTF(String)
readXxx(Byte,Short,Int,Long,Char,Float,Double,Boolean)readUTF(String)

long类型–>byte类型:先无符号右移,再强转进行截取。–>封装这个逻辑
–>DataOutputStream(数据输出流)–>包裹一个字节输出流,一次写出一个具体类型的数据。–>writeXxx(基本数据类型)、writeUTF(String)–>字符集问题:UTF-8中3个字节=1个字符,文件中出现乱码–>把指定类型的数据转换成字节并写出。
–>DataInputStream(字符输入流)–>包裹一个字节输入流–>readXxx(基本数据类型)、readUTF(String)–>把读取到的字节转换成指定类型的数据–>读取和写出的数据顺序要一致。

缓冲流:设置缓冲区数组(8192),减少系统磁盘的读取写出的IO操作,读写效率远高于之前的读写方式。
–>BufferedInputStream,负责给字节输入流提供缓冲功能,也是包裹一个字节输出流。
–>BufferedOutputStream,负责给字节输出流提供缓冲功能。

BufferedReader的readLine方法可以读取一行字符(不包括换行符)。返回的是String。和PrintWriter的println()方法配套使用。

BufferedWriter的newLine方法可以输出一个跨平台的换行符号"\r\n"(只支持windows系统)。

LineNumberReader是BufferedReader的子类,继承了BufferedReader的功能,并且可以统计行号:
调用getLineNumber()方法可以获取当前行号;
调用setLineNumber()方法可以设置当前行号。

转换流:
FileReader是使用默认码表读取文件,如果需要使用指定码表读取,那么可以使用InputStreamReader(字节流,编码表)(“UTF-8”、“GBK”)
FileWriter是使用默认码表写出文件,如果需要使用指定码表写出,那么可以使用OutputStreamWriter(字节流,编码表)

对象流:Java提供了一种对象序列化的机制,可以将对象和字节序列之间进行转换。
序列化、反序列化?
(1)对象输出流:java.io.ObjectOutputStream:
将Java对象转换为字节序列,并输出到内存、文件、网络等地方
(2)对象输入流:java.io.ObjectInputStream:
从某一个地方读取出对象的字节序列,并生成对应的对象。
<1>序列化:程序中,可以用一个字节序列来表示一个对象,该字节序列包含了对象的类型、对象中的数据等。如果这个字节序列写出到文件中,就相当于在文件中持久保存了这个对象的信息。
<2>反序列化:相反的过程,从文件中将这个字节序列读取回来,在内存中重新生成这个对象,对象的类型、对象中的数据等,都和之前的那个对象保持一致(这时候的对象和之前的对象,内存地址可能是不同的)。

Serializable接口只有标识作用,接口中没有内容。
继承序列化接口的有:
序列号serialVersionUID:
private static final long serialVersionUID = 1L;//默认1L
transient:隐藏属性,使得读取信息时不会读取该属性
增强功能:readObject和writeObject

包装流都有增强方法。

io=new 缓冲流/对象流(new 转换流(new 字节流(new File(“文件位置”))));

随机访问流:继承的是Object类,只能对文件进行读写。

//随机访问流的方法:
read();
write();
seek();//seek从0开始
seek(long pos);//long类型,pos指位置

替换文件内容:其他流通过删除重写,随机流通过定位后删除。
插入:插入位置后面的内容先保存在数组中,插入后把保存的数据加上。

IO操作的步骤:
1.根据需求选择流:
1)字节还是字符,
2)控制台-InputStream、PrintStream(OutputStream的子类),ByteArray…、CharArray…-数组,Piped…线程-管道,File…-文件、目录
3)Buffered…-效率高,Data…-处理不同类型的数据,字节和字符的转换-转换流,序列化、反序列化-对象流,随机访问流-。

2.读取字节流:3个read方法?

read();//一次读取一个字节,返回的是本次读取到的字节;
read(byte[] b);//一次读取多个字节,存放入一个字节数组中;
read(byte[] b,int off,int len);//读取多个字节,并且指定放入字节数组的位置,以及存放字节的数量。

3.写出字节流:3个write方法?

write();//一次写出一个字节;
write(byte[] b);//把字节数组的值全部写出;
write(byte[] b,int off,int len);
//指定要写出的字节数组的开始位置以及要写出的字节数量。

4.在finally代码块中,关闭流。

读字节数组的遍历的模板?

//创建流
byte[] b=new byte[n];//长度是n
int len;//定义一个下标或者长度
while((len=in.read(b)) != -1){//循环遍历byte数组
	out.write(len);//读取数组的每一个字节
	out.write(b,0,len);//读取数组的一段字节
}
//打印
//关闭流

BIO和NIO的问题以及优化方式?
BIO中的B是Blocking的意思,所以这是一种阻塞的IO模型。同步阻塞模型,用户线程进行IO操作时,如果数据没有准备好就会被阻塞。
BIO通信方式的特点:
(1)一个线程负责连接,多线程则为每一个接入开启一个线程。
(2)一个请求一个应答。
(3)请求之后应答之前客户端会一直等待(阻塞)。
BIO通信方式在单线程服务器下一次只能处理一个请求,在处理完毕之前一直阻塞。因此不适用于高并发的情况。不过可以使用多线程稍微改进。BIO模式因为进程的阻塞挂起,不会消耗过多的CPU资源,而且开发难度低,比较适合并发量小的网络应用开发。同时很容易发现因为请求IO会阻塞进程,所以不时候并发量大的应用。如果为每一个请求分配一个线程,系统开销就会过大。

NIO表示New I/O(Non-Blocking IO),是非阻塞的IO模型。
早期的Java只提供了一个File类来访问文件系统,但File类的功能比较有限,所提供的方法性能也不高。而且,大多数方法在出错时仅返回失败,并不会提供异常信息。
NIO为了弥补这种不足,引入了Path接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。Path可以看成是File类的升级版本,实际引用的资源也可以不存在。同时NIO在java.nio.file包下还提供了Files、Paths工具类,Files包含了大量静态的工具方法来操作文件;Paths则包含了两个返回Path的静态工厂方法。

BIO,NIO,AIO 有什么区别?
(1)BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
(2)NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
(3)AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

(1)BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。
(2)NIO (New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的 Socket 和 ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发
(3)AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。

Properties类表示一组持久的属性。 Properties可以保存到流中或从流中加载。 属性列表中的每个键及其对应的值都是一个字符串。
.properties文件:配置文件,key值和value值组成。默认是IOS字符集,显示中文要设置。

网络编程
软件结构:Client/Server(C/S结构)表示客户端/服务器的软件结构;Browser/Server(B/S结构)表示浏览器/服务器的软件结构。

TCP/IP协议栈,传输控制协议/因特网互联协议,采用4层结构,分别是应用层、传输层、网络层、链路层。
TCP,传输控制协议 (Transmission Control Protocol),TCP协议是面向连接的通信协议,传输数据之前,在发送端和接收端建立连接,然后再传输数
据,它提供了两台计算机之间可靠的、无差错的数据传输。
UDP,用户数据报协议,是无连接通信协议,在数据传输时,数据的发送端和接收端不建立连接,也不能保证对方能接收成功。

1.结合IO流
客户端:Socket -->new Socket(“127.0.0.1”, 9999)
服务器:ServerSocket -->new ServerSocket(9999).accept()

常常传输的是图片–>使用字节流–>字节流慢–>转换成字符流–>再包装成缓冲流
–>BufferedReader-readLine+PrintWrite-println
–>readLine读取的是下一行的字符串;println写出一行数据。

2.结合线程:
(不确定次数–>使用while循环)
不同的客户端的操作不同,通过线程实现–>把socket传入线程的构造器,在线程中实现传输操作–>每个线程对应一个客户端,多线程实现群聊

TCP三次握手
(1)第一次握手,客户端向服务器端发出连接请求,等待服务器确认;
(2)第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求;
(3)第三次握手,客户端再次向服务器端发送确认信息,确认连接。

使用Socket和ServerSocket进行的编程,也称为套接字编程。
(1)java.net.Socket类表示客户端:

//创建Socket对象,连接服务器,服务器地址是127.0.0.1,端口号是8888
Socket client = new Socket("127.0.0.1", 8888);
//使用out,可以给对方服务器写数据
OutputStream out = client.getOutputStream();
//使用in,可以读取对方服务器写回来的数据
InputStream in = client.getInputStream();

(2)java.net.ServerSocket类表示服务端:

ServerSocket server = new ServerSocket(8888);
//accept方法会导致线程阻塞到这,等待客户端的连接
Socket socket = server.accept();
//使用out,可以给对方客户端写数据
OutputStream out = socket.getOutputStream();
//使用in,可以读取对方客户端发送过来的数据
InputStream in = socket.getInputStream();

UDP的2个类:java.net.DatagramSocket负责接收和发送数据;
java.net.DatagramPacket负责封装要发送的数据和接收到的数据。

URI和URL是什么?
URI(uniform resource identifier),统一资源标识符,用来唯一的标识一个资源。
URL(uniform resource locator),统一资源定位符,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何定位这个资源。

TCP网络编程的3个问题?
1.现在服务端启动后,只能接收一个客户端的一次连接,怎样能接收一个客户端的多次连接?
2.怎么能让服务器端同时接收多个不同客户端的连接?
3.怎么让客户端不断的读取控制台的数据,然后写给服务器,而不是读取一次就结束?

经典案例:聊天室(IO+线程+集合)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值