java IO 学习
2016-07-18 00:00
417 查看
1. IO 的分类
基于字节操作的I/O接口:InputStream和OutputStream基于字符操作的I/O接口:Writer和Reader
基于磁盘操作的I/O接口:File
基于网络操作的I/O接口:Socket(不在java.io包下)
2. I/O操作
IO 主要是指输入输出流(InputStream/OutStream)InputStream类
OutputStream类
3. IO文件复制
InputStream 和 OutStream
public static void main(String[] args) { try { // 1. 获取文件流 InputStream is = new FileInputStream(new File("a.txt")); // 2. 转化成缓冲输入流 BufferedInputStream bis = new BufferedInputStream(is); // 3. 定义文件输出流 FileOutputStream fos = new FileOutputStream("b.txt"); // 4. 定义每次读取的大小 byte []buffer = new byte[1024]; // 5. 定义当前读取的字节数 int readCount = 0; // 6. 定义当前读取的长度 int readLen = 0; // 7. 如果没到文件尾,则一直读 while((readLen = bis.read(buffer)) != -1){ // 8. 通过输出流将每次输出的数据写入b文件中 fos.write(buffer,readCount,readLen-1); readCount+=readLen; } // 9. 关闭流 fos.flush(); is.close(); bis.close(); fos.close(); } catch (Exception e) { e.printStackTrace(); } }
Reader 和 Writer (按字节读取)
public static void main(String[] args) { try { BufferedReader br = new BufferedReader(new FileReader(new File("a.txt"))); BufferedWriter bw = new BufferedWriter(new FileWriter(new File("c.txt"))); char[] buffer = new char[1024]; int readLen = 0; int readCount = 0; while((readLen = br.read(buffer)) != -1){ bw.write(buffer, readCount, readLen-1); readCount += readLen; } br.close(); bw.close(); } catch (Exception e) { e.printStackTrace(); } }
Reader 和 Writer (按行读取)
public static void main(String[] args) { try { BufferedReader br = new BufferedReader(new FileReader(new File("a.txt"))); BufferedWriter bw = new BufferedWriter(new FileWriter(new File("d.txt"))); String temp = null; while((temp = br.readLine()) != null){ bw.write(temp); } br.close(); bw.close(); } catch (Exception e) { e.printStackTrace(); } }
数据流
public static void main(String[] args) { try { FileInputStream fis = new FileInputStream(new File("data.txt")); FileOutputStream fos = new FileOutputStream(new File("data.txt")); DataInputStream dis = new DataInputStream(fis); DataOutputStream dos = new DataOutputStream(fos); // 注意这里 读入的顺序 读取的顺序也一样 dos.writeUTF("faxingege"); dos.writeDouble(1.2222222); dos.writeBoolean(false); dos.flush(); System.out.println(dis.readUTF()); System.out.println(dis.readDouble()); System.out.println(dis.readBoolean()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
对象流
public static void main(String[] args) { HashMap<String, String> staff = new HashMap<String, String>(); staff.put("haha", "hello"); try { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("data.txt"))); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("data.txt"))); oos.writeObject(staff); oos.flush(); HashMap<String, String> staff1 = (HashMap<String, String>) ois.readObject(); System.out.println(staff1.get("haha")); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
管道流
public static void main(String[] args) { try { // 定义管道流 PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(); // 链接管道流 pis.connect(pos); // 定义输出线程 Thread inputThread = new Thread(new Runnable() { @Override public void run() { try { pos.write(("W:当前写入数据").getBytes()); Thread.sleep(5000); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }); inputThread.start(); // 定义输入线程 Thread outputThread = new Thread(new Runnable() { @Override public void run() { byte[] buffer = new byte[1024]; int readLen = 0; try { while (true) { readLen = pis.read(buffer); String s = new String(buffer, 0, readLen); System.out.println(s); } } catch (IOException e) { e.printStackTrace(); } } }); outputThread.start(); } catch (IOException e) { e.printStackTrace(); } }
4. Socket
UDP协议
1. 协议UDP是OSI参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成,提供面向事务的简单不可靠信息传送服务。UDP 协议基本上是IP协议与上层协议的接口。UDP协议适用端口分别运行在同一台设备上的多个应用程序。
UDP提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,UDP传输的可靠性由应用层负责。
常用的UDP端口号有:
应用协议 | 端口号 |
---|---|
DNS | 53 |
TFTP | 69 |
SNMP | 161 |
2. 使用
在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的ICQ和QQ就是使用的UDP协议。
3. 实现
Server端
public static void main(String[] args) { try { // 新建一个UDP的socket DatagramSocket udpSocket = new DatagramSocket(5555, InetAddress.getLocalHost()); // 定义个接受信息的报文类 byte[] buffer = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length); // 轮询IP端口 ,如果获取信息,则输出 while(true){ udpSocket.receive(datagramPacket); System.out.println(new String(datagramPacket.getData(), 0 , datagramPacket.getLength())); datagramPacket.setData(new String("服务器已经收到请求").getBytes()); udpSocket.send(datagramPacket); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
Client端
public static void main(String[] args) { try { // 新建一个UDP的socket DatagramSocket udpSocket = new DatagramSocket(5556, InetAddress.getLocalHost()); byte[] buffer = new byte[1024]; DatagramPacket datagramPacket = null; while(true){ System.out.println("请输入发往服务器端的话:"); Scanner scan = new Scanner(System.in); String ask = scan.nextLine(); System.out.println("您输入了:" + ask); datagramPacket = new DatagramPacket(ask.getBytes(),ask.getBytes().length,InetAddress.getLocalHost(), 5555); udpSocket.send(datagramPacket); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
TCP协议
1. 协议TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内另一个重要的传输协议。在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。
当应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,TCP则把数据流分割成适当长度的报文段,最大传输段大小(MSS)通常受该计算机连接的网络的数据链路层的最大传送单元(MTU)限制。之后TCP把数据包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。
TCP为了保证报文传输的可靠,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的字节发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据(假设丢失了)将会被重传。
在数据正确性与合法性上,TCP用一个校验和函数来检验数据是否有错误,在发送和接收时都要计算校验和;同时可以使用md5认证对数据进行加密。
在保证可靠性上,采用超时重传和捎带确认机制。
在流量控制上,采用滑动窗口协议,协议中规定,对于窗口内未经确认的分组需要重传。
在拥塞控制上,采用广受好评的TCP拥塞控制算法(也称AIMD算法)。
该算法主要包括三个主要部分:
1)加性增、乘性减;
2)慢启动;
3)对超时事件做出反应。
2.使用
连接建立
① 客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
② 服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
③ 客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
连接断开
(1) 某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。
(2) 接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。
注意:FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为,FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。
(3) 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。
(4) 接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。
既然每个方向都需要一个FIN和一个ACK,因此通常需要4个分节。
注意:
(1) “通常”是指,某些情况下,步骤1的FIN随数据一起发送,另外,步骤2和步骤3发送的分节都出自执行被动关闭那一端,有可能被合并成一个分节。
(2) 在步骤2与步骤3之间,从执行被动关闭一端到执行主动关闭一端流动数据是可能的,这称为“半关闭”(half-close)。
(3) 当一个Unix进程无论自愿地(调用exit或从main函数返回)还是非自愿地(收到一个终止本进程的信号)终止时,所有打开的描述符都被关闭,这也导致仍然打开的任何TCP连接上也发出一个FIN。
3.实现
Server端
public static void main(String[] args) { try { // 在5241端口上建立ServerSocket ServerSocket serverSocket = new ServerSocket(5241); // 轮询接受网路消息 while(true){ System.out.println("holding on line..."); // 接受TCP请求 Socket socket = serverSocket.accept(); InputStream is = socket.getInputStream(); byte []buffer = new byte[1024]; int readLen = 0; int readCount = 0; String result = ""; while((readLen = is.read(buffer)) != -1){ result += new String(buffer, readCount, readLen); readCount += readLen-1; } System.out.println("服务器收到消息: " + result); } } catch (IOException e) { e.printStackTrace(); } }
client端
public static void main(String[] args) { try { while(true){ Socket socket = new Socket(InetAddress.getLocalHost(),5241); OutputStream os = socket.getOutputStream(); System.out.println("请输入你想对服务器说的话:"); Scanner scan = new Scanner(System.in); String requestStr = scan.nextLine(); os.write(requestStr.getBytes()); os.close(); } } catch (IOException e) { e.printStackTrace(); } }
资料部分来源百度百科
代码地址: http://git.oschina.net/ifaxin/IO_Study
相关文章推荐
- java匿名内部类
- java多线程目录
- eclipse svn 同步和提交忽略制定某些文件类型和文件夹
- Spring MVC通过CROS协议解决跨域问题
- Spring propertyConfigurer类
- SpringMVC把从Jsp页面传递过来的日期字符串转换成Java日期类型方法
- 【Java】发送激活邮件
- Java technical documents
- Java security
- 根据表结构自动生成JavaBean,史上最强最专业的表结构转JavaBean的工具(第3版)
- Struts2中action的方法被执行两次
- JAVA:WordCount
- Spring_Jdbc连接管理
- 关于spring的事务操作方法
- 遍历list的几种方式
- 为什么切面要切业务层?
- java内存模型
- spring为什么实现接口?
- Java加密问题的的_改进
- Java加密问题的的_实现