您当前的位置:首页 > 互联网教程

JAVA的输入输出流是指的什么啊

发布时间:2025-05-24 10:16:42    发布人:远客网络

JAVA的输入输出流是指的什么啊

一、JAVA的输入输出流是指的什么啊

Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流....本文的目的是为大家做一个简要的介绍。

流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样,如下图:

Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。Java中其他多种多样变化的流均是由它们派生出来的:

在这其中InputStream和OutputStream在早期的Java版本中就已经存在了,它们是基于字节流的,而基于字符流的Reader和Writer是后来加入作为补充的。以上的层次图是Java类库中的一个基本的层次体系。

在这四个抽象类中,InputStream和Reader定义了完全相同的接口:

int read(char cbuf[], int offset, int length)

而OutputStream和Writer也是如此:

int write(char cbuf[], int offset, int length)

这六个方法都是最基本的,read()和write()通过方法的重载来读写一个字节,或者一个字节数组。

更多灵活多变的功能是由它们的子类来扩充完成的。知道了Java输入输出的基本层次结构以后,本文在这里想给大家一些以后可以反复应用例子,对于所有子类的细节及其功能并不详细讨论。

public void samples() throws IOException{

//1.这是从键盘读入一行数据,返回的是一个字符串

BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));

System.out.print("Enter a line:");

System.out.println(stdin.readLine());

BufferedReader in= new BufferedReader(new FileReader("IOStreamDemo.java"));

String s, s2= new String();

while((s= in.readLine())!= null)

//3.这是从一个字符串中逐个读入字节

StringReader in1= new StringReader(s2);

while((c= in1.read())!=-1)

System.out.print((char)c);

BufferedReader in2= new BufferedReader(new StringReader(s2));

PrintWriter out1= new PrintWriter(new BufferedWriter(new FileWriter("IODemo.out")));

while((s= in2.readLine())!= null)

out1.println(lineCount+++":"+ s);

System.err.println("End of stream");

对于上面的例子,需要说明的有以下几点:

1. BufferedReader是Reader的一个子类,它具有缓冲的作用,避免了频繁的从物理设备中读取信息。它有以下两个构造函数:

BufferedReader(Reader in, int sz)

void mark(int readAheadLimit)//标记当前位置

boolean markSupported()//是否支持标记

int read()//继承自Reader的基本方法

int read(char[] cbuf, int off, int len)//继承自Reader的基本方法

String readLine()//读取一行内容并以字符串形式返回

boolean ready()//判断流是否已经做好读入的准备

void reset()//重设到最近的一个标记

long skip(long n)//跳过指定个数的字符读取

2. InputStreamReader是InputStream和Reader之间的桥梁,由于System.in是字节流,需要用它来包装之后变为字符流供给 BufferedReader使用。

3. PrintWriter out1= new PrintWriter(new BufferedWriter(new FileWriter("IODemo.out")));

这句话体现了Java输入输出系统的一个特点,为了达到某个目的,需要包装好几层。首先,输出目的地是文件IODemo.out,所以最内层包装的是FileWriter,建立一个输出文件流,接下来,我们希望这个流是缓冲的,所以用BufferedWriter来包装它以达到目的,最后,我们需要格式化输出结果,于是将PrintWriter包在最外层。

Java提供了这样一个功能,将标准的输入输出流转向,也就是说,我们可以将某个其他的流设为标准输入或输出流,看下面这个例子:

