今天来复习一下基础IO,也就是最普通的IO。

  1. 网络IO的基本知识与概念
  2. 普通IO以及BIO服务器
  3. NIO的使用与服务器Hello world
  4. Netty的使用与服务器Hello world

输入流与输出流

Java的输入流和输出流,按照输入输出的单元不同,又可以分为字节流和字符流的。

JDK提供了很多输入流和输出流,比如:

字节流可以按照不同的变量类型进行读写,而字符流则是基于字符编码的。不同的字符编码包含的字节数是不一样的,因此在使用字符流时,一定要注意编码的问题。

读写

字节的输入输出流操作

  1. // 字节输入流操作
  2. InputStream input = new ByteArrayInputStream("abcd".getBytes());
  3. int data = input.read();
  4. while(data != -1){
  5. System.out.println((char)data);
  6. data = input.read();
  7. }
  8. // 字节输出流
  9. ByteArrayOutputStream output = new ByteArrayOutputStream();
  10. output.write("12345".getBytes());
  11. byte[] ob = output.toByteArray();

字符的输入输出流操作

  1. // 字符输入流操作
  2. Reader reader = new CharArrayReader("abcd".toCharArray());
  3. data = reader.read();
  4. while(data != -1){
  5. System.out.println((char)data);
  6. data = reader.read();
  7. }
  8. // 字符输出流
  9. CharArrayWriter writer = new CharArrayWriter();
  10. writer.write("12345".toCharArray());
  11. char[] wc = writer.toCharArray();

关闭流

