java中的输入输出流该怎么理解

2024-05-13

1. java中的输入输出流该怎么理解

 数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。对数据读取程序来说,看不到数据流在写入时的分段情况,每次可以读取其中的任意长度的数据,但只能先读取前面的数据后,再读取后面的数据。不管写入时是将数据分多次写入,还是作为一个整体一次写入,读取时的效果都是完全一样的。       “流是磁盘或其它外围设备中存储的数据的源点或终点。”    在电脑上的数据有三种存储方式,一种是外存,一种是内存,一种是缓存。比如电脑上的硬盘,磁盘,U盘等都是外存,在电脑上有内存条,缓存是在CPU里面的。外存的存储量最大,其次是内存,最后是缓存,但是外存的数据的读取最慢,其次是内存,缓存最快。这里总结从外存读取数据到内存以及将数据从内存写到外存中。对于内存和外存的理解,我们可以简单的理解为容器,即外存是一个容器,内存又是另外一个容器。那又怎样把放在外存这个容器内的数据读取到内存这个容器以及怎么把内存这个容器里的数据存到外存中呢?     在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:         标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流等等,java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。将数据冲外存中读取到内存中的称为输入流,将数据从内存写入外存中的称为输出流。    流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。

java中的输入输出流该怎么理解

2. 详讲一下java中的输入输出流

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

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

3. 求教java输入流问题

相信很多Java初学者在用Scnnner的时候会因为nextInt(),next(),nextLine()等出现bug。
我们先来看一段代码:


输入输出结果:


本想输入三次,将第一个整数存在变量m,下一个字符串存在str1,下一行字符串存在str2;
然而从结果来看,似乎跳过了in.nextLine();无法达到预期效果。
如果你想学习Java可以来这个群,首先是二二零,中间是一四二,最后是九零六,里面有大量的学习资料可以下载。
再来看看下一个I/O例子:


容易看出,str2储存了“ rty”,原因便是in.next()只读取了空格之前的数据,之后的in.nextLine()读取了包括空格在内的之后一整行数据。



在in.next()之后添加一个in.nextLine()把'\n'也读取就可以达到预期输入效果了。
三者同时使用的时候in.next()与in.nextInt()只会读取空格之前的数据,之后的会由in.nextLine()读取,根据需求,有时候可以都用in.nextLine(),之后再进行类型转换。或者搞清楚程序运行步骤,理清这几个输入之间的先后关系,在合适的位置添加一个in.nextLine()也可以解决问题。

求教java输入流问题

4. 输入流的java的输入流

