《Java编程思想》Java I/O系统章节阅读笔记

简介:

今天正好要写个小程序需要用到io操作,突然想起来java有个nio一直没用过,就找了点资料研究了一下,顺便做点笔记,以便日后查阅。

-------------------------------------------------------------------------------------------------------------------------------------------

编程语言的I/O类库中常使用流的概念,但它屏蔽了实际的I/O设备中处理数据的细节。在Java中很少使用单一的类来创建流对象,而是通过叠合多个对象来提供所期望的功能(用到了装饰器模式)。InputStream和OutputStream就是用来输入和输出的。在Java1.1中,Reader和Writer利用适配器转换了它们来实现国际化,因为老的I/O流继承结果仅支持8位字节流,不能很好的处理16位的Unicode字符。

文件操作的类:FileInputReader,FileOutputReader,RandomAccessFile。其中RandomAccessFile是一个自我独立的类,虽然可读可写,但都是自己内部实现,并没继承输入输出流的层次结构。在JDK1.4中,其大部分功能已经由nio内存映射文件所取代。

基本的文件输出:FileWriter对象可以向文件写入数据,实际上,我们通常会用BufferedWriter将其包装起来用以缓冲输出,为了提供格式化机制,它又被装饰成PrintWriter。例如:new PrintWriter(new BufferedWriter(new FileWriter(file))),在J2SE 5中甲了一个辅助构造器,可以简写成new PrintWriter(file)。

管道流:PipedInputStream,PipedOutputStream,PipedReader及PipedWriter,它们的价值在多线程中才能体现,因为管道流用于任务之间的通信。

-------------------------------------------------------------------------------------------------------------------------------------------

new I/O:目的是为了提高速度,在新版本的JDK中,旧的I/O也使用nio重新实现,有性能提升。速度的提高来自于所使用的结构更接近于操作系统的执行I/O方式——通道和缓冲器。

流使用getChannel()方法会产生一个FileChannel。通道是一种相当基础的东西:可以向它传送用于读写的ByteBuffer,并且可以锁定文件的某些区域用于独占式访问(后面有提到)。

 
  1. import java.nio.*;  
  2. import java.nio.channels.*;  
  3. import java.io.*;  
  4.  
  5. public class GetChannel {  
  6.   private static final int BSIZE = 1024;  
  7.   public static void main(String[] args) throws Exception {  
  8.     // Write a file:  
  9.     FileChannel fc =  
  10.       new FileOutputStream("data.txt").getChannel();  
  11.     fc.write(ByteBuffer.wrap("Some text ".getBytes()));  
  12.     fc.close();  
  13.     // Add to the end of the file:  
  14.     fc = new RandomAccessFile("data.txt""rw").getChannel();  
  15.     fc.position(fc.size()); // Move to the end  
  16.     fc.write(ByteBuffer.wrap("Some more".getBytes()));  
  17.     fc.close();  
  18.     // Read the file:  
  19.     fc = new FileInputStream("data.txt").getChannel();  
  20.     ByteBuffer buff = ByteBuffer.allocate(BSIZE);  
  21.     fc.read(buff);  
  22.     buff.flip();  
  23.     while(buff.hasRemaining())  
  24.       System.out.print((char)buff.get());  
  25.   }  
  26. }  
  27.  

