文档章节

java IO 学习

华夏第一帅神
 华夏第一帅神
发布于 2016/07/18 12:21
字数 2454
阅读 21
收藏 1

1. IO 的分类

  1. 基于字节操作的I/O接口:InputStream和OutputStream
  2. 基于字符操作的I/O接口:Writer和Reader
  3. 基于磁盘操作的I/O接口:File
  4. 基于网络操作的I/O接口:Socket(不在java.io包下)

2. I/O操作

IO 主要是指输入输出流(InputStream/OutStream)

  • InputStream类 InputStream类

  • OutputStream类 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端口号有:

应用协议端口号
DNS53
TFTP69
SNMP161

   UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差。但是正因为UDP协议的控制选项较少,在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或者可以保障可靠性的应用程序,如DNS、TFTP、SNMP等。

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.使用
  1. 连接建立

① 客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。

② 服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。

③ 客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。

连接建立

  1. 连接断开

(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

© 著作权归作者所有

华夏第一帅神

华夏第一帅神

粉丝 9
博文 15
码字总数 16947
作品 0
昌平
高级程序员
私信 提问
泥沙砖瓦浆木匠/java-core-learning-example

感谢赞助的ta们 Java 核心系列教程,关于Java核心技术学习积累的例子,是初学者及核心技术巩固的最佳实践。 包括基础语法,OOP,字符串,集合,IO,反射,线程,网络等。 未完成模块:阿里J...

泥沙砖瓦浆木匠
04/02
0
0
Java IO模型与系统底层IO模型是什么关系??

在学习IO的时候,了解了LInux的5中IO模型,也学习了JAVA的IO模型,但有一个问题十分困扰: 比如,在一次网络IO中,从C段发起IO到S端准备数据,再到S端发送返回数据,C端收到返回数据,从jav...

pinitianjie
2018/03/14
520
2
Java FileInputStream

一、序言 IO操作,才程序中比较普遍,JAVA 中提出了IO/NIO 的概念,也一直在说NIO 比IO快,一直不知道原因,就想memcache 和ehcache 比较优劣一样,这些东西得自己看看如何实现的,才 知道区...

pczhangtl
2014/08/03
0
0
JAVA NIO编程入门(一)

JAVA NIO编程入门(一) 一、前言 笔者之前接触的NIO编程比较少,所以对这一块的基础也比较弱,NIO作为java编程中一个重要的模块,不能很好的掌握它,感觉自己在java方面就掌握的不够,所以,...

木木匠
2018/09/01
0
0
菜鸟的java学习问题,请各位大神提点建议~~

大家好,小弟是新人,很高兴来到这这里,希望能学习到丁点知识,嘿嘿~ 小弟我刚去学java一小段时间,但是总觉得难以掌握,前路渺茫;我是报名我们学校的一个老师自己开设的学习班的;这班里也...

808_小星星
2011/10/29
246
7

没有更多内容

加载失败,请刷新页面

加载更多

利用mybatis generator生成实体类、Mapper接口以及对应的XML文件

项目中通常会遇到数据的持久化,如果是采用mybatis的orm,就会涉及到生成xml的问题,刚好mybatis官网提供了这么个插件MyBatis Generator,效果简直是棒呆。 1. 首先需要在build.gradle文件中...

啊哈关关
今天
2
0
SpringSocial相关的知识点

使用SprigSocial开发第三方登录 核心类 ServiceProvider(AbstractOauth2ServiceProvider):主要负责实现server提供商(例如QQ,微信等共有的东西),默认实现类是AbstractOauth2ServiceProvider...

chendom
今天
2
0
Java并发之AQS详解

一、概述   谈到并发,不得不谈ReentrantLock;而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)!   类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资源...

群星纪元
昨天
2
0
Fabric-sdk-java最新教程

Fabric Java SDK是Fabric区块链官方提供的用于Java应用开发的SDK,全称为Fabric-sdk-java,网上可用资料不多,本文列出了精心整理的针对Fabric Java SDK的最新精选教程。 如果希望快速掌握F...

汇智网教程
昨天
3
0
react 子组件监听props 变化

componentWillReceiveProps //已经被废弃 getDerivedStateFromProps// 推荐使用//如果条件不存在必须要返回null static getDerivedStateFromProps(props, current_stat...

一箭落旄头
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部