当然,我们经常想做的一件事情是将格式化的输出打印到控制台,但那已在第5章创建的com.bruceeckel.tools中得到了简化。  第1到第4部分演示了输入流的创建与使用(尽管第4部分展示了将输出流作为一个测试工具的简单应用)。  1.缓冲的输入文件  为打开一个文件以便输入,需要使用一个FileInputStream,同时将一个String或File对象作为文件名使用。为提高速度,最好先对文件进行缓冲处理,从而获得用于一个BufferedInputStream的构建器的结果句柄。为了以格式化的形式读取输入数据,我们将那个结果句柄赋给用于一个DataInputStream的构建器。DataInputStream是我们的最终(final)对象,并是我们进行读取操作的接口。  在这个例子中,只用到了readLine()方法,但理所当然任何DataInputStream方法都可以采用。一旦抵达文件末尾,readLine()就会返回一个null(空),以便中止并退出while循环。  “Strings2”用于聚集完整的文件内容(包括必须添加的新行,因为readLine()去除了那些行)。随后,在本程序的后面部分中使用s2。最后,我们调用close(),用它关闭文件。从技术上说,会在运行finalize()时调用close()。而且我们希望一旦程序退出,就发生这种情况(无论是否进行垃圾收集)。然而,Java1.0有一个非常突出的错误(Bug),造成这种情况不会发生。在Java1.1中,必须明确调用System.runFinalizersOnExit(true),用它保证会为系统中的每个对象调用finalize()。然而,最安全的方法还是为文件明确调用close()。  2.从内存输入  这一部分采用已经包含了完整文件内容的Strings2,并用它创建一个StringBufferInputStream(字串缓冲输入流)——作为构建器的参数,要求使用一个String,而非一个StringBuffer)。随后,我们用read()依次读取每个字符,并将其发送至控制台。注意read()将下一个字节返回为int,所以必须将其造型为一个char,以便正确地打印。  3.格式化内存输入  StringBufferInputStream的接口是有限的,所以通常需要将其封装到一个DataInputStream内,从而增强它的能力。然而,若选择用readByte()每次读出一个字符,那么所有值都是有效的,所以不可再用返回值来侦测何时结束输入。相反,可用available()方法判断有多少字符可用。下面这个例子展示了如何从文件中一次读出一个字符:  //:TestEOF.java  //Testingfortheendoffilewhilereading  //abyteatatime.  importjava.io.*;  publicclassTestEOF{  publicstaticvoidmain(String[]args){  try{  DataInputStreamin=  newDataInputStream(  newBufferedInputStream(  newFileInputStream("TestEof.java")));  while(in.available()!=0)  System.out.print((char)in.readByte());  }catch(IOExceptione){  System.err.println("IOException");  }  }  }///:~注意取决于当前从什么媒体读入,avaiable()的工作方式也是有所区别的。它在字面上意味着“可以不受阻塞读取的字节数量”。对一个文件来说,它意味着整个文件。但对一个不同种类的数据流来说,它却可能有不同的含义。因此在使用时应考虑周全。  为了在这样的情况下侦测输入的结束,也可以通过捕获一个违例来实现。然而,若真的用违例来控制数据流,却显得有些大材小用。  4.行的编号与文件输出  这个例子展示了如何LineNumberInputStream来跟踪输入行的编号。在这里,不可简单地将所有构建器都组合起来,因为必须保持LineNumberInputStream的一个句柄(注意这并非一种继承环境,所以不能简单地将in4造型到一个LineNumberInputStream)。因此,li容纳了指向LineNumberInputStream的句柄,然后在它的基础上创建一个DataInputStream,以便读入数据。  这个例子也展示了如何将格式化数据写入一个文件。首先创建了一个FileOutputStream,用它同一个文件连接。考虑到效率方面的原因,它生成了一个BufferedOutputStream。这几乎肯定是我们一般的做法,但却必须明确地这样做。随后为了进行格式化,它转换成一个PrintStream。用这种方式创建的数据文件可作为一个原始的文本文件读取。  标志DataInputStream何时结束的一个方法是readLine()。一旦没有更多的字串可以读取,它就会返回null。每个行都会伴随自己的行号打印到文件里。该行号可通过li查询。  可看到用于out1的、一个明确指定的close()。若程序准备掉转头来,并再次读取相同的文件,这种做法就显得相当有用。然而,该程序直到结束也没有检查文件IODemo.txt。正如以前指出的那样,如果不为自己的所有输出文件调用close(),就可能发现缓冲区不会得到刷新,造成它们不完整。

5. java输入输出流的本质是什么?

Java输入输出流的本质是I/O操作,是指使用Java进行输入输出操作。Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。
流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件、内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。
Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。Java中其他多种多样变化的流均是由它们派生出来的。在这其中InputStream和OutputStream在早期的Java版本中就已经存在了,它们是基于字节流的,而基于字符流的Reader和 Writer是后来加入作为补充的。

java输入输出流的本质是什么?

6. 小白求助,java输入流问题

这个用到java io的知识:
Java.io包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。
Java.io包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。
一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。
Java为I/O提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。
但本节讲述最基本的和流与I/O相关的功能。我们将通过一个个例子来学习这些功能。
输入:
Java的控制台输入由System.in完成。
为了获得一个绑定到控制台的字符流,你可以把System.in包装在一个BufferedReader 对象中来创建一个字符流。
下面是创建BufferedReader的基本语法:
BufferedReader br = new BufferedReader(new 
                      InputStreamReader(System.in));

