InputStream——关于Java中对流的操作


转载自:http://yk3288.blog.hexun.com/35720129_d.html

征服我Java的软肋,InputStream,我不怕你了! 

天命使然,一直在学Java,虽然有好几次都想转型,用点C++或是.net之类的,可以说是博采众长吧,但一直没有什么机会,反而,在各种各样的找工作和培训中反复的接触Java,Oracle和JavaScript,自认对Java比较熟悉,可是只要一考,操作中总会出现一些让人想不到的问题,丢人。而对于Java中文件的操作,我更是摸不清头脑,因为平时对文件的操作就不多,加之里面有对流的操作,更是把我弄得晕头转向,弄不出一个所以然。所以每次要写对文件的操作,我就会把自己的那本破旧好多年的笔记本拿出来,一个一个字符的往电脑里敲,这个输入流套那个输出流,完成预想的功能。想当初,这几段我赖以生存的代码还是在上课的时候,拼命在老师来回切换PPT的时候,飞速抄写下来的。但也许只关注实现的步骤了,没有听清楚老师所讲的原理,结果就成了这个样子,写了这么些年的Java代码,却从来不知道这些流到底是怎么回事。这也就是我水平不高的原因之一,讲原理说不出个所以然;论实战,到那都要仰仗自己的那个破旧小本本。

现在又在写Java代码,又在翻几年前的旧账,从同学那找来一本《INTRODUCTION TO PROGRAMMING USING JAVA  --AN OBJECT-ORIENTED APPROACH SECTION EDITION》(《Java 面向对象程序设计(第二版)(影印版)》),清华大学出版社出版的,都是英文,恰好公司现在都是英文字符,于是乎就开始翻这本书,本来无所谓Java知识的,我就当是复习,主要是锻炼锻炼读英语而已,可看了几页,发现还是有点收获,特别是对文件操作的这部分,还有对流的操作的介绍,读完之后,终于对流有了一定的了解,觉得收获挺大,于是就把它整理出来,虽然大部分都是对原书的照搬,可加一点自己的理解,就当时我的原创博文吧!

      3.8 Introdution to Input

先说一说Input和Output把,以前老是分不清这两个东西是怎么回事,主要是没有把对象弄清楚,只要把以电脑为主角,那么一切就好办了,对于计算机来说,Input就是把数据读到内存里,而Output就是把数据从内存中写出来了,而具体的从那里读,写到哪里去,就看初始化流时使用的对象了,即new的时候在构造函数里写的参数。

A computer’s input and output mechanism rely on many specialized pieces of hardware and software that must be carefully coordinated. As in any other large complex project, a reliable input/output system must be structured so that responsibilities are clearly assigned and coordination channels universally agreed on. While every kind of input and output is fundamentally about transmitting data (e.g. from the keyboard to the processor, or from the processor to disk storage), each different “flavor” (e.g. input from the keyboard versus input from the web) has particular characteristics that require the data to be processed differently. We will see that Java’s Input and output classes have been carefully designed to reflect relationships.

从书中的描述可以看出,其输入的使用难度在于输入设备的不同,因而要对不同的输入的数据格式作不同的处理。其实,现在我写的input大致只有两种,一种是从控制台输入的,也就是keyboard输入,这对于Java来说并不是一件难事,因为对一个计算机系统而言,一个控制台输入设备大多已经绑定在操作系统中了,Java只需找到接口,直接使用就可以了,因此Java对于控制台的输入有许多实现好的类,可以直接使用,如Scanner,System. in等,对于控制台的输入,后面会着重介绍的;而另一种就是文件输入,对于该种input,Java程序没有办法直接绑定为对应文件,所以只能由程序员来读写;而其他的输入设备,输入流,使用大体就和文件差不多了。

Overview of File Input: from Disk to Program

We’ll see that this transfer requires the efforts of a handful of Java classes that take responsibility for different phases of the transfer process. Figure 3.4 diagrams the process of the reading text data; the three unlabeled rectangles represent classes whose names and responsibilities we will discuss in the text few sections. The first step is to read data from the disk directly; this data is passed on a steam of bytes(that is, as the sequence of  numerical values—not text).Next , these characters are then combined to produce a String.

Raw data  ->Stream of the bytes   ->    stream of chars -> Stirng 

Figure 3.4 Overview of the file Input process

其实,一看这个图就简单了,按照这个图的意思,就是从文件中读出的数据,先是一个bytes流,然后在将其变成char流,最后就可以变成String,当然这就是我们最熟悉的数据类型,怎么处理就是我们程序员说了算的。可是为什么要这么变呢?不能读出来就是String类型吗?这样多简单呀!于是乎书里就从计算机的编码方式开始讲了。

From byte to char: The Case of for Unicode

