Java输入输出流的使用详细介绍
1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。 Java.io是大多数面向数据流的输入/输出类的主要软件包。此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO。 流IO的好处是简单易用,缺点是效率较低。块IO效率很高,但编程比较复杂。 2.数据流的基本概念 数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。对数据读取程序来说,看不到数据流在写入时的分段情况,每次可以读取其中的任意长度的数据,但只能先读取前面的数据后,再读取后面的数据。不管写入时是将数据分多次写入,还是作为一个整体一次写入,读取时的效果都是完全一样的。 “流是磁盘或其它外围设备中存储的数据的源点或终点。” 在电脑上的数据有三种存储方式,一种是外存,一种是内存,一种是缓存。比如电脑上的硬盘,磁盘,U盘等都是外存,在电脑上有内存条,缓存是在CPU里面的。外存的存储量最大,其次是内存,最后是缓存,但是外存的数据的读取最慢,其次是内存,缓存最快。这里总结从外存读取数据到内存以及将数据从内存写到外存中。对于内存和外存的理解,我们可以简单的理解为容器,即外存是一个容器,内存又是另外一个容器。那又怎样把放在外存这个容器内的数据读取到内存这个容器以及怎么把内存这个容器里的数据存到外存中呢? 在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛: 标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流等等,java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。将数据冲外存中读取到内存中的称为输入流,将数据从内存写入外存中的称为输出流。 流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。 总结的基本概念如下: 一组有序,有起点和终点的字节的数据序列。包括输入流和输出流。 程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道 程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道。
采用数据流的目的就是使得输出输入独立于设备。 Input Stream不关心数据源来自何种设备(键盘,文件,网络) 流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:
1) 字节流:数据流中最小的数据单元是字节 2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。 3. 标准I/O Java程序可通过命令行参数与外界进行简短的信息交换,同时,也规定了与标准输入、输出设备,如键盘、显示器进行信息交换的方式。而通过文件可以与外界进行任意数据形式的信息交换。 1. 命令行参数复制代码 代码如下: public class TestArgs { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("args[" + i + "] is <" + args[i] + ">"); } } } 运行结果: args[0] is <Java> args[1] is <C> args[2] is <VB> 2. 标准输入,输出数据流java系统自带的标准数据流:java.lang.System: 复制代码 代码如下: java.lang.System public final class System extends Object{ static PrintStream err;//标准错误流(输出) static InputStream in;//标准输入(键盘输入流) static PrintStream out;//标准输出流(显示器输出流) } 注意: 1) 标准输出流 System.out System.out向标准输出设备输出数据,其数据类型为PrintStream。方法: Void print(参数)
Void println(参数)
2)标准输入流 System.in System.in读取标准输入设备数据(从标准输入获取数据,一般是键盘),其数 据类型为InputStream。方法: int read() //返回ASCII码。若,返回值=-1,说明没有读取到任何字节读取工作结束。
int read(byte[] b)//读入多个字节到缓冲区b中返回值是读入的字节数
例如: 复制代码 代码如下: public class StandardInputOutput { public static void main(String args[]) { int b; try { System.out.println("please Input:"); while ((b = System.in.read()) != -1) { System.out.print((char) b); } } catch (IOException e) { System.out.println(e.toString()); } } } 等待键盘输入,键盘输入什么,就打印出什么:
3)标准错误流 System.err输出标准错误,其数据类型为PrintStream。可查阅API获得详细说明。 标准输出通过System.out调用println方法输出参数并换行,而print方法输出参数但不换行。println或print方法都通 过重载实现了输出基本数据类型的多个方法,包括输出参数类型为boolean、char、int、long、float和double。同时,也重载实现 了输出参数类型为char[]、String和Object的方法。其中,print(Object)和println(Object)方法在运行时将调 用参数Object的toString方法。 4.java.IO层次体系结构 在整个Java.io包中最重要的就是5个类和一个接口。5个类指的是File、OutputStream、InputStream、Writer、Reader;一个接口指的是Serializable.掌握了这些IO的核心操作那么对于Java中的IO体系也就有了一个初步的认识了
Java I/O主要包括如下几个层次,包含三个部分: 1.流式部分DDIO的主体部分; 2.非流式部分DD主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor等类; 3.其他类--文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。 主要的类如下: 1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。 2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。 3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。 Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。 4. Reader(文件格式操作):抽象类,基于字符的输入操作。 5. Writer(文件格式操作):抽象类,基于字符的输出操作。 6. RandomAccessFile(随机文件操作):它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。 Java中IO流的体系结构如图: 5. 非流式文件类--File类 在Java语言的java.io包中,由File类提供了描述文件和目录的操作与管理方法。但File类不是InputStream、OutputStream或Reader、Writer的子类,因为它不负责数据的输入输出,而专门用来管理磁盘文件与目录。
作用:File类主要用于命名文件、查询文件属性和处理文件目录。 复制代码 代码如下: public class File extends Object implements Serializable,Comparable {} File类共提供了三个不同的构造函数,以不同的参数形式灵活地接收文件和目录名信息。构造函数: 1)File (String pathname) 例:File f1=new File("FileTest1.txt"); //创建文件对象f1,f1所指的文件是在当前目录下创建的FileTest1.txt
2)File (String parent , String child) 例:File f2=new File(“D:dir1","FileTest2.txt") ;// 注意:D:dir1目录事先必须存在,否则异常
3)File (File parent ,String child) 例:File f4=new File("dir3"); File f5=new File(f4,"FileTest5.txt"); //在如果 dir3目录不存在使用f4.mkdir()先创建 一个对应于某磁盘文件或目录的File对象一经创建, 就可以通过调用它的方法来获得文件或目录的属性。
1)public boolean exists( ) 判断文件或目录是否存在
2)public boolean isFile( ) 判断是文件还是目录 3)public boolean isDirectory( ) 判断是文件还是目录 4)public String getName( ) 返回文件名或目录名 5)public String getPath( ) 返回文件或目录的路径。 6)public long length( ) 获取文件的长度 7)public String[ ] list ( ) 将目录中所有文件名保存在字符串数组中返回。 File类中还定义了一些对文件或目录进行管理、操作的方法,常用的方法有:
1) public boolean renameTo( File newFile ); 重命名文件 2) public void delete( ); 删除文件 3) public boolean mkdir( ); 创建目录 例子: 复制代码 代码如下: import java.io.File; import java.io.IOException; public class TestFile { public static void main(String args[]) throws IOException { File dir = new File("root"); File f1 = new File(dir,"fileOne.txt"); File f2 = new File(dir,"fileTwo.java"); // 文件对象创建后,指定的文件或目录不一定物理上存在 if (!dir.exists()) dir.mkdir(); if (!f1.exists()) f1.createNewFile(); if (!f2.exists()) f2.createNewFile(); System.out.println("f1's AbsolutePath= " + f1.getAbsolutePath()); System.out.println("f1 Canread=" + f1.canRead()); System.out.println("f1's len= " + f1.length()); String[] FL; int count = 0; FL = dir.list(); for (int i = 0; i < FL.length; i++) { count++; System.out.println(FL[i] + "is in root"); } System.out.println("there are" + count + "file in //root"); } } 说明:File类的方法: (4) list()返回目录中所有文件名字符串 6. Java.IO流类库 java.io包中包含了流式I/O所需要的所有类。在java.io包中有四个基本类:InputStream、OutputStream及Reader、Writer类,它们分别处理字节流和字符流: 基本数据流的I/O 字节流 字符流 输入流 Inputstream Reader 输出流 OutputStream Writer Java中其他多种多样变化的流均是由它们派生出来的: JDK1.4版本开始引入了新I/O类库,它位于java.nio包中,新I/O类库利用通道和缓冲区等来提高I/O操作的效率。 在java.io包中, java.io.InputStream 表示字节输入流, java.io.OutputStream表示字节输出流,处于java.io包最顶层。这两个类均为抽象类,也就是说它们不能被实例化,必须生成子类之后才能实现一定的功能。 1. io流的具体分类 一、按I/O类型来总体分类: 1. Memory 1)从/向内存数组读写数据: CharArrayReader、 CharArrayWriter、ByteArrayInputStream、ByteArrayOutputStream 二、按数据来源(去向)分类:
7. 字节流InputStream/OutputStream InputStream 为字节输入流,它本身为一个抽象类,必须依靠其子类实现各种功能,此抽象类是表示字节输入流的所有类的超类。 继承自InputStream 的流都是向程序中输入数据的,且数据单位为字节(8bit); InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法.Inputstream类中的常用方法: 主要的子类:
1) FileInputStream把一个文件作为InputStream,实现对文件的读取操作 1. public void write(byte b[ ]):将参数b中的字节写到输出流。 2. public void write(byte b[ ],int len) :将参数b的从偏移量off开始的len个字节写到输出流。 3. public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。 4. public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。 5. public void close( ) : 关闭输出流并释放与流相关的系统资源。 主要的子类:
1) ByteArrayOutputStream:把信息存入内存中的一个缓冲区中 流结束的判断:方法read()的返回值为-1时;readLine()的返回值为null时。 3. 文件输入流: FileInputStream类FileInputStream可以使用read()方法一次读入一个字节,并以int类型返回,或者是使用read()方法时读入至一个byte数组,byte数组的元素有多少个,就读入多少个字节。在将整个文件读取完成或写入完毕的过程中,这么一个byte数组通常被当作缓冲区,因为这么一个byte数组通常扮演承接数据的中间角色。
作用:以文件作为数据输入源的数据流。或者说是打开文件,从文件读数据到内存的类。 使用方法(1) File fin=new File("d:/abc.txt"); FileInputStream in=new FileInputStream( fin); 使用方法(2) 程序举例: 复制代码 代码如下: import java.io.IOException; import java.io.FileInputStream; public class TestFile { public static void main(String args[]) throws IOException { try{ FileInputStream rf=new FileInputStream("InputFromFile.java"); int n=512; byte buffer[]=new byte[n]; while((rf.read(buffer,n)!=-1)&&(n>0)){ System.out.println(new String(buffer) ); } System.out.println(); rf.close(); } catch(IOException IOe){ System.out.println(IOe.toString()); } } } 4.文件输出流:FileOutputStream类 作用:用来处理以文件作为数据输出目的数据流;或者说是从内存区读数据入文件 FileOutputStream类用来处理以文件作为数据输出目的数据流;一个表示文件名的字符串,也可以是File或FileDescriptor对象。 程序举例:使用键盘输入一段文章,将文章保存在文件write.txt中 复制代码 代码如下: import java.io.IOException; import java.io.FileOutputStream; public class TestFile { public static void main(String args[]) throws IOException { try { System.out.println("please Input from Keyboard"); int count,n = 512; byte buffer[] = new byte[n]; count = System.in.read(buffer); FileOutputStream wf = new FileOutputStream("d:/myjava/write.txt"); wf.write(buffer,count); wf.close(); // 当流写操作结束时,调用close方法关闭流。 System.out.println("Save to the write.txt"); } catch (IOException IOe) { System.out.println("File Write Error!"); } } } 5. FileInputStream流和FileOutputStream的应用 利用程序将文件file1.txt 拷贝到file2.txt中。 复制代码 代码如下: import java.io.File; import java.io.IOException; import java.io.FileOutputStream; import java.io.FileInputStream; public class TestFile { public static void main(String args[]) throws IOException { try { File inFile = new File("copy.java"); File outFile = new File("copy2.java"); FileInputStream finS = new FileInputStream(inFile); FileOutputStream foutS = new FileOutputStream(outFile); int c; while ((c = finS.read()) != -1) { foutS.write(c); } finS.close(); foutS.close(); } catch (IOException e) { System.err.println("FileStreamsTest: " + e); } } } 6. 缓冲输入输出流 BufferedInputStream/ BufferedOutputStream
计算机访问外部设备非常耗时。访问外存的频率越高,造成CPU闲置的概率就越大。为了减少访问外存的次数,应该在一次对外设的访问中,读写更多的数据。为此,除了程序和流节点间交换数据必需的读写机制外,还应该增加缓冲机制。缓冲流就是每一个数据流分配一个缓冲区,一个缓冲区就是一个临时存储数据的内存。这样可以减少访问硬盘的次数,提高传输效率。 BufferedInputStream:当向缓冲流写入数据时候,数据先写到缓冲区,待缓冲区写满后,系统一次性将数据发送给输出设备。 BufferedOutputStream :当从向缓冲流读取数据时候,系统先从缓冲区读出数据,待缓冲区为空时,系统再从输入设备读取数据到缓冲区。 1)将文件读入内存:
将BufferedInputStream与FileInputStream相接 FileInputStream in=new FileInputStream( “file1.txt ” ); BufferedInputStream bin=new BufferedInputStream( in); 2)将内存写入文件: 将BufferedOutputStream与 FileOutputStream相接 FileOutputStreamout=new FileOutputStream(“file1.txt”); BufferedOutputStream bin=new BufferedInputStream(out); 3)键盘输入流读到内存 将BufferedReader与标准的数据流相接
InputStreamReader sin=new InputStreamReader (System.in) ;
BufferedReader bin=new BufferedReader(sin); 复制代码 代码如下: import java.io.*; public class ReadWriteToFile { public static void main(String args[]) throws IOException { InputStreamReader sin = new InputStreamReader(System.in); BufferedReader bin = new BufferedReader(sin); FileWriter out = new FileWriter("myfile.txt"); BufferedWriter bout = new BufferedWriter(out); String s; while ((s = bin.readLine()).length() > 0) { bout.write(s,s.length()); } } } 程序说明: 从键盘读入字符,并写入到文件中BufferedReader类的方法:String readLine() 作用:读一行字符串,以回车符为结束。 BufferedWriter类的方法:bout.write(String s,offset,len) 作用:从缓冲区将字符串s从offset开始,len长度的字符串写到某处。 8. 字符流Writer/Reader Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。 1. Reader抽象类用于读取字符流的抽象类。子类必须实现的方法只有 read(char[],int,int) 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。 1) FileReader :与FileInputStream对应 (1) public int read() throws IOException; //读取一个字符,返回值为读取的字符 (2) public int read(char cbuf[]) throws IOException; /*读取一系列字符到数组cbuf[]中,返回值为实际读取的字符的数量*/ 写入字符流的抽象类。子类必须实现的方法仅有 write(char[],int)、flush() 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。 其子类如下: 1) FileWrite: 与FileOutputStream对应 6) StringWriter:无与之对应的以字节为导向的stream 主要方法: (1) public void write(int c) throws IOException; //将整型值c的低16位写入输出流 Reader与Writer处理的是字符流,在处理字符流时涉及了字符编码的转换问题 复制代码 代码如下: import java.io.*; public class EncodeTest { private static void readBuff(byte [] buff) throws IOException { ByteArrayInputStream in =new ByteArrayInputStream(buff); int data; while((data=in.read())!=-1) System.out.print(data+" "); System.out.println(); in.close(); } public static void main(String args[]) throws IOException { System.out.println("内存中采用unicode字符编码:" ); char c='好'; int lowBit=c&0xFF; int highBit=(c&0xFF00)>>8; System.out.println(""+lowBit+" "+highBit); String s="好"; System.out.println("本地操作系统默认字符编码:"); readBuff(s.getBytes()); System.out.println("采用GBK字符编码:"); readBuff(s.getBytes("GBK")); System.out.println("采用UTF-8字符编码:"); readBuff(s.getBytes("UTF-8")); } } Writer类能够将内存中的Unicode字符转换为其他编码类型的字符,再写到输出流中。 9. IOException异常类的子类
1.public class EOFException : (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Comet OJ - Contest #9 & X Round 3 【XR-3】
- Java内存管理以及各个内存区域详解
- java – Mockito在Spring中的间谍对象
- java – 使用org.apache.commons.logging编写日志
- Java Web Services / JAXB – 抽象超类
- java – 使用Spring而不将依赖项暴露给客户端应用
- 你说一下对Java中的volatile的理解吧
- Java的wait(), notify()和notifyAll()使用心得
- Java定时任务:利用java Timer类实现定时执行任务
- java – libgdx – 如何绘制一些像素