`
lindingyu
  • 浏览: 29052 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
文章分类
社区版块
存档分类
最新评论

JAVA输入流和输出流

 
阅读更多

JAVA中的输入流和输出流是装载和运送信息的管道,管道一端接到信息来源,另一端连接信息的目的地。文中分别介绍输入(InputStream)和输出流(OutputStream)

       1、InputStream抽象类,是所有字节输入流的超类,直接继承Object,不能用构造器创建对象,只能通过子类创建对象。


                                                                字节输入流相关类的继承图

        2、FileInputStream类,文件输入流,构造器创建对象时要传入文件对象或文件路径,即把输入流信息源端接到文件上,可以把文件内容读取到流中。常用的方法是read()和read(byte[] b),前者是依次读取每个字节,后者一次性把信息读取到byte数组中。

  3、ByteArrayInputStream类,byte数组输入流,构造器参数是byte数组,与FileInputStream类似,把输入流的信息源端连接到byte数组上,读取byte数组中的内容。常用方法与FileInputStream相同。

       实例1,用FileInputStream/ByteArrayInputStream的两个方法读取信息。

InputStream is = new FileInputStream(File file)//ByteArrayInputStream(byte[] b);
//依次读取每个字节,read()
int i;
while((i=is.read())!=-1){
   System.out.println(i);//打印出读取内容
}
//一并读取到字节数组中,read(byte[])
byte[] b = new byte[is.available];
is.read(b);
String s = new String(b);//将字节数组转换成String
System.out.println(s);

        上述代码分别用read()和read(byte[] b)读取文件//字节数组,是最基础的实例.

 4、FilterInputStream,构造器是protected,故不能通过构造器创建对象,一般使

用其子类对象,嵌套在基本输入流(InputStream)上使用。

       5、BufferedInputStream类是FilterInputStream的子类,为添加了mark,reset功   能。创建对象时会创建一个内部缓冲区数组,在缓冲区中可以操作输入流的内容。

       6、DataInputStream类,FilterInputStream的子类,使用率非常高的输入流嵌套   这个高级管道后,输入流可以读取任何基本类型的数据,readInt()—读取4个字节组成Int返回。其他数据类型以此类推。

       7、ObjectInputStream类,InputStream的子类,重构序列化内容的输入流, 继承DataInput接口,和DataInputStream一样可以读取基本数据类型。另外Object obj = readObject();方法返回obj对象,即返回重构的序列化对象(要先知道序列化文件中对象存储顺序)。一般和ObjectOutputStream一起使用。不能读取普通输入的txt文件,因为ObjectInputStream读取文件要先读取一Header,会导致文件编码出错。(随后的ObjectOutputStream中有实例)

        8、 PipedInputStream类,必须要和PipedOutputStream类一同使用对接两个管道,Piped要在线程中使用,否则会造成单线程堵塞。连接的方法1,构造器中传入参数PipedInputStream pis = new PipedInputStream(PipedOutputStream pos),Out类与此相同,2,连接方法pis.connect(pos)或pos.connect(pis),其中pis和pos分别是PipedInputStream和PipedOutputStream的对象。需要注意的是不能重复连接,即构造器连接了就不要再用connect方法连接,不然会抛出异常。读取/写入方法分别是pis.read(byte[] b)和pos.write(byte[] b)。

  9、SequenceInputStream类,串联多个输入流,依次读取输入流中内容,构造器参数有两种(InputStream s1,InputStream s2)和(Enumeration<InputStream> e),前者连接两个输入流,后者连接多个输入流。需要特别注意的是,虽然Sequence类提供了read(byte[] b)方法,但是该方法每次只能读取一个InputStream中的内容,方法available()返回的是第一个InputStream内容长度。所以,在Sequence中,只能用read()方法依次读取每个字节,再拼接起来。

实例2:串联两个输入流

//SequenceInputStream串联两个输入流
public void SequenceInputStream(){
     try{	
	InputStream is = new FileInputStream(File file);//文件路径也可做参数	
	InputStream is1 = new FileInputStream(File file);
	SequenceInputStream sis = new SequenceInputStream(is,is1);
              //如果用sis.available结果与is.available相同
	     int len = is.available()+is1.available();
	     byte[] b = new byte[len];
	     int c = 0,count=0;
	     while((c=sis.read())!=-1){//依次读取每个字节,并存放在byte[]中
		  b[count] = (byte)c;
		  count++;
		}
		System.out.println("String是: "+new String(b));				
	  }catch(Exception e){e.printStackTrace();}	
	}

   实例3:串联多个输入流,只需对实例2稍作修改

//串联多个输入流
public static void SequenceEnumeration(){
	  try{
		Vector<InputStream> v = new Vector();
		v.addElement(new FileInputStream(File file);
		v.addElement(new FileInputStream(File file);
		v.addElement(new FileInputStream(File file);
		Enumeration<InputStream> e = v.elements();
		SequenceInputStream sis = new SequenceInputStream(e);
		int len=0;
		//长度仍需要依次累加
                for(int i=0;i<v.size();i++){
			len = len+ v.get(i).available();
		}
		byte[] b = new byte[len];
		int c = 0,count=0;
		while((c=sis.read())!=-1){
			b[count] = (byte)c;
			count++;
		}
		System.out.println("String是: "+new String(b));		
	  }catch(Exception e){e.printStackTrace();}
	}

 

       下面介绍输出流,有联合了对应输入流的实例

       1、OutputStream抽象类,是所有字节输出流的超类,有最基本的写入方法write(byte[] b),大多使用其子类。

                                                                             字节输出流相关类的继承图

         2、FileOutputStream类,文件输出流,将输出流中的内容输出到文件中,故构造器参数是文件对象或文件路径,构造器创建对象时就把流管道的输出端连到文件了。输出方法也是write(byte[] b)。但是,写入的文件路径不存在怎么办,路径存在恰好有同名文件夹怎么办?在附件FileOut.rar中有文件环境检测程序(很简单的程序)。

       3、ByteArrayOutputStream类,字节数组输出流,把流中的内容输出到字节数组中。一般与DataOutputStreamObjectOutputStream联合使用,作用就是把信息(基本数据类型或对象)转换成byte[],因为任何信息本质上说都是由字节组成,所以这样是返璞归真,把信息转化成了最本质的字节,信息经过传递,到另外一台主机上后,在用对应的输入流读取,还原信息原貌。

   ByteArrayInputStream和ByteArrayOutputStream处理信息流程图

   实例4:ByteArrayOutputStream和ObjectOutputStream的联合使用

   代码中用上述两个输出流把对象序列化,并转化成字节数组,在用对应的输入流重构被序列化的对象。

   节点对象代码如下:需要注意的是该节点对象必须连接Serializable接口,不然运行ObjectOutputStream会报错。

 

public class Node implements Serializable{
	private String name;//节点名
	private int weight;//权值
	private int d;//度

	public Node(String name,int weight,int d){
		this.name = name;
		this.weight = weight;
		this.d = d;
	}
	//get(),set()方法略
}
     主体代码:
public class ByteArrayOut{
    public static byte[] b;
    //创建一个ArrayList,里面放Node
    public static ArrayList<Node> getList(){
    	ArrayList<Node> list = new ArrayList<Node>();
    	for(int i=0;i<10;i++){
    		Node node = new Node("N"+i,i*2,i+3);
    		list.add(node);
    	}  	
    	return list;
    }   
    //把List中的Node对象放入输出流并转换成了byte[]
	public static byte[] WriteObj(){
	  try{	
		ArrayList<Node> list = getList();
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(os);
		   oos.writeInt(list.size());
		for(int i=0;i<list.size();i++){
		   oos.writeObject(list.get(i));
		}
		byte[] b = os.toByteArray();
		os.flush();
		os.close();
		System.out.println(b.length);
		return b;
	  }catch(Exception e){e.printStackTrace();}
	    return null;	 
	}
	
	public static void AyaByteArray(byte[] b){
	  try{	
		ByteArrayInputStream bis = new ByteArrayInputStream(b);
		ObjectInputStream ois = new ObjectInputStream(bis);
		int len = ois.readInt();
		System.out.println("读取出来的len:"+len);
		ArrayList<Node> li = new ArrayList<Node>();
		for(int i=0;i<len;i++){
			Node node = (Node)ois.readObject();
			li.add(node);
		}
		ois.close();
        //遍历list
		for(int i=0;i<li.size();i++){
			Node node = li.get(i);
			System.out.println("第"+i+"个node,name:"+node.getName()
					+" 度:"+node.getD()+" 权重"+node.getWeight());		
		}				
	  }catch(Exception ef){ef.printStackTrace();}
		
	}
	
	public static void main(String[] args){
		byte[] b = ByteArrayOut.WriteObj();
		ByteArrayOut.AyaByteArray(b);
	}
}
      上述实例完成了对象的序列化,把对象转化成一个一个的字节保存,随后又用保存的字节重构原对象,成功传递对象

 

      4、FilterOutputStream,所有缓冲输出流的父类,构造器是protected,不能创建对象,一般嵌套基本输出流使用。

      5、BufferedOutputStream类,FilterOutputStream的子类,创建对象时提供缓冲区,要嵌套在基本输出流上使用。使用方法write(byte[] b)把字节数组的内容读到输出流的缓冲区。可以实现文件复制。

 

      6、DataOutputStream类,FilterOutputStream的子类,也要嵌套在基本数据流上使用,可以把JAVA中的基本数据类型写入输出流中,如writeInt(Int i),writeUTF(String str)分别将Int,String到写到输出流中,到网络另一端再用对应输入流读取。DataOutputStream经常和ByteArrayOutputStream联合使用,以字节数组形式储存并传输基本数据类型。

      7、ObjectOutputStream类,用特有的writeObj(Object obj)方法把对象读入输入流中,即序列化对象,将其保存。需要时调用ObjectInputStream重构被序列化的对象,与DataOutputStream相似,可以读基本数据类型到数据流。但对于方法writeBytes(String s),ObjectInputStream中没有对应的读取方法(只有readByte(byte b),没有readBytes()),所以使用writeBytes(String s)时要先写入字符串长度,再写入字符串,读取时readByte(byte b)依次读取每个自己,或用writeUTF(String s)方法写入,对应的readUTF(String s)读取。

 

     实例5:ObjectInputStream和ObjectOutputStream的写入和读取。

public class ObjectOut {

	public static void writeObject(){
	 try{	
                FileOutputStream fos = new FileOutputStream("C:\\obj.obj");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeInt(10);
		oos.writeUTF("UTF_str");
		Node node = new Node("name",12,12);
		oos.writeObject(node);
		oos.flush();
		oos.close();
		
	 }catch(Exception e){e.printStackTrace();}
	}
	
	public static void readObject(){
	 try{
		FileInputStream fis = new FileInputStream("C:\\obj.obj");
		ObjectInputStream ois = new ObjectInputStream(fis);
		int i = ois.readInt(); 
		String str1 = ois.readUTF();
		Node node = (Node)ois.readObject();
		System.out.println("int是:"+i+" str1是:"+str1);
		System.out.println("node的name:"+node.getName()
				+" 度:"+node.getD()+" 权重"+node.getWeight());
		 
	 }catch(Exception e){e.printStackTrace();}
	}
	
	public static void main(String[] args){
		ObjectOut.writeObject();
		ObjectOut.readObject();
	}
	
}
       8、PipedOutputStream类,与PipedInputStream连接使用的专属类,构造器参数就是PipedInputStream。或者用方法connect()连接,不能多次连接。另外,Piped输入输出流绝大多数情况下用于多线程,一个线程写入信息,另一个线程读取。如果用单线程,则可能造成通道锁死。

 

     至此,JAVA中字节输入流和输出流经常使用的类介绍完毕。流是传输信息的管道,两端分别连接信息源和目的地,例如,需要读取文件中内容时,用FileInputStream从文件中把信息读出来就行了,需要写入信息到文件中时,就用FileOutputStream把信息写入文件。更多时候,把流管道的一端连接到网络,在网络另一端用对应流接收,就实现网络之间的信息传递。

     写得不好的地方,敬请批评指正。

 

 

 


 

  • 大小: 9.7 KB
  • 大小: 9.6 KB
  • 大小: 9.1 KB
分享到:
评论

相关推荐

    Java 输入流和输出流总结

    Java IO总结

    java 输入输出流

    Java的输入输出流机制是相当强大且灵活的,它提供了多种类型和级别的流来满足不同场景的需求,从基本的字节流到高级的过滤流和对象流,构成了完整的I/O体系。理解和熟练掌握Java的输入输出流对于任何Java开发者来说...

    Java输入输出 Java输入输出

    java java输入输出 java输入流 java输出流 java java输入输出 java输入流 java输出流 java java输入输出 java输入流 java输出流

    实验9 Java输入输出流.doc

    Java输入输出流是Java编程中一个非常重要的概念,主要用于数据的读取和写入操作,包括文本文件和二进制文件。在实验9中,主要目的是理解和掌握I/O流的分类,以及如何进行文本和二进制文件的读写。 I/O流在Java中被...

    JAVA输入输出流实验报告

    通过这两个实验,我们可以了解到Java IO流的基本使用步骤:创建输入流对象,创建对应类型的输出流对象,然后通过读写方法进行数据传输,最后记得关闭流资源以释放系统资源。 此外,Java还提供了更高级的流,如`...

    java中的各种输入流与输出流

    Java中的输入流与输出流是Java I/O体系的重要组成部分,它们是Java程序进行数据传输的基础。在Java中,I/O操作被设计为流(Stream)的形式,流是数据的有序序列,可以是从内存到磁盘、从一个文件到另一个文件、甚至从...

    Java输入流及输出流

    对输入流及输出流的理解可以很好地掌握Java这门语言的学习

    java输入输出流,电子课件

    Java输入输出流是Java编程中不可或缺的部分,它用于应用程序与外部设备之间进行数据交换,比如磁盘、网络、键盘和显示器。I/O流是Java中处理输入和输出的基础框架,它提供了一种抽象的方式来处理不同类型的输入源和...

    JAVA输入输出流详细解读

    ### JAVA输入输出流详细解读 #### I/O类体系与流分类 在JAVA的I/O类体系中,所有的基础IO类都被归置于`java.io`包内,而那些新实现的IO类则分布在以`java.nio`开头的一系列包中。在深入探讨前,我们先来了解`java....

    java中的输入流与输出流

    java中的输入流与输出流java中的输入流与输出流

    java的输入输出流

    Java的输入输出流(Input/Output Stream)是Java.io包的核心组成部分,用于处理数据的传输,无论是从硬盘、网络还是内存。Java提供了两种主要类型的流:字节流和字符流。 字节流处理的是单个字节的数据,分为输入流...

    Java 输入与输出流操作

    下面将详细阐述Java输入与输出流的相关知识点。 1. **流的概念**: 流是Java I/O的核心概念,它代表数据的源或目的地。流可以是向文件、内存、网络连接等地方读写数据。Java中的流分为字节流和字符流,字节流处理...

    Java 输入输出流 源码

    Java输入输出流是Java编程语言中的核心概念,用于在程序之间、程序与系统资源之间传输数据。这个主题包括了从磁盘、网络、内存到控制台等不同源和目标的数据读写操作。在这个Java作业中,你将深入理解并实践这一关键...

    JAVa输入输出流程序

    Java输入输出流(IO流)是Java编程语言中处理数据传输的核心部分,它允许程序进行数据的读取和写入操作。在Java中,一切皆为流,输入流用于读取数据,而输出流用于写入数据。这些流可以处理各种类型的数据,包括文本...

    Java学习资料-输入输出流

    Java 输入/输出流是Java程序进行数据传输的关键机制,它允许程序从源(如键盘、文件)接收数据或将数据发送到目的地(如显示器、文件)。Java中的I/O流分为四类:字节流(Byte Streams)和字符流(Character Streams...

    java输入输出流的简单例子

    Java输入输出流是Java IO(Input/Output)体系的基础,它是Java处理数据传输的核心机制。在Java中,一切皆为对象,输入输出流也不例外。Java的输入输出流分为字节流和字符流两大类,每类又分别有输入流和输出流四种...

    java输入输出流.ppt

    Java输入输出流(I/O流)是Java编程中不可或缺的一部分,它主要用于程序与外部资源之间的数据传输。在Java中,I/O流的概念被用来抽象各种输入源和输出目标,包括键盘、显示器、文件、网络连接等。I/O流的设计遵循...

    java输入输出流与文件处理

    ### Java输入输出流与文件处理 #### 重要概念与基础知识 **输入输出流与文件处理**在编程领域占据着核心地位,特别是在Java中,通过`java.io`包提供了丰富的类和接口来支持输入输出操作。这包括从键盘读取用户输入...

    java输入输出流的两种写法

    Java 输入输出流是Java编程语言中处理数据传输的基础机制...以上就是Java输入输出流的基本概念和常见写法。在实际应用中,根据需求选择合适的流类型,并合理利用缓冲、对象序列化等特性,可以提高程序性能并简化代码。

Global site tag (gtag.js) - Google Analytics