从流动方向来看,input代表从读取外部文件内容到java程序里,ouput代表从内存写入数据到文件里
    https://blog.csdn.net/qq_34626097/article/details/84112199
    程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。

    • 节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.
    • 处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

    输入,输出,字节,字符流基础概念 - 图1
    https://www.cnblogs.com/wxgblogs/p/5647415.html
    一般output,input都是相对于当前运行的内存。

    1. //解读以下
    2. PrintWriter pw = new PrintWriter(
    3. new BufferedWriter(
    4. new OutputStreamWriter(
    5. new FileOutputStream("pw2.txt")
    6. , "UTF-8")
    7. )
    8. );
    9. FileOutputStream:输出节点流
    10. OutputStream(OutputStream out, String charsetName): 使用指定的字符集将字符编码为字节
    11. out:字节输出流,可以用来写转换之后的字节到文件中
    12. charsetName:指定的编码表名称,不区分大小写,可以是utf-8/UTF-8,gbk/GBK,...不指定默认使用UTF-8

    BufferedReader和BufferedWriter是带有默认缓冲区的字符输入输出流,其效率相较于没有缓冲区要高:

    1. 1.java.io.BufferedReaderjava.io.BufferedWriter类各拥有8192字符的缓冲区。当BufferedReader在读
    2. 取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。
    3. 2. 从标准输入流System.in中直接读取使用者输入时,使用者每输入一个字符,System.in就读取一个字符。为了能
    4. 一次读取一行使用者的输入,使用了BufferedReader来对使用者输入的字符进行缓冲。readLine()方法会在读取到使用者的换行字符时,再一次将整行字符串传入。
    5. 3. System.in是一个位流,为了转换为字符流,可使用InputStreamReader为其进行字符转换,然后再使用Buffer
    6. edReader为其增加缓冲功能。

    —————————————————————————————————
    综合案例 https://segmentfault.com/a/1190000012316621
    printWrite 不开自动刷, 会等缓冲区数据到一定大小,才会从缓冲区写入

    1. public class MyServer {
    2. private static ExecutorService executorService = Executors.newCachedThreadPool(); //创建一个线程池
    3. //一旦有新的客户端请求,创建这个线程进行处理
    4. private static class HandleMsg implements Runnable{
    5. Socket client; //创建一个客户端
    6. public HandleMsg(Socket client){ //构造传参绑定
    7. this.client = client;
    8. }
    9. @Override
    10. public void run() {
    11. BufferedReader bufferedReader = null; //创建字符缓存输入流
    12. PrintWriter printWriter = null; //创建字符写入流
    13. try {
    14. //1,从client中获得输入流,用于读取client输入内容;
    15. //2,基于以上节点流转换为inputstreamreader处理(转换流,实现字节-字符转换
    16. //3,根据以上处理流创建缓冲流,优化性能
    17. //获取客户端的输入流
    18. bufferedReader = new BufferedReader(new InputStreamReader(client.getInput
    19. Stream()));
    20. //获取客户端的输出流,true是随时刷新,等待写入;
    21. printWriter = new PrintWriter(client.getOutputStream(),true);
    22. String inputLine = null;
    23. long a = System.currentTimeMillis();
    24. while ((inputLine = bufferedReader.readLine())!=null){
    25. printWriter.println(inputLine);
    26. }
    27. long b = System.currentTimeMillis();
    28. System.out.println("此线程花费了:"+(b-a)+"秒!");
    29. } catch (IOException e) {
    30. e.printStackTrace();
    31. }finally {
    32. try {
    33. bufferedReader.close();
    34. printWriter.close();
    35. client.close();
    36. } catch (IOException e) {
    37. e.printStackTrace();
    38. }
    39. }
    40. }
    41. }
    42. public static void main(String[] args) throws IOException { //服务端的主线程是用来循环监听客户端请求
    43. ServerSocket server = new ServerSocket(8686); //创建一个服务端且端口为8686
    44. Socket client = null;
    45. while (true){ //循环监听
    46. client = server.accept(); //服务端监听到一个客户端请求
    47. System.out.println(client.getRemoteSocketAddress()+"地址的客户端连接成功!");
    48. executorService.submit(new HandleMsg(client)); //将该客户端请求通过线程池放入HandlMsg线程中进行处理
    49. }
    50. }
    51. }
    52. public class MyClient {
    53. public static void main(String[] args) throws IOException {
    54. Socket client = null;
    55. PrintWriter printWriter = null;
    56. BufferedReader bufferedReader = null;
    57. try {
    58. client = new Socket();
    59. client.connect(new InetSocketAddress("localhost",8686));
    60. printWriter = new PrintWriter(client.getOutputStream(),true);
    61. printWriter.println("hello");
    62. printWriter.flush();
    63. bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream())); //读取服务器返回的信息并进行输出
    64. System.out.println("来自服务器的信息是:"+bufferedReader.readLine());
    65. } catch (IOException e) {
    66. e.printStackTrace();
    67. }finally {
    68. printWriter.close();
    69. bufferedReader.close();
    70. client.close();
    71. }
    72. }
    73. }

    零拷贝收集:
    mmap,sendfile,DMA gather 知乎 https://zhuanlan.zhihu.com/p/357820303