Java IO流
来源:互联网 发布:java 生成xml格式报文 编辑:程序博客网 时间:2024/06/06 09:58
Java的IO流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作,Java中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述为“流”(Stream),通过流的方式允许Java程序使用相同的方式来访问不同的输入/输出源。 Java把所有传统的个流类型(类或抽象类)都放在java.io包中,用以实现输入/输出功能。
按照不同的分类方式,可以将流分为不同的类型,下面我们从不同的角度对流进行分类:
输入流和输出流
按照流的流向来分,可以分为输入流和输出流:
(1)输入流:只能从中读取数据,而不能向其写出数据。
(2)输出流:只能向其写出数据,而不能从中读取数据。
此处的输入、输出涉及到一个方向问题,数据从内存到硬盘,通常我们称为输出流------也就是说,这里的输入、输出是从程序运行所在内存的角度来划分的。
Java的输入流主要由InputStream和Reader作为基类,而输出流则主要由OutputStream和Writer作为基类。
字节流和字符流
字节流和字符流区别非常简单,它们的用法几乎完全一样,区别在于字节流和字符流所操作的数据单元不同:字节流操作的最小数据单元是8位的字节,而字符流操作的最小数据单元是16位的字符。
字节流主要由InputStream和OutputStream作为基类,而字符流则主要由Reader和Writer作为基类。
节点流和处理流
按照角色分,可以分为节点流和处理流。
可以从/向一个特定的IO设备(如磁盘、网络)读/写数据的流,称为节点流,节点流常常也被称为低级流。处理流则用于对一个已经存在的流进行连接或封装,通过封装后流来实现数据读/写功能,处理流也称为高级流。
流的概念模型
Java把所有设备里的有序数据抽象成流模型简化了输入/输出的处理。Java的IO流共涉及40多个类,这些看上去杂乱无章,但实际上是有规则的。Java的IO流的40多个类都是从4个抽象基类派生出来的:
(1)InputStream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流。
(2)OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流。
对于InputSteam和Reader而言,它们把输入设备抽象成一个“水管”,这个水管里的每个“水滴”依次排列,如下图所示:
输入流使用隐式指针来表示当前正准备从哪个“水滴”开始读取,每当程序从InputStream或Reader里取出一个或多个“水滴”后,记录指针自动向后移动。
对于OutputStream和Writer而言,它们同样把输出设备抽象成一个“水管”,只是这个水管里没有任何水滴,如下图所示:
如上图所示,当我们执行输出时,程序相当于依次把“水滴”放入到输出流的水管中,输出流同样采用隐式的记录指针来标识当前水滴即将放入的位置,每当程序想OutputStream或Writer里输出一个或多个水滴后,记录指针自动向后移动。
InputStream和Reader
在InputStream里包含如下三个方法:
(1)int read():从输入流中读取单个字节(相当于从图15.5所示水管中取出一滴水),返回所读去的字节数据(字节数据可以转换成int类型)。
(2)int read(byte[ ] b):从输入流中读取最多b.length个字节的数据,并将其存储在字节数组b中,返回实际读取的字节数。
(3)int read(byte[ ] b,int off,int len):从输入流中读取最多len字节的数据,并将其存储在数组b中,放入b数组中时,并不是从数组起点开始,而是从offset位置开始,返回实际读取的字节数。
在Reader里包含如下三个方法:
(1)int read():从输入流中读取单个字符,返回所读取的字符数据(字符数据可直接转换为int类型)。
(2)int read(char[ ] cbuf):从输入流中读取最多cbuf.length个字符的数据,并将其存储在字符数组cbuf中,返回实际读取的字节数。
(3)int read(char[ ],int off,int len):从输入流中读取最多len个字符的数据,并将其存储在字符数组cbuf中,放入cbuf数组中时,并不是从数组起点开始,而是从offset位置开始,返回实际读取的字符数。
InputStream和Reader都是抽象类,本身不能创建实例,但它们分别有一个用于读取文件的输入流:FileInputStream和FileReader,它们都是节点流-----会直接和指定文件关联。下面的程序示范了使用FileInputStream来读取自身的效果:
public class FileInputStreamTest
{
public static void main(String[] args) throws IOException
{
FileInputStream fis=new FileInputStream("FileInputStreamTest.java");
byte[] bbuf=new byte[1024];
int hasRead=0;
while((hasRead=fis.read(bbuf))>0)
{
//取出"竹筒"中的水滴(字节),将字节数组转换成字符串输入
System.out.print(new String(bbuf,0,hasRead));
}
fs.close();
}
}
上面的程序中的粗体字代码部分是使用FileInputStream循环“取水”的过程,运行上面程序将会输出上面程序的源代码。
下面的程序时使用FileInputStream来执行输入,并用FileOutputStream来执行输出,用以实现复制FileOutputStreamTest.java文件的功能。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;class FileOutputStreamTest
{
public static void main(String[] args) throws IOException
{
FileInputStream fis=null;
FileOutputStream fos=null;
try
{
fis=new FileInputStream("FileOutputStreamTest.java");
fos=new FileOutputStream("newFile.txt");
byte[] bbuf=new byte[1024];
int hasRead=0;
while((hasRead=fis.read(bbuf))>0)
{
fos.write(bbuf,0,hasRead);
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
finally
{
if(fis!=null)
{
fis.close();}
if(fos!=null)
{
fos.close();
}
}
}
}
运行上面的程序后,newFile.txt文件的内容和FileOutputStreamTest.java文件中的内容完全相同。
处理流
处理流可以隐藏底层设备上节点流的差异,并对外提供更加方便的输入\输出方法,让程序员只需要关心高级流的操作。我们要识别处理流非常简单,只有流的构造器参数不是一个物理节点,而是存在的流,那么这种流一定是处理流:而所有节点流都是直接以物理IO节点作为构造参数的,下面程序使用PrintStream处理流来包装InputStream,使用处理流后的输出流在输出是更加方便。
class PrintStreamTest
{
public static void main(String[] args)
{
PrintStream ps=null;
try
{
FileOutputStream fos=new FileOutputStream("test.txt");
ps=new PrintStream(fos);
ps.println("普通字符串");
ps.println(new PrintStreamTest());
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
finally
{
ps.close();
}
System.out.println("Hello World!");
}
}
上面程序先定义了一个节点输出流FileOutputStream,然后程序使用PrintStream来包装了该节点流,然后使用PrintStream输出字符串、输出对象。
输入输出体系
上面的表中粗体字标出的类代表节点流,必须直接与指定的物理节点关联;斜体字标出的类代表抽象基类,无法直接创建实例。
转换流
在输入/输出体系里还提供了2个转换流,这两个转换流用于实现将字节流转换成字符流,其中InputStreamReader将字节输入流转换成字符输入流,OutputStreamWriter将字节输出流转换成字符输出流。Java只提供了将字节流转换成字符流的转换流,没有提供将字符流转换成字节流的转换流。
下面介绍将标准输入流(System.in)即键盘输入,转换成字符输入流。标准输入流是InputStream类的实例,使用不太方便,而且键盘输入的内容是文本内容,我们可以使用InputStreamReader将其转换成字符输入流,并将Reder再次包装成BufferedReader,一行一行读取内容,程序如下:
import java.io.*;
import java.lang.System;
class KeyinTest
{
public static void main(String[] args) throws Exception
{
BufferedReader br=null;
try
{//将System.in对象转换成Reader对象
InputStreamReader reader=new InputStreamReader(System.in);//将普通Reader包装成BufferedReader
br=new BufferedReader(reader);
String buffer=null;
while((buffer=br.readLine())!=null)
{
if(buffer.equals("exit"))
{
System.exit(1);
}
System.out.println("输入内容为:"+buffer);
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
finally
{
if(br!=null)
{
br.close();
}
}
System.out.println("Hello World!");
}
}
- JAVA【IO一】IO流
- Java-IO-java的IO流
- java IO 流
- JAVA之IO流
- java IO(字符流)
- java的io流
- JAVA之IO流(
- JAVA 基础IO流
- JAVA 中的IO流
- Java IO 流学习
- JAVA 中的IO流
- Java IO流操作方法。。
- java io流总结
- 转]JAVA IO流
- JAVA IO流
- Java中的IO流
- JAVA IO 流操作
- 详述JAVA IO流
- ResultSetMetaData和DatabaseMetaData
- 面向对象的三个特征
- 【转载】JAVA --String类笔试面试题
- 一些java笔试面试题
- 文件过滤器
- Java IO流
- 转 Android ListView专题之十三 使用Button使用的问题
- Android GridView专题之一 给GridView添加ContextMenu
- Socket
- XML解析
- Android百度地图API学习(一) 开始
- Android百度地图API学习(二) 开发基本流程
- Android 百度地图API学习-----坐标
- Android 百度地图API学习(四)-----覆盖类