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类,字节数组输出流,把流中的内容输出到字节数组中。一般与DataOutputStream或ObjectOutputStream联合使用,作用就是把信息(基本数据类型或对象)转换成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把信息写入文件。更多时候,把流管道的一端连接到网络,在网络另一端用对应流接收,就实现网络之间的信息传递。
写得不好的地方,敬请批评指正。
相关推荐
Java IO总结
Java的输入输出流机制是相当强大且灵活的,它提供了多种类型和级别的流来满足不同场景的需求,从基本的字节流到高级的过滤流和对象流,构成了完整的I/O体系。理解和熟练掌握Java的输入输出流对于任何Java开发者来说...
java java输入输出 java输入流 java输出流 java java输入输出 java输入流 java输出流 java java输入输出 java输入流 java输出流
Java输入输出流是Java编程中一个非常重要的概念,主要用于数据的读取和写入操作,包括文本文件和二进制文件。在实验9中,主要目的是理解和掌握I/O流的分类,以及如何进行文本和二进制文件的读写。 I/O流在Java中被...
通过这两个实验,我们可以了解到Java IO流的基本使用步骤:创建输入流对象,创建对应类型的输出流对象,然后通过读写方法进行数据传输,最后记得关闭流资源以释放系统资源。 此外,Java还提供了更高级的流,如`...
Java中的输入流与输出流是Java I/O体系的重要组成部分,它们是Java程序进行数据传输的基础。在Java中,I/O操作被设计为流(Stream)的形式,流是数据的有序序列,可以是从内存到磁盘、从一个文件到另一个文件、甚至从...
对输入流及输出流的理解可以很好地掌握Java这门语言的学习
Java输入输出流是Java编程中不可或缺的部分,它用于应用程序与外部设备之间进行数据交换,比如磁盘、网络、键盘和显示器。I/O流是Java中处理输入和输出的基础框架,它提供了一种抽象的方式来处理不同类型的输入源和...
### JAVA输入输出流详细解读 #### I/O类体系与流分类 在JAVA的I/O类体系中,所有的基础IO类都被归置于`java.io`包内,而那些新实现的IO类则分布在以`java.nio`开头的一系列包中。在深入探讨前,我们先来了解`java....
java中的输入流与输出流java中的输入流与输出流
Java的输入输出流(Input/Output Stream)是Java.io包的核心组成部分,用于处理数据的传输,无论是从硬盘、网络还是内存。Java提供了两种主要类型的流:字节流和字符流。 字节流处理的是单个字节的数据,分为输入流...
下面将详细阐述Java输入与输出流的相关知识点。 1. **流的概念**: 流是Java I/O的核心概念,它代表数据的源或目的地。流可以是向文件、内存、网络连接等地方读写数据。Java中的流分为字节流和字符流,字节流处理...
Java输入输出流是Java编程语言中的核心概念,用于在程序之间、程序与系统资源之间传输数据。这个主题包括了从磁盘、网络、内存到控制台等不同源和目标的数据读写操作。在这个Java作业中,你将深入理解并实践这一关键...
Java输入输出流(IO流)是Java编程语言中处理数据传输的核心部分,它允许程序进行数据的读取和写入操作。在Java中,一切皆为流,输入流用于读取数据,而输出流用于写入数据。这些流可以处理各种类型的数据,包括文本...
Java 输入/输出流是Java程序进行数据传输的关键机制,它允许程序从源(如键盘、文件)接收数据或将数据发送到目的地(如显示器、文件)。Java中的I/O流分为四类:字节流(Byte Streams)和字符流(Character Streams...
Java输入输出流是Java IO(Input/Output)体系的基础,它是Java处理数据传输的核心机制。在Java中,一切皆为对象,输入输出流也不例外。Java的输入输出流分为字节流和字符流两大类,每类又分别有输入流和输出流四种...
Java输入输出流(I/O流)是Java编程中不可或缺的一部分,它主要用于程序与外部资源之间的数据传输。在Java中,I/O流的概念被用来抽象各种输入源和输出目标,包括键盘、显示器、文件、网络连接等。I/O流的设计遵循...
### Java输入输出流与文件处理 #### 重要概念与基础知识 **输入输出流与文件处理**在编程领域占据着核心地位,特别是在Java中,通过`java.io`包提供了丰富的类和接口来支持输入输出操作。这包括从键盘读取用户输入...
Java 输入输出流是Java编程语言中处理数据传输的基础机制...以上就是Java输入输出流的基本概念和常见写法。在实际应用中,根据需求选择合适的流类型,并合理利用缓冲、对象序列化等特性,可以提高程序性能并简化代码。