将字节存放于ByteBuffer有2种方法:一是用put方法直接填充一个或多个字节,或基本数据类型;另一种是用warp方法将已存在的字节数组包装到ByteBuffer中。对于只读访问,我们必须显示的使用静态的allocate方法分配ByteBuffer。nio的目标就是快速移动大量数据,因此ByteBuffer的大小就很重要——需要在实际运行的程序中测试来找到最佳值。要达到更高的速度也有可能,方法就是使用allocateDirect()而不是allocate(),以产生一个与操作系统有更高耦合性的“直接”缓冲器,但效果需要实际测试一下。

 
  1. import java.nio.*;  
  2. import java.nio.channels.*;  
  3. import java.io.*;  
  4.  
  5. public class ChannelCopy {  
  6.   private static final int BSIZE = 1024;  
  7.   public static void main(String[] args) throws Exception {  
  8.     if(args.length != 2) {  
  9.       System.out.println("arguments: sourcefile destfile");  
  10.       System.exit(1);  
  11.     }  
  12.     FileChannel in = new FileInputStream(args[0]).getChannel();  
  13.     FileChannel out = new FileOutputStream(args[1]).getChannel();  
  14.     //有一种特殊的办法,将2个通道直接相连   
  15.     // in = transferTo(0, in.size(), out); 或者 out = transferFrom(in, 0, in.size());  
  16.     ByteBuffer buffer = ByteBuffer.allocate(BSIZE);  
  17.     while(in.read(buffer) != -1) {  
  18.       buffer.flip(); // Prepare for writing  
  19.       out.write(buffer);  
  20.       buffer.clear();  // Prepare for reading  
  21.     }  
  22.   }  
  23. }  

BufferWriter转换成char型来操作,很不方便,我们利用CharBuffer的toString()方法来转换成String型就方便多了。

 
  1. import java.nio.*;  
  2. import java.nio.channels.*;  
  3. import java.nio.charset.*;  
  4. import java.io.*;  
  5.  
  6. public class BufferToText {  
  7.   private static final int BSIZE = 1024;  
  8.   public static void main(String[] args) throws Exception {  
  9.     FileChannel fc =  
  10.       new FileOutputStream("data2.txt").getChannel();  
  11.     fc.write(ByteBuffer.wrap("Some text".getBytes()));  
  12.     fc.close();  
  13.     fc = new FileInputStream("data2.txt").getChannel();  
  14.     ByteBuffer buff = ByteBuffer.allocate(BSIZE);  
  15.     fc.read(buff);  
  16.     buff.flip();  
  17.     // Doesn't work:  
  18.     System.out.println(buff.asCharBuffer());  
  19.     // Decode using this system's default Charset:  
  20.     buff.rewind();  
  21.     String encoding = System.getProperty("file.encoding");  
  22.     System.out.println("Decoded using " + encoding + ": " 
  23.       + Charset.forName(encoding).decode(buff));  
  24.     // Or, we could encode with something that will print:  
  25.     fc = new FileOutputStream("data2.txt").getChannel();  
  26.     fc.write(ByteBuffer.wrap(  
  27.       "Some text".getBytes("UTF-16BE")));  
  28.     fc.close();  
  29.     // Now try reading again:  
  30.     fc = new FileInputStream("data2.txt").getChannel();  
  31.     buff.clear();  
  32.     fc.read(buff);  
  33.     buff.flip();  
  34.     System.out.println(buff.asCharBuffer());  
  35.     // Use a CharBuffer to write through:  
  36.     fc = new FileOutputStream("data2.txt").getChannel();  
  37.     buff = ByteBuffer.allocate(24); // More than needed  
  38.     buff.asCharBuffer().put("Some text");  
  39.     fc.write(buff);  
  40.     fc.close();  
  41.     // Read and display:  
  42.     fc = new FileInputStream("data2.txt").getChannel();  
  43.     buff.clear();  
  44.     fc.read(buff);  
  45.     buff.flip();  
  46.     System.out.println(buff.asCharBuffer());  
  47.   }  
  48. }  
  49.  

-------------------------------------------------------------------------------------------------------------------------------------------

内存映射文件:它允许我们创建和修改那些因为太大而不能放入内存的文件。

 
  1. import java.nio.*;  
  2. import java.nio.channels.*;  
  3. import java.io.*;  
  4. import static net.mindview.util.Print.*;  
  5.  
  6. public class LargeMappedFiles {  
  7.   static int length = 0x8FFFFFF// 128 MB  
  8.   public static void main(String[] args) throws Exception {  
  9.     MappedByteBuffer out =  
  10.       new RandomAccessFile("test.dat""rw").getChannel()  
  11.       .map(FileChannel.MapMode.READ_WRITE, 0, length);  
  12.     for(int i = 0; i < length; i++)  
  13.       out.put((byte)'x');  
  14.     print("Finished writing");  
  15.     for(int i = length/2; i < length/2 + 6; i++)  
  16.       printnb((char)out.get(i));  
  17.   }  
  18. }  
  19.  