Originally, most computer system recognized text based only on Latin characters—the English alphabet, punctuation, and a handful of European symbols. This character set, limited to about 120 characters, become known as the American Standard Code for Information Interchage (ASCII) character set; this was standard for many years. The amount of memory required to hold a single ASCII character become known as a byte. One of the uses pf the Java’s byte primitive type is to hold ASCII character values. Recall that byte value can store integer value from -128 to 127; ASCII values are represented by assigning character values to the number -128 to 127.

读到这的时候,真为自己汗颜,玩了这几年计算机,对于ASCII码,今天总算才是知道了这是五个字母,而不是自己一直认为的四个字母,原来我一直以为倒数最后两个字母是阿拉伯数字Ⅱ,还自以为是的认为这种编码方式是某种原先版本的改进型呢!!!

As the Internet proliferated, it became desirable to allow representations of other languages (such as Arabic, Hebrew, Chinese, and so forth) and their associated alphabets. An expanded character set, known as Unicode, was introduced to accommodate a wide variety of the palpable (including all characters in the ASCII set as well). Because there are many more possible Unicode characters than ASCII characters, a Unicode character requires a larger amount of memory. The Java primitive type char is used to contain Unicode characters values, and the Java String class uses Unicode-based chars to store the characters that compose a String.

这个时候,我突然想到了一个问题,我经常会忘了一些字符的ASCII码值。怎么办?用程序打出来呀,于是:

     Char c = ‘A’;

     System.out.println(c);

可是,我用这个方法永远打不出来,我想要的值,一直是永远不变的‘A’,这可把我郁闷坏了,为什么出不来呢?有些时候,事情还是要从小事想起,现在好了,终于明白是怎么回事了,下回想要知道ASCII码值,没必要再猜了。另外,对于Java支持中文,我理解的就更深刻了,没必要死记硬背什么Unicode,支持中文什么的,16位的类型了。  

Despite the attractiveness of the Unicode, most disk files are still composed of the bytes representing ASCII characters. These file may have been created by editor word processors, or other programs, designed before Unicode was introduced that can manipulate only ASCII files. Alternatively, because ASCII takes up less room than Unicode, a file may be saved in ASCII for the sake of space efficiency. In either case, ASCII-based files contain their data as bytes.

这就解释了我们为什么读文件的时候不能直接是String类型的,而必须是bytes流,然后在通过各种流进行转换。接下来,我们学的就是Java中的几个关于流的类就行了。

3.9 The File Input Process

Class File: Accessing Disk File Information

对于File这个类,我没有什么可说的,用的比较多,无非就new一个对象,然后在eclipse中按点,按联想的方法进行选择使用就可以了。不过File有个方法,以前到一直没有注意过,不知道以后有没有机会用一下:

      public boolean renameTo(File dest)

Class FileInputStream: Reading bytes from a Disk File

While the File class provides access to information about the file residing on disk, it provides no support for transferring data from the file into memory. Classes that support the behavior of transferring data from some source into memory are categorized as input stream. Java provides several such classes; for reading data from disk files, Java provides the FileInputStream class. A FileInputStream object is created by providing it with information about the file to be read in. This is done by passing a File object as argument to the constructor:

      File file = new File(String filePath);

      FileInputStream fis = new FileInputStream(file);

The class also provides another constructor that a filePath( as a String) that provides a convenient shortcut for the two statement:

      FileInputStream fis = new FileInputStream(“filePath”);

这是第一步,将文件数据变成了bytes流,想怎么用就是程序员说了算了,当然,它只能表示几个简单的ASCII码,所以我们还要继续努力将它变成char流,这样对付中文就有办法了:

Class InputSteamReader: Tranforing bytes to chars

As we discussed in the overview, Java’s char type supports the Unicode character set rather the limited ASCII character set. Because many files stored in the disk are still represented in ASCII (that is , as Bytes), Java provides the InputStreamReader class, whose responsibility it is to transform a stream of Unicode chars suitable for processing in a java application.

We create an InputStrem object by passing as an argument to its constructor an input strem object whose bytes we wish to turn into chars. With out FileInputStream fis object of the previous section, we can write:

InputStreamReader isr = new InputStreamReader(fis);

从这个类的定义和作用来看,就不难知道为什么他的构造函数中要添加这么一个流对象了,理解起来就不是那么困难了,使用isr的方法我们就可以得到一个char流了。接下来,我们把他写成我们最熟悉的String类型,以便我们进行使用。

Class BufferReader:From Stream of the char to String

While an InputStramReader object does produce data in a form usable by a Java Program (a sequence of character), this is not necessary the form that is easier for us to use as programmer. Usually we view text files not as sequences of character but as sequences of lines. The BufferedReader class is responsible for transforming a stream of chars (as provided by an InputStreamReader) into a sequence of String.