BufferedReader对象创建后,我们便可以使用read()方法从控制台读取一个字符,或者用readLine()方法读取一个字符串。
实例:
// 使用 BufferedReader 在控制台读取字符

import java.io.*;

public class BRRead {
   public static void main(String args[]) throws IOException
   {
      char c;
      // 使用 System.in 创建 BufferedReader 
      BufferedReader br = new BufferedReader(new 
                         InputStreamReader(System.in));
      System.out.println("Enter characters, 'q' to quit.");
      // 读取字符
      do {
         c = (char) br.read();
         System.out.println(c);
      } while(c != 'q');
   }
}

7. java.io的Java流输入输出原理

Java把这些不同来源和目标的数据都统一抽象为数据流。Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流。 按流向分:输入流: 程序可以从中读取数据的流。输出流: 程序能向其中写入数据的流。按数据传输单位分:字节流: 以字节为单位传输数据的流字符流: 以字符为单位传输数据的流按功能分:节点流: 用于直接操作目标设备的流过滤流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。 JDK所提供的所有流类位于java.io包中,都分别继承自以下四种抽象流类。InputStream:继承自InputStream的流都是用于向程序中输入数据的,且数据单位都是字节(8位)。OutputStream:继承自OutputStream的流都是程序用于向外输出数据的,且数据单位都是字节(8位)。Reader:继承自Reader的流都是用于向程序中输入数据的,且数据单位都是字符(16位)。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  已过时。此类错误假定字节能充分表示字符。

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

8. JAVA的输入输出流是指的什么啊?

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

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

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



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

  在这四个抽象类中,InputStream和Reader定义了完全相同的接口:
int read()
int read(char cbuf[])
int read(char cbuf[], int offset, int length)

  而OutputStream和Writer也是如此:
int write(int c)
int write(char cbuf[])
int write(char cbuf[], int offset, int length)

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

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

import java.io.*;

    public class IOStreamDemo {

          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());

               //2. 这是从文件中逐行读入数据

               BufferedReader in = new BufferedReader(new FileReader("IOStreamDemo.java"));
               String s, s2 = new String();
               while((s = in.readLine())!= null)
                          s2 += s + "\n";
               in.close();

               //3. 这是从一个字符串中逐个读入字节
               StringReader in1 = new StringReader(s2);
               int c;
               while((c = in1.read()) != -1)
                          System.out.print((char)c);

               //4. 这是将一个字符串写入文件
               try {
                          BufferedReader in2 = new BufferedReader(new StringReader(s2));
                          PrintWriter out1 = new PrintWriter(new BufferedWriter(new FileWriter("IODemo.out")));
                          int lineCount = 1;
                          while((s = in2.readLine()) != null )
                                     out1.println(lineCount++ + ": " + s);
                          out1.close();
               } catch(EOFException e) {
                          System.err.println("End of stream");
               }
          }
    } 

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

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

  这里的sz是指定缓冲区的大小。

  它的基本方法:
void close() //关闭流

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

import java.io.*;

public class Redirecting {

       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")));
              System.setIn(in);
              System.setOut(out);

              BufferedReader br = new BufferedReader( new InputStreamReader(System.in));
              String s;
              while((s = br.readLine()) != null)
                     System.out.println(s);
              out.close();
              System.setOut(console);
      }
}

  在这里java.lang.System的静态方法
static void setIn(InputStream in)
static void setOut(PrintStream out)

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

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

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

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

import java.io.*;
import java.util.*;

public class Logon implements Serializable {

       private Date date = new Date();
       private String username;
       private transient String password;


       Logon(String name, String pwd) {
              username = name;
              password = pwd;
       }


       public String toString() {
              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"));
              o.writeObject(a);
              o.close();

              int seconds = 5;
              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输入输出流有个基本的认识。