文件加锁:通过对FileChannel调用tryLock()和lock(),就可以获得整个文件的FileLock。启动tryLock()是非阻塞式的,它设法获取锁,但如果不能获得,将直接放方法调用返回。lock()是阻塞式的,它要阻塞线程直到获得锁,或者调用lock()的线程中断,或者调用lock()的通道关闭。

 
  1. import java.nio.channels.*;  
  2. import java.util.concurrent.*;  
  3. import java.io.*;  
  4.  
  5. public class FileLocking {  
  6.   public static void main(String[] args) throws Exception {  
  7.     FileOutputStream fos= new FileOutputStream("file.txt");  
  8.     FileLock fl = fos.getChannel().tryLock();  
  9.     if(fl != null) {  
  10.       System.out.println("Locked File");  
  11.       TimeUnit.MILLISECONDS.sleep(100);  
  12.       fl.release();  
  13.       System.out.println("Released Lock");  
  14.     }  
  15.     fos.close();  
  16.   }  
  17. }  
  18.  

对映射文件的部分加锁:

 
  1. import java.nio.*;  
  2. import java.nio.channels.*;  
  3. import java.io.*;  
  4.  
  5. public class LockingMappedFiles {  
  6.   static final int LENGTH = 0x8FFFFFF// 128 MB  
  7.   static FileChannel fc;  
  8.   public static void main(String[] args) throws Exception {  
  9.     fc =  
  10.       new RandomAccessFile("test.dat""rw").getChannel();  
  11.     MappedByteBuffer out =  
  12.       fc.map(FileChannel.MapMode.READ_WRITE, 0, LENGTH);  
  13.     for(int i = 0; i < LENGTH; i++)  
  14.       out.put((byte)'x');  
  15.     new LockAndModify(out, 00 + LENGTH/3);  
  16.     new LockAndModify(out, LENGTH/2, LENGTH/2 + LENGTH/4);  
  17.   }  
  18.   private static class LockAndModify extends Thread {  
  19.     private ByteBuffer buff;  
  20.     private int start, end;  
  21.     LockAndModify(ByteBuffer mbb, int start, int end) {  
  22.       this.start = start;  
  23.       this.end = end;  
  24.       mbb.limit(end);  
  25.       mbb.position(start);  
  26.       buff = mbb.slice();  
  27.       start();  
  28.     }  
  29.     public void run() {  
  30.       try {  
  31.         // Exclusive lock with no overlap:  
  32.         FileLock fl = fc.lock(start, end, false);  
  33.         System.out.println("Locked: "+ start +" to "+ end);  
  34.         // Perform modification:  
  35.         while(buff.position() < buff.limit() - 1)  
  36.           buff.put((byte)(buff.get() + 1));  
  37.         fl.release();  
  38.         System.out.println("Released: "+start+" to "+ end);  
  39.       } catch(IOException e) {  
  40.         throw new RuntimeException(e);  
  41.       }  
  42.     }  
  43.   }  
  44. }  

 


本文转自passover 51CTO博客,原文链接:http://blog.51cto.com/passover/425926,如需转载请自行联系原作者