Creating a new BufferReader object object is very similar to creating the other objects in the chain we’ve been building : We pass an InputStreamReader object to its bonstructor, like this:

     BufferedReader br = new BufferedReader(isr);

The BuffferedReader class provides a method, redline(), that return a String corresponding to one whole line of the text in the associated file. We can then manipulate this String using any of the String any of String methods we’ve studied already.

这下大功告成了,终于见到了我们熟悉的Stirng类型返回了,不过使用的时候可用注意,注意读的文件是什么类型的,二进制文件,如图像,音频什么的,当然就没有什么必要读这么多,一个byte流就可以全部搞定了。

书中还有几个例子:

      BufferedReader br = new BufferedReader(

                              New InputStremReader(

                                   New FileInputStream(File)));

      String line = br.readLine();

可惜的是,在文中的例子,因为文中的知识还没介绍全,所以对所有的流都没有关闭,这对于初学者可要相当的注意的。

3.10 KeyBoard Input

相比之下,键盘输入就比较好了,因为输入设备与计算机系统相统一,java很容易就可以得到一个相同的稳定的流来获取数据,想Scanner就是一个封装好的类,构造的时候,往里传一个System.in的InputStream类型参数,就可以直接使用它的对应方法读取从控制台输入的数据,我常用的就是readLine()方法,返回的Stirng类型,很容易就可以被我们所处理。当然想要自己来写这些类也很简单,书中就详细介绍了这部分的知识。和文件输入的唯一不同也就是bytes流获取的不同而已。

We said earlier that file input was the most complicated form of input; let’s look now at obtain input form the keyboard. This is of input is a bit simpler only because we don’t have to expend effort identifying which of many input sources we wish to use – while there are many possible data files, there is only one keyboard. Moreover , just as java makes output  to the monitor easy for us by predefined System.out, keyboard input is represented by the predefined object System.in.

Java treats the keyboard as a stream if the bytes , which means that System.in is an InputStream oject (though not a FileInputStream object, because the keyboard is not a file). We can apply familiar techniques to this object in order to create a BufferedReader object corresponding to the keyboard (see Figure 3.6):

      BufferedReader br = new BufferedReader(

                   New InputStreamReader(System.in) )

  

                          Keyboard  -> Stream of the bytes  (System.in,Java Provided) ->

                                     (Programer provided)    stream of chars -> Stirng 

Figure 3.6 Overview of the keyboard input

这个图和FileInput那个图基本没有什么区别,只要了解了FileInput的过程,其他的没有什么问题,况且这个过程的前一大部分已经由Java完成了,我们所做的无非是后面的部分,实际上,通常我们都是用JDK已经封装好的Scanner类了。

当然输入设备不仅仅有这么多,在数据库中,或者其他设备也有对流的操作,但只要了解了这些流的操作,一切都没有问题。我在看书的过程中,还发现了一个比较有意思的数据源,特地也摘抄一部分如下:

3.12 Network Computing: An Introduction

Network Input

Reading input from the World Wide Web resources in a Java program is as simple as reading input from a disk file. Again, the key is to obtain an InputStream that provides the fundamental behavior a stream of input (in this case from Web site)

The Java class library provides a class ,URL, to model URLs, The URL class provides a constructor that takes a String argument (the URL as we would write it) as follows:

         URL url = new URL(“www.hexun.com”);

It also provides a method , openStream(), which takes no arguments but returns an InputStream, as follow:

InputStream ins = url.openStream();

其实从Web获取数据的关键就是得到流对象,这下一切搞定,没有什么问题了,剩下的步骤就是文件读取一样了。

This methods does quite a bit of work behind the scenes: It sets up communication software on your site, imitates contact with the remote machine, waits for a response, sets up the connection, and then constructs an InputStream object to model the connection, returning a reference to this object.

Once we have an InputStream like this, we are in business: we can easily construct a BufferedReader object(as we did for file and keyboard) and then read from the remote resource, as follow:

        InputStreamReader isr = new InputStreamReader(ins);

        BufferedReader br = new BufferedReader(isr);

        String str = br.readLine();

 

这就是书中关于Input的介绍,不知道各位读者看完之后又没有什么收获,反正我觉得自己进步挺大,以后见到流在业不会头疼了,类似Input,对于Output,常用的几个流对象也一样,如FileOutputStream,构造时需要一个文件对象;PrintStream,通过接收一个bytes流,就可以得到一个character流,剩下的要怎么用,就是咱们程序员说的算了,难道不是吗?

 

注:由于图片上传没有成功,所以影响了各位读者,敬请原谅!!!


也可以参考代码:java通过InputStream读取和写入文件操作实例代码,下载地址:http://www.zuidaima.com/share/1758442014903296.htm

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值