Java IO最详解
2016-06-02 10:51
417 查看
刚开始学Java时候,一直搞不懂java里面的io关系,在网上找了很多大多都是给个结构图草草描述也看的不是很懂。而且没有结合到java7 的最新技术,所以自己结合API来整理一下,有错的话请指正,也希望大家提出宝贵意见。
首先看个图:(如果你也是初学者,我相信你看了真个人都不好了,想想java设计者真是煞费苦心啊!)
Java I/O系统的类实在是太多了,这里我们只学习一些基本的和常用的,相信能够掌握这些就可以解决我们以后的普通应用了
什么是数据流(字节流)
数据流是指所有的数据通信通道;
有两类流,InputStream and OutputStream。
Java中每一种流的基本功能依赖于它们InputStream 用于read,OutputStream 用于write, 读和写都是相对与内存说的,读就是从其他地方把数据拿进内存,写就是把数据从内存推出去
这两个都是抽象类,不能直接使用
InputStream 的方法有:
1.read() :从流中读入数据 有3中方式:
2.int read(): 一次读一个字节
3.int read(byte[]) :读多个字节到数组中
4.int read(byte[],int off,int len) :指定从数组的哪里开始,读多长
5.skip() :跳过流中若干字节
6.available() :返回流中可用字节数,但基于网络时无效,返回0
7.markSupported(): 判断是否支持标记与复位操作
8.mark() :在流中标记一个位置,要与markSupported()连用
9.reset() :返回标记过的位置
10.close() :关闭流
OutputStream 的方法:
1.write(int) :写一个字节到流中
2.write(byte[]): 将数组中的内容写到流中
3.write(byte[],int off,int len): 将数组中从off指定的位置开始len长度的数据写到流中
4.close() :关闭流
5.flush() :将缓冲区中的数据强制输出
File 类
File 可以表示文件也可以表示目录,File 类控制所有硬盘操作
构造器:
1.File(File parent,String child): 用父类和文件名构造
2.File(String pathname) :用绝对路径构造
3.File(String parent,String child): 用父目录和文件名构造
4.File(URI uri) :用远程文件构造
常用方法:
-----------------------------------------------------------------------------------------------------------------------------------------------------------
1.boolean createNewFile();
2.boolean exists();
例子:
//建立 test.txt 文件对象,判断是否存在,不存在就创建
---------------------------------------------------------------------------------------------------------------------------------------------------------
3.boolean mkdir()/mkdirs()
4.boolean renameTo(File destination)
例子://看一下这 mkdir()/mkdirs() 的区别和 renameTo 的用法
--------------------------------------------------------------------------------------------------------------------------------------------------------------
String getPath()/getAbsolutePath()
String getParent()/getName()
例子://硬盘上并没有parent 目录和 test.txt 文件,但我们仍然可以操作,因为我们创建了他们的对象,是对对象进行操
String list[] //显示目录下所有文件
long lastModified() //返回 1970.1.1 到最后修改时间的秒数
boolean isDirectory()例子://列出目录下的所有文件和目录,最后修改时间,是目录的后面标出<DIR>,是文件的后面标出文件长度
File f=new File("temp.txt");
FileInputStream in=new FileInputStream(f);
FileOutputStream out=new FileOutputStream(f);
例子:文件拷贝
BufferedInputStream
BufferedOutputStream
他们是在普通文件流上加了缓冲的功能,所以构造他们时要先构造普通流
例子:文件拷贝的缓冲改进
原始数据流
DataInputStream
DataOutputStream
他们是在普通流上加了读写原始型数据的功能,所以构造他们时要先构造普通流
方法:
readBoolean()/writeBoolean()
readByte()/writeByte()
readChar()/writeByte()
......
例子://这个流比较简单,要注意的就是读时的顺序要和写时的一样
串行化:对象通过写出描述自己状态的数值来记述自己的过程叫串行话
对象流:能够输入输出对象的流
将串行化的对象通过对象流写入文件或传送到其他地方
对象流是在普通流上加了传输对象的功能,所以构造对象流时要先构造普通文件流
注意:只有实现了Serializable接口的类才能被串行化
例子:
上面的几种流的单位是 byte,所以叫做字节流,写入文件的都是二进制字节,我们无法直接看,下面要学习的是字节流
Java采用 Unicode 字符集,每个字符和汉字都采用2个字节进行编码,ASCII 码是 Unicode 编码的自集
InputStreamReader 是 字节流 到 字符桥的桥梁 ( byte->char 读取字节然后用特定字符集编码成字符)
OutputStreamWriter是 字符流 到 字节流的桥梁 ( char->byte )
他们是在字节流的基础上加了桥梁作用,所以构造他们时要先构造普通文件流
我们常用的是:
BufferedReader 方法:readLine()
PrintWriter 方法:println()
例子:
可同时完成读写操作
支持随机文件操作的方法:
readXXX()/writeXXX()
seek() 将指针调到所需位置
getFilePointer() 返回指针当前位置
length() 返回文件长度
例子:把若干个32位的整数写到一个名为 “temp.txt”的文件中,然后利用seek方法,以相反的顺序再读取这些数据
这部分的难点就是类比较复杂,尤其是每个类的构造方式,我认为记住下面这个图比记类的继承关系更好些
字节流:
InputStream
|-- FileInputStream (基本文件流)
|-- BufferedInputStream
|-- DataInputStream
|-- ObjectInputStream
OutputStream 同上图
BufferedInputStream DataInputStream ObjectInputStream 只是在 FileInputStream 上增添了相应的功能,构造时先构造FileInputStream
字符流:
Reader
|-- InputStreamReader (byte->char 桥梁)
|-- BufferedReader (常用)
Writer
|-- OutputStreamWriter (char->byte 桥梁)
|-- BufferedWriter
|-- PrintWriter (常用)
随机存取文件 RandomAccessFile
首先看个图:(如果你也是初学者,我相信你看了真个人都不好了,想想java设计者真是煞费苦心啊!)
Java I/O系统的类实在是太多了,这里我们只学习一些基本的和常用的,相信能够掌握这些就可以解决我们以后的普通应用了
什么是数据流(字节流)
数据流是指所有的数据通信通道;
有两类流,InputStream and OutputStream。
Java中每一种流的基本功能依赖于它们InputStream 用于read,OutputStream 用于write, 读和写都是相对与内存说的,读就是从其他地方把数据拿进内存,写就是把数据从内存推出去
这两个都是抽象类,不能直接使用
InputStream 的方法有:
1.read() :从流中读入数据 有3中方式:
2.int read(): 一次读一个字节
3.int read(byte[]) :读多个字节到数组中
4.int read(byte[],int off,int len) :指定从数组的哪里开始,读多长
5.skip() :跳过流中若干字节
6.available() :返回流中可用字节数,但基于网络时无效,返回0
7.markSupported(): 判断是否支持标记与复位操作
8.mark() :在流中标记一个位置,要与markSupported()连用
9.reset() :返回标记过的位置
10.close() :关闭流
OutputStream 的方法:
1.write(int) :写一个字节到流中
2.write(byte[]): 将数组中的内容写到流中
3.write(byte[],int off,int len): 将数组中从off指定的位置开始len长度的数据写到流中
4.close() :关闭流
5.flush() :将缓冲区中的数据强制输出
File 类
File 可以表示文件也可以表示目录,File 类控制所有硬盘操作
构造器:
1.File(File parent,String child): 用父类和文件名构造
2.File(String pathname) :用绝对路径构造
3.File(String parent,String child): 用父目录和文件名构造
4.File(URI uri) :用远程文件构造
常用方法:
-----------------------------------------------------------------------------------------------------------------------------------------------------------
1.boolean createNewFile();
2.boolean exists();
例子:
//建立 test.txt 文件对象,判断是否存在,不存在就创建
import java.io.*; public class CreateNewFile{ public static void main(String args[]){ File f=new File("test.txt"); try{ if(!f.exists()) f.createNewFile(); else System.out.println("exists"); }catch(Exception e){ e.printStackTrace(); } } }
---------------------------------------------------------------------------------------------------------------------------------------------------------
3.boolean mkdir()/mkdirs()
4.boolean renameTo(File destination)
例子://看一下这 mkdir()/mkdirs() 的区别和 renameTo 的用法
import java.io.*; public class CreateDir{ public static void main(String args[]){ File f=new File("test.txt"); File f1=new File("Dir"); File f2=new File("Top/Bottom"); File f3=new File("newTest.txt"); try{ f.renameTo(f3); f1.mkdir(); f2.mkdirs(); }catch(Exception e){ e.printStackTrace(); } } }
--------------------------------------------------------------------------------------------------------------------------------------------------------------
String getPath()/getAbsolutePath()
String getParent()/getName()
例子://硬盘上并没有parent 目录和 test.txt 文件,但我们仍然可以操作,因为我们创建了他们的对象,是对对象进行操
import java.io.*; public class Test{ public static void main(String args[]){ File f=new File("parent/test.txt"); File f1=new File("newTest.txt"); try{ System.out.println(f.getParent()); System.out.println(f.getName()); System.out.println(f1.getPath()); System.out.println(f1.getAbsolutePath()); }catch(Exception e){ e.printStackTrace(); } } }----------------------------------------------------------------------------------------------------------------------------------------------------------
String list[] //显示目录下所有文件
long lastModified() //返回 1970.1.1 到最后修改时间的秒数
boolean isDirectory()例子://列出目录下的所有文件和目录,最后修改时间,是目录的后面标出<DIR>,是文件的后面标出文件长度
import java.io.*; import java.util.*; public class Dir{ public static void main(String args[]){ File f=new File("Dir"); String[] listAll=null; File temp=null; try{ listAll=f.list(); for(int i=0;i<listAll.length;i++){ temp=new File(listAll<i>); System.out.print(listAll<i>+"\t"); if(temp.isDirectory()) System.out.print("\t<DIR>\t"); else System.out.print(temp.length()+"\t"); System.out.println(new Date(temp.lastModified())) } }catch(Exception e){ e.printStackTrace(); } } }文件流的建立
File f=new File("temp.txt");
FileInputStream in=new FileInputStream(f);
FileOutputStream out=new FileOutputStream(f);
例子:文件拷贝
import java.io.*; public class Copy{ public static void main(String args[]){ FileInputStream fis=null; FileOutputStream fos=null; try{ fis=new FileInputStream("c2.gif"); fos=new FileOutputStream("c2_copy.gif"); int c; while((c=fis.read()) != -1) fos.write(c); }catch(Exception e){ e.printStackTrace(); }finally{ if(fis != null) try{ fis.close(); }catch(Exception e){ e.printStackTrace(); } if(fos!= null) try{ fos.close(); }catch(Exception e){ e.printStackTrace(); } } } } <span style="background-color: rgb(0, 102, 0);"><span style="color:#FFFFFF;"><strong> </strong></span></span>缓冲区流
BufferedInputStream
BufferedOutputStream
他们是在普通文件流上加了缓冲的功能,所以构造他们时要先构造普通流
例子:文件拷贝的缓冲改进
import java.io.*; public class Copy{ public static void main(String args[]){ BufferedInputStream bis=null; BufferedOutputStream bos=null; byte buf[]=new byte[100]; try{ bis=new BufferedInputStream(new FileInputStream("persia.mp3")); bos=new BufferedOutputStream(new FileOutputStream("persia_copy.mp3")); int len=0; while( true ){ len=bis.read(buf); if(len<=0) break; bos.write(buf,0,len); } bos.flush();//缓冲区只有满时才会将数据输出到输出流,用flush()将未满的缓冲区中数据强制输出 }catch(Exception e){ e.printStackTrace(); }finally{ if(bis != null) try{ bis.close(); }catch(Exception e){ e.printStackTrace(); } if(bos!= null) try{ bos.close(); }catch(Exception e){ e.printStackTrace(); } } } }
原始数据流
DataInputStreamDataOutputStream
他们是在普通流上加了读写原始型数据的功能,所以构造他们时要先构造普通流
方法:
readBoolean()/writeBoolean()
readByte()/writeByte()
readChar()/writeByte()
......
例子://这个流比较简单,要注意的就是读时的顺序要和写时的一样
import java.io.*; public class DataOut{ public static void main(String args[]){ DataOutputStream dos=null; try{ dos=new DataOutputStream(new FileOutputStream("dataout.txt")); dos.writeInt(1); dos.writeBoolean(true); dos.writeLong(100L); dos.writeChar('a'); }catch(Exception e){ e.printStackTrace(); }finally{ if(dos!=null) try{ dos.close(); }catch(Exception e){ } } } }
import java.io.*; public class DataIn{ public static void main(String args[]){ DataInputStream dis=null; try{ dis=new DataInputStream(new FileInputStream("dataout.txt")); System.out.println(dis.readInt()); System.out.println(dis.readBoolean()); System.out.println(dis.readLong()); System.out.println(dis.readChar()); }catch(Exception e){ e.printStackTrace(); }finally{ if(dis!=null) try{ dis.close(); }catch(Exception e){ } } } }对象流
串行化:对象通过写出描述自己状态的数值来记述自己的过程叫串行话
对象流:能够输入输出对象的流
将串行化的对象通过对象流写入文件或传送到其他地方
对象流是在普通流上加了传输对象的功能,所以构造对象流时要先构造普通文件流
注意:只有实现了Serializable接口的类才能被串行化
例子:
import java.io.*; class Student implements Serializable{ private String name; private int age; public Student(String name,int age){ this.name=name; this.age=age; } public void greeting(){ System.out.println("hello ,my name is "+name); } public String toString(){ return "Student["+name+","+age+"]"; } }
public class ObjectOutTest{ public static void main(String args[]){ ObjectOutputStream oos=null; try{ oos=new ObjectOutputStream(new FileOutputStream("student.txt")); Student s1=new Student("Jerry",24); Student s2=new Student("Andy",33); oos.writeObject(s1); oos.writeObject(s2); }catch(Exception e){ e.printStackTrace(); }finally{ if(oos!=null) try{ oos.close(); }catch(Exception e){ e.printStackTrace(); } } } }
import java.io.*; public class ObjectInTest{ public static void main(String args[]){ ObjectInputStream ois=null; Student s=null; try{ ois=new ObjectInputStream( new FileInputStream("student.txt")); System.out.println("--------------------"); s=(Student)ois.readObject(); System.out.println(s); s.greeting(); System.out.println("--------------------"); s=(Student)ois.readObject(); System.out.println(s); s.greeting(); }catch(Exception e){ e.printStackTrace(); }finally{ if(ois!=null) try{ ois.close(); }catch(Exception e){ e.printStackTrace(); } } } }字符流 InputStreamReader/OutputStreamWriter
上面的几种流的单位是 byte,所以叫做字节流,写入文件的都是二进制字节,我们无法直接看,下面要学习的是字节流
Java采用 Unicode 字符集,每个字符和汉字都采用2个字节进行编码,ASCII 码是 Unicode 编码的自集
InputStreamReader 是 字节流 到 字符桥的桥梁 ( byte->char 读取字节然后用特定字符集编码成字符)
OutputStreamWriter是 字符流 到 字节流的桥梁 ( char->byte )
他们是在字节流的基础上加了桥梁作用,所以构造他们时要先构造普通文件流
我们常用的是:
BufferedReader 方法:readLine()
PrintWriter 方法:println()
例子:
import java.io.*; public class PrintWriterTest{ public static void main(String args[]){ PrintWriter pw=null; try{ pw=new PrintWriter(new OutputStreamWriter(new FileOutputStream("bufferedwriter.txt"))); pw.println("hello world"); }catch(Exception e){ e.printStackTrace(); }finally{ if(pw!=null) try{ pw.close(); }catch(Exception e){ e.printStackTrace(); } } } }
import java.io.*; public class BufferedReaderTest{ public static void main(String args[]){ BufferedReader br=null; try{ br=new BufferedReader(new InputStreamReader(new FileInputStream("bufferedwriter.txt"))); System.out.println(br.readLine()); }catch(Exception e){ e.printStackTrace(); }finally{ if(br!=null) try{ br.close(); }catch(Exception e){ e.printStackTrace(); } } } }随机存取文件 RandomAccessFile
可同时完成读写操作
支持随机文件操作的方法:
readXXX()/writeXXX()
seek() 将指针调到所需位置
getFilePointer() 返回指针当前位置
length() 返回文件长度
例子:把若干个32位的整数写到一个名为 “temp.txt”的文件中,然后利用seek方法,以相反的顺序再读取这些数据
import java.io.*; public class RandomFile{ public static void main(String args[]){ RandomAccessFile raf=null; int data[]={12,31,56,23,27,1,43,65,4,99}; try{ raf=new RandomAccessFile("temp.txt","rw"); for(int i=0;i<data.length;i++) raf.writeInt(data<i>); for(int i=data.length-1;i>=0;i--){ raf.seek(i*4); System.out.println(raf.readInt()); } }catch(Exception e){ e.getMessage(); }finally{ if(raf!=null) try{ raf.close(); }catch(Exception e){ e.getMessage(); } } } }小结
这部分的难点就是类比较复杂,尤其是每个类的构造方式,我认为记住下面这个图比记类的继承关系更好些
字节流:
InputStream
|-- FileInputStream (基本文件流)
|-- BufferedInputStream
|-- DataInputStream
|-- ObjectInputStream
OutputStream 同上图
BufferedInputStream DataInputStream ObjectInputStream 只是在 FileInputStream 上增添了相应的功能,构造时先构造FileInputStream
字符流:
Reader
|-- InputStreamReader (byte->char 桥梁)
|-- BufferedReader (常用)
Writer
|-- OutputStreamWriter (char->byte 桥梁)
|-- BufferedWriter
|-- PrintWriter (常用)
随机存取文件 RandomAccessFile
相关文章推荐
- Java 中Iterator 、Vector、ArrayList、List 使用深入剖析
- [jvm解析系列][一]Java内存区域分配和内存溢出异常OOM
- eclipse开发Android项目无法导入相同名称工程
- Java设计模式
- java之BASE64加解密
- Java获取文件路径笔记
- Java NIO系列教程(六) Selector
- Java虚拟机(JVM)的内存设置
- Java开发中的23种设计模式详解
- Java.lang.Runnable 接口
- Spark 1.6 (Java) 问题汇总
- Java基础知识点收集
- Eclipse快捷键-方便查找
- JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载
- Java中值传递与引用传递
- Java注解
- Java String 对 null 对象的容错处理
- Java做web开发的另一种思路
- java6.02学习笔记UDPserver
- Solr安装及集成javaWeb