在上篇中,已经写下了IO流概念以及对File类操作,如果想查阅上篇的内容,请点击这里: http://www.cnblogs.com/idayln/archive/2013/05/27/3102810.html . 此文是它的姊妹篇!本文以Demo为主,不会涉及太多概念!!!
- 输入流: InputStream/Reader 拥有一系列read方法
- InputStream 是字节输入流的超类
- Reader是字符输入流的超类
- 输出流: OutputStream/Writer 拥有一系列write方法
- OutputStream 字节输出类的超类
- Writer 字符输出流的超类
输出流代码:
1 static void demo0() throws Exception { 2 try (OutputStream outputStream = new FileOutputStream("demo1.txt")) { 3 outputStream.write("First 'demo' for how to use 'OutputStream' !" 4 .getBytes()); 5 } 6 System.out.println("Over"); 7 }
看到这段代码,是不是感觉有点奇怪?别紧张.
- 上段代码是Java 7中异常新特性:try-with-resources: 它可以自行进行资源管理,例如上例就不需要手动close;需要注意的是:try(/* 此处可以是代码块 */),这种语法节省的好多代码。
- OutputStream是个抽象类,它必须通过子类来进行实例化。
- OutputStream主要分为二种功能
- 字入数据的write系列方法
- 参数为byte: 单一字节
- 参数为byte数组
- 参数为byte数组和数组中的起始位置与长度
- 流的控制
- 关闭:close
- 刷新保存:flush: 其实不必手动flush。第一:当内部缓冲期满过,它会自动自动执行flush;第二:当invoke close方法时,会自动执行flush。
- 字入数据的write系列方法
输入流代码:
1 static void demo1() throws IOException{ 2 InputStream inputStream =null; 3 try { 4 inputStream = new FileInputStream("demo0.txt"); 5 byte[] bb = new byte[1024]; //缓冲区 6 int temp; 7 while((temp=inputStream.read(bb))!=-1){ 8 System.out.println(new String(bb, 0, temp)); 9 } 10 } catch (FileNotFoundException e) { 11 // TODO Auto-generated catch block 12 e.printStackTrace(); 13 }finally{ 14 if(inputStream!=null){ 15 inputStream.close(); 16 } 17 } 18 }
InputStream:
- 上段采用Java 6的语法,是不是明显感觉到代码量增多:从7行增加到18行。
- 与OutputStream一样是个抽象类。因为它们都是比较早设计的类,因此并没有采用流行的面向接口编程思想。
- 与OutputStream一样也主要有二个功能:read系列方法,但是它的流的控制没有flush而是添加了skip,mark这二个方法,平时用得少,感兴趣的同学可以自行去查API。
Reader,Writer与InputStream,OutputStream基本功能相,这里就不在解释。深入理解了InputStream与OutputStream之后,学其它就很快;对于不同的处理流,查API就行!!
附上IO流体系结构表:
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
抽象基类 | InputStream | OutputSteam | Reader | Writer |
文件 | FileInputStream | FileOutputSteam | FileReader | FileWriter |
数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
缓冲 | BufferedInputStream | BufferedOutputStream | BufferdReader |
BufferWriter |
对象 | ObjectInputStream | ObjectOutputStream | ||
转换 | InputStreamReader | OutputStreamWriter | ||
打印 | PrintStream | PrintWriter | ||
字符串 | StringReader | StringWriter | ||
管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
这多类,该如何记忆,理解呢? 我是这么理解的。
首先把它们大致划分为:节点流与处理流。节点流就是直接与物理节点,进行交互;而处理流通常直接处理的对象是节点流,是再上一层的包装。
比如:如果想对read操作进行同步缓冲,可以使用BufferedInputStream:
1 static void demo2() throws Exception{ 2 InputStream inputStream =null; 3 BufferedInputStream bufferedInputStream =null; 4 try { 5 inputStream = new FileInputStream("demo0.txt"); 6 bufferedInputStream = new BufferedInputStream(inputStream); 7 byte[] bb = new byte[1024]; 8 int temp=-1; 9 while((temp=bufferedInputStream.read(bb))!=-1){ 10 System.out.println(new String(bb,0,temp)); 11 } 12 } catch (FileNotFoundException e) { 13 // TODO Auto-generated catch block 14 e.printStackTrace(); 15 }finally{ 16 if(inputStream!=null){ 17 inputStream.close(); 18 } 19 } 20 }
RandomAccessFile: 任意访问内容类:既可以读取文件内容,也可以向文件输出数据,可以自由访问文件的任意位置,它可以自由定位文件记录指针。
二个重要方法:
- long getFilePointer(): 获取文件记录的当前指针位置
- void seek(long position): 将文件的记录指针特定position的位置。
使用RandomAccessFile 必须要设置模式:
- r: 只读
- rw: 读写,如果不存在,则自动创建。
- rws: 读写,读文件内容与元数据改动都会同步更新到Target Device上;
- rwd:与rws类似,差别在于,当元数据改动后,不会同步更新到Target Device
1 static void demo3() throws Exception{ 2 RandomAccessFile file = new RandomAccessFile("demo0.txt", "rw"); 3 System.out.println("Before invoke write:"+file.getFilePointer()); 4 file.seek(file.length()); 5 file.write("\nUsing RandomAccessFile Class".getBytes()); 6 7 System.out.println("After invoke write:"+file.getFilePointer()); 8 file.seek(0); 9 byte[] bb = new byte[1024]; 10 int temp=-1; 11 while ((temp=file.read(bb))>0) { 12 System.out.println(new String(bb,0,temp)); 13 } 14 15 file.close(); 16 }
如果要在指定的位置进行插入内容,那必须得把指定位置的内容进行缓存,不然会被替代。
1 static void demo4(String fileName,long position,String content) throws Exception{ 2 RandomAccessFile file = new RandomAccessFile(fileName, "rws"); 3 File tempFile = File.createTempFile("temp", null); 4 5 long currentLength = file.length(); 6 if(position>currentLength){ 7 return; 8 //Maybe you can setup position=currentLenght; Also you can setup anything what you want !!! 9 } 10 FileOutputStream fileOutputStream = new FileOutputStream(tempFile); // write data to "temp" file 11 FileInputStream fileInputStream = new FileInputStream(tempFile); // read data 12 byte[] bb = new byte[512]; 13 int tempNum=-1; 14 15 file.seek(position); 16 17 while((tempNum=file.read(bb))>0){ 18 fileOutputStream.write(bb, 0, tempNum); 19 } 20 21 file.seek(position); // Go back to position 22 file.write(content.getBytes()); 23 24 while((tempNum=fileInputStream.read(bb))>0){ 25 file.write(bb, 0, tempNum); 26 } 27 28 tempFile.deleteOnExit(); 29 if(fileInputStream!=null){ 30 fileInputStream.close(); 31 } 32 if(fileOutputStream!=null){ 33 fileOutputStream.close(); 34 } 35 36 file.close(); 37 }
【Dylan童鞋】
关注Dylan童鞋,请搜索微信号:DylanTongXue 。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Q群:315858410. 此群用于关注DylanTongXue者交流!群成员职业不限,程序员居多,讨论主题不限:技术分享,生活感悟,职场心得,时事分析...