相关实践学习
【AI破次元壁合照】少年白马醉春风,函数计算一键部署AI绘画平台
本次实验基于阿里云函数计算产品能力开发AI绘画平台,可让您实现“破次元壁”与角色合照,为角色换背景效果,用AI绘图技术绘出属于自己的少年江湖。
从 0 入门函数计算
在函数计算的架构中,开发者只需要编写业务代码,并监控业务运行情况就可以了。这将开发者从繁重的运维工作中解放出来,将精力投入到更有意义的开发任务上。
相关文章
|
3月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
373 8
|
3月前
|
移动开发 监控 小程序
java家政平台源码,家政上门清洁系统源码,数据多端互通,可直接搭建使用
一款基于Java+SpringBoot+Vue+UniApp开发的家政上门系统,支持小程序、APP、H5、公众号多端互通。涵盖用户端、技工端与管理后台,支持多城市、服务分类、在线预约、微信支付、抢单派单、技能认证、钱包提现等功能,源码开源,可直接部署使用。
305 24
|
3月前
|
安全 前端开发 Java
使用Java编写UDP协议的简易群聊系统
通过这个基础框架,你可以进一步增加更多的功能,例如用户认证、消息格式化、更复杂的客户端界面等,来丰富你的群聊系统。
196 11
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
Java与生成式AI:构建内容生成与创意辅助系统
生成式AI正在重塑内容创作、软件开发和创意设计的方式。本文深入探讨如何在Java生态中构建支持文本、图像、代码等多种生成任务的创意辅助系统。我们将完整展示集成大型生成模型(如GPT、Stable Diffusion)、处理生成任务队列、优化生成结果以及构建企业级生成式AI应用的全流程,为Java开发者提供构建下一代创意辅助系统的完整技术方案。
262 10
|
3月前
|
人工智能 监控 Java
Java与AI智能体:构建自主决策与工具调用的智能系统
随着AI智能体技术的快速发展,构建能够自主理解任务、制定计划并执行复杂操作的智能系统已成为新的技术前沿。本文深入探讨如何在Java生态中构建具备工具调用、记忆管理和自主决策能力的AI智能体系统。我们将完整展示从智能体架构设计、工具生态系统、记忆机制到多智能体协作的全流程,为Java开发者提供构建下一代自主智能系统的完整技术方案。
581 4
|
3月前
|
机器学习/深度学习 分布式计算 Java
Java与图神经网络:构建企业级知识图谱与智能推理系统
图神经网络(GNN)作为处理非欧几里得数据的前沿技术,正成为企业知识管理和智能推理的核心引擎。本文深入探讨如何在Java生态中构建基于GNN的知识图谱系统,涵盖从图数据建模、GNN模型集成、分布式图计算到实时推理的全流程。通过具体的代码实现和架构设计,展示如何将先进的图神经网络技术融入传统Java企业应用,为构建下一代智能决策系统提供完整解决方案。
423 0
|
4月前
|
JavaScript Java 大数据
基于JavaWeb的销售管理系统设计系统
本系统基于Java、MySQL、Spring Boot与Vue.js技术,构建高效、可扩展的销售管理平台,实现客户、订单、数据可视化等全流程自动化管理,提升企业运营效率与决策能力。
|
4月前
|
安全 Cloud Native Java
Java 模块化系统(JPMS)技术详解与实践指南
本文档全面介绍 Java 平台模块系统(JPMS)的核心概念、架构设计和实践应用。作为 Java 9 引入的最重要特性之一,JPMS 为 Java 应用程序提供了强大的模块化支持,解决了长期存在的 JAR 地狱问题,并改善了应用的安全性和可维护性。本文将深入探讨模块声明、模块路径、访问控制、服务绑定等核心机制,帮助开发者构建更加健壮和可维护的 Java 应用。
353 0
|
4月前
|
NoSQL Java 关系型数据库
超全 Java 学习路线,帮你系统掌握编程的超详细 Java 学习路线
本文为超全Java学习路线,涵盖基础语法、面向对象编程、数据结构与算法、多线程、JVM原理、主流框架(如Spring Boot)、数据库(MySQL、Redis)及项目实战等内容,助力从零基础到企业级开发高手的进阶之路。
394 1
|
5月前
|
Java 数据库 前端开发
分享44个java系统,总有一款适合您
分享44个微信小程序,总有一款适合您
87 0