public static void main(String[] args) throws IOException{

PrintStream console= System.out;

BufferedInputStream in= new BufferedInputStream( new FileInputStream("Redirecting.java"));

PrintStream out= new PrintStream( new BufferedOutputStream( new FileOutputStream("test.out")));

BufferedReader br= new BufferedReader( new InputStreamReader(System.in));

while((s= br.readLine())!= null)

在这里java.lang.System的静态方法

static void setIn(InputStream in)

static void setOut(PrintStream out)

提供了重新定义标准输入输出流的方法,这样做是很方便的,比如一个程序的结果有很多,有时候甚至要翻页显示,这样不便于观看结果,这是你就可以将标准输出流定义为一个文件流,程序运行完之后打开相应的文件观看结果,就直观了许多。

Java流有着另一个重要的用途,那就是利用对象流对对象进行序列化。下面将开始介绍这方面的问题。

在一个程序运行的时候,其中的变量数据是保存在内存中的,一旦程序结束这些数据将不会被保存,一种解决的办法是将数据写入文件,而Java中提供了一种机制,它可以将程序中的对象写入文件,之后再从文件中把对象读出来重新建立。这就是所谓的对象序列化Java中引入它主要是为了RMI(Remote Method Invocation)和Java Bean所用,不过在平时应用中,它也是很有用的一种技术。

所有需要实现对象序列化的对象必须首先实现Serializable接口。下面看一个例子:

public class Logon implements Serializable{

private Date date= new Date();

private transient String password;

Logon(String name, String pwd){

String pwd=(password== null)?"(n/a)": password;

return"logon info:\n"+"username:"+ username+"\n date:"+ date+"\n password:"+ pwd;

public static void main(String[] args) throws IOException, ClassNotFoundException{

Logon a= new Logon("Morgan","morgan83");

System.out.println("logon a="+ a);

ObjectOutputStream o= new ObjectOutputStream( new FileOutputStream("Logon.out"));

long t= System.currentTimeMillis()+ seconds* 1000;

while(System.currentTimeMillis()< t);

ObjectInputStream in= new ObjectInputStream( new FileInputStream("Logon.out"));

System.out.println("Recovering object at"+ new Date());

a=(Logon)in.readObject();

System.out.println("logon a="+ a);

类Logon是一个记录登录信息的类,包括用户名和密码。首先它实现了接口Serializable,这就标志着它可以被序列化。之后再main方法里ObjectOutputStream o= new ObjectOutputStream( new FileOutputStream("Logon.out"));新建一个对象输出流包装一个文件流,表示对象序列化的目的地是文件Logon.out。然后用方法writeObject开始写入。想要还原的时候也很简单ObjectInputStream in= new ObjectInputStream( new FileInputStream("Logon.out"));新建一个对象输入流以文件流Logon.out为参数,之后调用readObject方法就可以了。

需要说明一点,对象序列化有一个神奇之处就是,它建立了一张对象网,将当前要序列化的对象中所持有的引用指向的对象都包含起来一起写入到文件,更为奇妙的是,如果你一次序列化了好几个对象,它们中相同的内容将会被共享写入。这的确是一个非常好的机制。它可以用来实现深层拷贝。

关键字transient在这里表示当前内容将不被序列化,比如例子中的密码,需要保密,所以没有被写入文件。

对Java的输入输出功能,就浅浅的介绍到这里,本文的目的只是开一个好头,希望能让大家对Java输入输出流有个基本的认识。

二、java 输入输出流 (被采纳为答案者加100分)

其中BufferedInputStream是FileInputStream的子类,你可以理解成同样处理一个文件,BufferedInputStream效率更高,原因是BufferedInputStream采用了更高效的字节流处理方式,

BufferedInputStream才用缓冲流把内在的缓冲器连接到I/O流,允许java程序对多个字节同时操作,这样就提高了效率。

inputstreamreader的构造函数带两个参数,一是关联到的文件,二是字符解码方式.所以实际上通过inputstreamreader实例读出来的东西已经不是磁盘上原始的字节数据了,而是根据你指定的解码方式(如果你没有指定,则使用系统缺省的,win2000下是gbk/gb2312)把字节流转换成了字符流,注意字节流和字符流的区别,一个字节就是8比特位(32位机器上),而一个字符含多少字节则与不同的编码/解码方式有关了,如gbk是一字节,utf-8是1-3的变长字节,utf-16是2个定长字节.

于是值得你注意的就是当你用inputstreamreader读文件时,你应该知道该文件被存储时是用什么方式编码的,否则你指定错了解码方式,读出来的就是乱码.但是退一步来说,在全英文环境下,问题也没这严重.因为所有的字符集在前七位上都是与ascii兼容的(我猜的,也许有的不是),然而当你的程序涉及中文字符时,肯定是会出错了.

那么fileinputstream的特点呢?它的构造函数就一个,即关联到的文件,既然没有指定解码方式,那它所做的就是只以字节流的方式读出文件而不做任何处理,你应该用一个字节数组来接受它,对该数组你以后还可以做任何想做的操作。

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.BufferedReader;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.InputStreamReader;

/* public static void main(String[] args){

String str=new String("Face recognition in the thermal infrared domain has received relatively little attention in the literature in comparison with recognition in visible-spectrum imagery");

StringTokenizer token=new StringTokenizer(str);

Hashtable ht=new Hashtable();

while(token.hasMoreTokens()){

String temp=new String(token.nextToken());

System.out.print("KEY_NO:"+obj);

System.out.println("="+ht.get(obj));

public static void main(String[] args){

String file1="d:\\1.doc";

String file2="d:\\2.doc";

//fileCheck("d:\\test1.txt");

// readFile("D:\\test1.txt");

// readFileByte("D:\\test1.txt");

// readFileByFile("D:\\test1.txt");

// TODO Auto-generated catch block

public static void testFile() throws IOException{

copyFile("D:\\test1.txt","D:\\test2.txt");

public static void copyFile(String inName,String outName) throws IOException

if(!tmp.canRead())tmp.createNewFile();

BufferedInputStream in= new BufferedInputStream(new FileInputStream(inName));

BufferedOutputStream out= new BufferedOutputStream(new FileOutputStream(outName));

public static void readFile(String inName) throws IOException

BufferedReader read= new BufferedReader(new InputStreamReader(new FileInputStream(inName)));

while((b=read.readLine())!=null)

public static void readFileByte(String inName) throws IOException

BufferedInputStream read= new BufferedInputStream(new FileInputStream(inName));

public static void readFileByFile(String name) throws IOException

FileReader fr= new FileReader(tmp);

BufferedReader br= new BufferedReader(fr);

while((b=br.readLine())!=null)

public static void copyFile(InputStream in,OutputStream out, boolean close) throws IOException{

public static void print(Object o)

public static void fileCheck(String name) throws IOException

print("Canonical name:"+f.getCanonicalPath());

print("Parent directory:"+p);

if(f.canRead())print("file can be read!");

if(f.canWrite())print("file can be writable!");

print("last modified time:"+d);

print("file size is:"+f.length()+" bytes");

}else if(f.isDirectory()){print("is a directry!");}

print("neither a directory or a file!");

三、java.io的Java流输入输出原理

1、Java把这些不同来源和目标的数据都统一抽象为数据流。Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。

2、在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流。按流向分:

3、输入流:程序可以从中读取数据的流。

4、输出流:程序能向其中写入数据的流。

5、字节流:以字节为单位传输数据的流

6、字符流:以字符为单位传输数据的流

7、节点流:用于直接操作目标设备的流

8、过滤流:是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。 JDK所提供的所有流类位于java.io包中,都分别继承自以下四种抽象流类。

9、InputStream:继承自InputStream的流都是用于向程序中输入数据的,且数据单位都是字节(8位)。

10、OutputStream:继承自OutputStream的流都是程序用于向外输出数据的,且数据单位都是字节(8位)。

11、Reader:继承自Reader的流都是用于向程序中输入数据的,且数据单位都是字符(16位)。

12、Writer:继承自Writer的流都是程序用于向外输出数据的,且数据单位都是字符(16位)。 BufferedInputStream BufferedInputStream为另一个输入流添加一些功能,即缓冲输入以及支持 mark和 reset方法的能力。 BufferedOutputStream该类实现缓冲的输出流。 BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 BufferedWriter将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 ByteArrayInputStream ByteArrayInputStream包含一个内部缓冲区,该缓冲区包含从流中读取的字节。 ByteArrayOutputStream此类实现了一个输出流,其中的数据被写入一个 byte数组。 CharArrayReader此类实现一个可用作字符输入流的字符缓冲区。 CharArrayWriter此类实现一个可用作 Writer的字符缓冲区。 Console此类包含多个方法,可访问与当前 Java虚拟机关联的基于字符的控制台设备(如果有)。 DataInputStream数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java数据类型。 DataOutputStream数据输出流允许应用程序以适当方式将基本 Java数据类型写入输出流中。 File文件和目录路径名的抽象表示形式。 FileDescriptor文件描述符类的实例用作与基础机器有关的某种结构的不透明句柄,该结构表示开放文件、开放套接字或者字节的另一个源或接收者。 FileInputStream FileInputStream从文件系统中的某个文件中获得输入字节。 FileOutputStream文件输出流是用于将数据写入 File或 FileDescriptor的输出流。 FilePermission此类表示对文件和目录的访问。 FileReader用来读取字符文件的便捷类。 FileWriter用来写入字符文件的便捷类。 FilterInputStream FilterInputStream包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。 FilterOutputStream此类是过滤输出流的所有类的超类。 FilterReader用于读取已过滤的字符流的抽象类。 FilterWriter用于写入已过滤的字符流的抽象类。 InputStream此抽象类是表示字节输入流的所有类的超类。 InputStreamReader InputStreamReader是字节流通向字符流的桥梁:它使用指定的 charset读取字节并将其解码为字符。 LineNumberInputStream已过时。此类错误假定字节能充分表示字符。