流打开后,相当于占用了一个文件的资源,需要及时的释放。传统的标准关闭的方式为:

  1. // 字节输入流操作
  2. InputStream input = null;
  3. try {
  4. input = new ByteArrayInputStream("abcd".getBytes());
  5. int data = input.read();
  6. while (data != -1) {
  7. System.out.println((char) data);
  8. // todo
  9. data = input.read();
  10. }
  11. }catch(Exception e){
  12. // todo
  13. }finally {
  14. if(input != null) {
  15. try {
  16. input.close();
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }

在JDK1.7后引入了try-with-resources的语法,可以在跳出try{}的时候直接自动释放:

  1. try(InputStream input1 = new ByteArrayInputStream("abcd".getBytes())){
  2. //
  3. }catch (Exception e){
  4. //
  5. }

IOUtils

直接使用IO的API还是很麻烦的,网上的大多数教程都是各种while循环,操作很麻烦。其实apache common已经提供了一个工具类——IOUtils,可以方便的进行IO操作。

比如 IOUtils.readLines(is, Charset.forName("UTF-8"));可以方便的按照一行一行读取.

BIO阻塞服务器

基于原始的IO和Socket就可以编写一个最基本的BIO服务器。

概要: 这个模型很简单,就是主线程(Acceptor)负责接收连接,然后开启新的线程专门负责连接处理客户端的请求。


  1. import io.netty.util.CharsetUtil;
  2. import java.io.IOException;
  3. import java.io.OutputStream;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. public class PlainOioServer {
  7. public void serve(int port) throws IOException {
  8. // 开启Socket服务器,并监听端口
  9. final ServerSocket socket = new ServerSocket(port);
  10. try{
  11. for(;;){
  12. // 轮训接收监听
  13. final Socket clientSocket = socket.accept();
  14. try {
  15. Thread.sleep(500000);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. System.out.println("accepted connection from "+clientSocket);
  20. // 创建新线程处理请求
  21. new Thread(()->{
  22. OutputStream out;
  23. try{
  24. out = clientSocket.getOutputStream();
  25. out.write("Hi\r\n".getBytes(CharsetUtil.UTF_8));
  26. out.flush();
  27. } catch (IOException e) {
  28. e.printStackTrace();
  29. } finally {
  30. try{
  31. clientSocket.close();
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }).start();
  37. }
  38. } catch (IOException e){
  39. e.printStackTrace();
  40. }
  41. }
  42. public static void main(String[] args) throws IOException {
  43. PlainOioServer server = new PlainOioServer();
  44. server.serve(5555);
  45. }
  46. }

然后执行telnet localhost 5555,就能看到返回结果了。

这种阻塞模式的服务器,原理上很简单,问题也容易就暴露出来:

  1. 服务端与客户端的连接相当于1:1,因此如果连接数上升,服务器的压力会很大
  2. 如果主线程Acceptor阻塞,那么整个服务器将会阻塞,单点问题严重
  3. 线程数膨胀后,整个服务器性能都会下降

改进的方式可以基于线程池或者消息队列,不过也存在一些问题:

  1. 线程池的数量、消息队列后端服务器并发处理数,都是并发数的限制
  2. 仍然存在Acceptor的单点阻塞问题

接下来,将会介绍基于Nio的非阻塞服务器模式,如果忘记什么是IO多路复用,可以回顾前面一篇分享。敬请期待吧...

漫谈Java IO之普通IO流与BIO服务器的更多相关文章

  1. Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

    声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ...

  2. Java nio 笔记:系统IO、缓冲区、流IO、socket通道

    一.Java IO 和 系统 IO 不匹配 在大多数情况下,Java 应用程序并非真的受着 I/O 的束缚.操作系统并非不能快速传送数据,让 Java 有事可做:相反,是 JVM 自身在 I/O 方面 ...

  3. JAVA基础知识之IO——IO流(Stream)的概念

    Java IO 流 Java将不同的设备或载体(键盘.文件.网络.管道等)的输入输出数据统称为"流"(Stream),即JAVA的IO都是基于流的. JAVA传统的所有流类型类都包 ...

  4. 漫谈Java IO之 NIO那些事儿

    前面一篇中已经介绍了基本IO的使用以及最简单的阻塞服务器的例子,本篇就来介绍下NIO的相关内容,前面的分享可以参考目录: 网络IO的基本知识与概念 普通IO以及BIO服务器 NIO的使用与服务器Hel ...

  5. Java的递归、IO流

    .t1 { background-color: #ff8080; width: 1100px; height: 40px } 一.递归 [递归] 1. 在函数自身内部,调用函数本身的方式,称为递归. ...

  6. Java提高篇(二):IO字节流、字符流和处理流

    在我们的Java语言当中,通常会有对文件进行读写,因此我们引入java的IO类来进行文件的读写. 一.字节流 下面是一个字节流的实例: import java.io.*; public class I ...

  7. java基础11(IO流)-字符流

    转换流 由于字节流操作中文不是特别方便,所以java中提供了转换流 编码表:由现实世界的字符和对应的数值组成的一张表 编码:把看得懂的变成看不懂的(String-------byte[]) 解码:把看 ...

  8. Java IO 字节流与字符流 (三)

    概述 IO流用来处理设备之间的数据传输 Java对数据的操作时通过流的方式 Java用于操作流的对象都在IO包中 流按操作的数据分为:字节流和字符流 流按流向不同分为:输入流和输出流 IO流常用基类 ...

  9. Java基础之详谈IO流

    Java基础知识.IO流详细讲解.你所要的IO这里都有

随机推荐

  1. dtls_srtp学习笔记

    注:以下为rfc5764的学习笔记,不保证完全正确. DTLS-SRTP是DTLS的一个扩展,将SRTP加解密与DTLS的key交换和会话管理相结合.从SRTP的角度看,是为其提供一种新的key协商管 ...

  2. [POJ2774]Long Long Message

    vjudge 一句话题意 给两个串,求最长公共子串. sol 把两个串接在一起求后缀数组.其实中间最好用一个没有出现过的字符连接起来. 判断如果\(SA[i]\)和\(SA[i-1]\)不属于同一个串 ...

  3. golang 详解defer

    什么是defer defer用来声明一个延迟函数,把这个函数放入到一个调用链表上, 当外部的包含方法return之前,返回参数到调用方法之前调用,也可以说是运行到最外层方法体的"}" ...

  4. 浅析Unity中的Enlighten与混合光照

    0x00 前言 在Unity的5.6版本之前的5.x中,主要使用了Geomerics公司的Enlighten[1]来提供实时全局照明以及烘焙全局照明,在5.6之后Unity引入了新的Lightmapp ...

  5. java操作impala

    public class App { static String JDBC_DRIVER = "com.cloudera.impala.jdbc4.Driver"; static ...

  6. java设计模式-----11、代理模式

    Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问. 所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代 ...

  7. SQL Server 历史SQL执行记录

    编程执行Sql语句难免忘记保存执行的文本,或是意外设备故障多种情况的发生.对于写的简单的Sql语句丢了就丢了,但对于自己写的复杂的丢失就有些慌了, 有时候很难再次写出来,这时候就需要用一些方法找回Sq ...

  8. Spring MVC简单原理

    Spring MVC原理 针对有Java Web基础.Spring基础和Spring MVC使用经验者. 前言 目前基于Java的web后端,Spring生态应该是比较常见了.虽然现在流行前后端分离, ...

  9. ZFS建池建卷和格式化

    建池 zpool create pool_name path -f  (例如path=/dev/sdb) zfs set primarycache=metadata pool_name (关闭数据缓存 ...

  10. 关于“应用程序无法启动,因为应用程序的并行配置不正确。请参阅应用程序事件日志,或使用命令行sxstrace.exe工具”问题的解决方法

    今天打开QQ管家加速版的时候突然出现了这个错误,百度了下说是系统缺少Microsoft Visual C++ 20XX(运行库),下载这个安装即可解决问题.