当前位置:  编程技术>移动开发
本页文章导读:
    ▪怎么正确使用Java I/O输出和读入数据        如何正确使用Java I/O输出和读入数据    如何正确使用Java I/O输出和读入数据 (转)前言Java的I/O系统使用“流”来处理各种类型的输入、输出数据的任务。在传输数据的过程中,我们需要.........
    ▪ 用intent兑现Activity跳转        用intent实现Activity跳转    利用intent实现Activity的关键代码:    //假设有两个Activity:Activity01和Activity02    button.setOnClickLisener(new Button.onClickLisener(){    @Override    public void onClick(View v).........
    ▪ 关于一进入程序就自动执行Spinner的OnItemSelectedListener的有关问题解决方法       关于一进入程序就自动执行Spinner的OnItemSelectedListener的问题解决办法 解决办法就是添加一句话   mySpinner.setSelection(0, true);   这句话的作用是预设一个一开始的选择默认值。如果不设置的话.........

[1]怎么正确使用Java I/O输出和读入数据
    来源: 互联网  发布时间: 2014-02-18
如何正确使用Java I/O输出和读入数据
   如何正确使用Java I/O输出和读入数据

(转)
前言
Java的I/O系统使用“流”来处理各种类型的输入、输出数据的任务。
在传输数据的过程中,我们需要判断流中传输的数据何时结束这样的问题。这对于我们正确地发送和接收数据是非常关键的。
如何判断流的末尾和批数据的末尾,是解决这个问题的关键。本文就是要深入地分析Java I/O输入输出的工作原理,保证我们能够正确地执行数据的发送和接收!
Java I/O任务
一个Java的I/O任务,创建了一个连接两个系统的数据传输管道。它分为两个部分:输入流和输出流。
输入流,指的是通过流向本系统的内存传输数据的单向数据传输通道。
输出流,指的是通过流向外部系统传输数据的单向数据传输通道。

输入流

InputStream类是表示字节输入流的所有类的超类。这是一个抽象类。
我们看它提供的读入数据的方法:
read
public abstract int read()
                  throws IOException
从输入流读取下一个数据字节。返回 0 到 255 范围内的 int 字节值。如果因已到达流末尾而没有可用的字节,则返回值 -1。在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。
子类必须提供此方法的一个实现。
返回:
下一个数据字节,如果到达流的末尾,则返回 -1。
抛出:
IOException - 如果发生 I/O 错误。

--------------------------------------------

read
public int read(byte[] b)
         throws IOException
从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。
如果 b 为 null,将抛出 NullPointerException。如果 b 的长度为 0,则无字节可读且返回 0;否则,要尝试读取至少一个字节。如果因为流位于文件末尾而没有可用的字节,则返回值 -1;否则,至少可以读取一个字节并将其存储在 b 中。
将读取的第一个字节存储在元素 b[0] 中,下一个存储在 b[1] 中,依次类推。读取的字节数最多等于 b 的长度。让 k 为实际读取的字节数;这些字节将存储在元素 b[0] 至 b[k-1] 之间,不影响元素 b[k] 至 b[b.length-1]。
如果不是因为流位于文件末尾而无法读取读取第一个字节,则抛出 IOException。特别是,如果输入流已关闭,则抛出 IOException。
类 InputStream 的 read(b) 方法的效果等同于:
read(b, 0, b.length)
参数:
b - 读入数据的缓冲区。
返回:
读入缓冲区的总字节数,如果由于流末尾已到达而不再有数据,则返回 -1。
抛出:
IOException - 如果发生 I/O 错误。
NullPointerException - 如果 b 为 null。
另请参见:
read(byte[], int, int)

--------------------------------------------

read
public int read(byte[] b,
                int off,
                int len)
         throws IOException
将输入流中最多 len 个数据字节读入字节数组。尝试读取多达 len 字节,但可能读取较少数量。以整数形式返回实际读取的字节数。
在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。
如果 b 为 null,则抛出 NullPointerException。
如果 off 为负,或 len 为负,或 off+len 大于数组 b 的长度,则抛出 IndexOutOfBoundsException。
如果 len 为 0,则没有字节可读且返回 0;否则,要尝试读取至少一个字节。如果因为流位于文件末尾而没有可用的字节,则返回值 -1;否则,至少可以读取一个字节并将其存储在 b 中。
将读取的第一个字节存储在元素 b[off] 中,下一个存储在 b[off+1] 中,依次类推。读取的字节数最多等于 len。让 k 为实际读取的字节数;这些字节将存储在元素 b[off] 至 b[off+k-1] 之间,其余元素 b[off+k] 至 b[off+len-1] 不受影响。
在任何情况下,元素 b[0] 至 b[off] 和元素 b[off+len] 至 b[b.length-1] 都不会受到影响。
如果不是因为流位于文件末尾而无法读取第一个字节,则抛出 IOException。特别是,如果输入流已关闭,则抛出 IOException。
类 InputStream 的 read(b, off, len) 方法只重复调用方法 read()。如果第一个这样的调用导致 IOException,则从对 read(b, off, len) 方法的调用中返回该异常。如果对 read() 的任何后续调用导致 IOException,则该异常会被捕获并将发生异常时的位置视为文件的末尾;到达该点时读取的字节存储在 b 中并返回发生异常之前读取的字节数。建议让子类提供此方法的更有效的实现。
参数:
b - 读入数据的缓冲区。
off - 在其处写入数据的数组 b 的初始偏移量。
len - 要读取的最大字节数。
返回:
读入缓冲区的总字节数,如果由于已到达流末尾而不再有数据,则返回 -1。
抛出:
IOException - 如果发生 I/O 错误。
NullPointerException - 如果 b 为 null。
另请参见:
read()


read方法解读
这些方法的核心。实际上就是read()方法。
这个方法的JavaDoc中指出:
“如果因已到达流末尾而没有可用的字节,则返回值 -1。如果因已到达流末尾而没有可用的字节,则返回值 -1。在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。”

1,read方法会在能够返回流中的字节之前,一直阻塞线程。这就是说,read方法是一个低消耗的监听和读取I/O传输的好方法。
这个方法的实现,具有非常高的性能。

2,如果输入流的I/O系统在执行这个read方法时抛出异常,那么显然这个方法会非正常结束,这个也是毫无疑问的。

3,“如果因已到达流末尾而没有可用的字节,则返回值 -1。”
这句话看似没有问题,但实际上有非常大的歧义!什么是流的末尾?只有流的末尾才能返回-1吗?

InputStream类和SocketInputStream类的源码解读
通过查看InputStream类的源码,我发现实际上,流,就好比是双向2车道的高速公路。它传输数据是一批一批的。我把它叫做“批数据”。
假设A=======B两个系统通过一个I/O流来连接。
那么,从B端通向A端的车道,就叫作A的“输入流”。同一条车道,在B这边,叫作B的“输出流”。
同理,从A端通向B端的车道,就叫作A的“输出流”。同一条车道,在B这边,就叫作B的“输入流”。

数据在这条高速公路上,不是一条一条跑的,而是一批一批跑。

OutputStream类,此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。

OutputStream类的write方法,每执行一次,就向这条高速公路上发送了一批数据。OutputStream类的一些子类,它们并不是在每次write()方法执行之后立刻把这批数据发送到数据高速公路上的。而是只有在执行flush()方法之后,才把之前write的多批数据真正地发送到数据通道中。
这样,多个write()方法发送的数据就变为了一批数据了!

通过read()方法读入时,当读完该批数据之后,如果再一次执行read()方法,就会立刻返回-1。
实际上,这是并没有到达流的末尾!仅仅是读完了一批发送的数据而已!

如果我们又一次执行read()方法,那么,如果:
1,流没有结束。也就是说,对面的发送端可能还会发送下一批数据时,就会进入阻塞状态。当前线程暂停,直到读取到输入流中下一批数据的第一个字节。
2,流结束了。也就是说,对面的发送端不再发送任何数据,也即:这条数据通道已经没有用了,这时,可以说“到达流的末尾”了!返回-1。
  
所以,InputStream及其子类的read()方法的注释是不完整的!
Read()方法的注释,应该这么说:
read
public abstract int read()
                  throws IOException
从输入流读取下一个数据字节。返回 0 到 255 范围内的 int 字节值。
如果在读完一批数据后首次调用read()方法,那么返回-1。表示这批数据已经读完了!
如果因已到达流末尾而没有可用的字节,则返回值 -1。在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。
子类必须提供此方法的一个实现。
返回:
下一个数据字节;
如果刚读完一批数据,则返回-1;
如果到达流的末尾,则返回 -1。
抛出:
IOException - 如果发生 I/O 错误。


如何正确使用Java I/O输出和读入数据
明白了Java的I/O流的工作机理和read方法的执行结果,我们就能够正确地使用Java I/O系统输出和读入数据了。

如何分批输出数据
由于read(…)方法是分批读取数据的,所以,我们应该在输出端正确地分批输出数据。
Write(…)方法,然后执行flush()方法能够将多批数据合并成一批数据输出。
尽管OutputStream这个基类的flush()方法是无用的,但是由于我们得到的OutputStream类型的输出对象都是这个类的子类的对象,所以,我们还是应该尽量使用flush()方法强制向输出流中物理输出数据,以避免错误。

如何分批读取数据
    我们常常使用public int read(byte[] b,
                int off,
                int len)
         throws IOException
这个方法来读取一批数据。
查看这个方法的源代码,我们可以发现,它在读取完一批数据时,又执行了一次read()方法,由于前面论述的原因,这个方法立刻返回-1,然后这个方法退出,返回这次读取的字节数。
因此,如果我们要读取一批数据,可以采用如下几种方法:
使用read()判断-1来读完一批数据:
    代码示例:
Int byte;
While((byte=inputStream.read())!=-1 ){
    Byte就是返回的字节。

}
如果读完一批数据后再一次执行read方法,将会立刻返回-1,表示这批数据已经读完。

使用read(byte[] buffer)判断是否返回小于buffer.length或者-1来判断是否读完一批数据
上面那样一个一个字节读取数据比较麻烦,我们通常使用一个字节数组来读取数据。
read(byte[] buffer)方法返回:
1,buffer.length,表示从输入流中读取到的数据塞满了这个字节数组。此时,可能已经读完了这批数据,也可能没有读完这批数据。
    如果刚好读完,那么再执行一次read()方法,就会返回-1,表示这批数据已经读完,而不是表示流已经结束。
2,小于buffer.length。表示读完了该批数据。并且执行了一次read()方法,返回-1,表示这批数据已经读完。
3,-1。这批数据已经读完了。 不可能是表示流已经结束。因为之前就会退出while循环。
   
代码示例:
Byte[] buffer=new byte[1024];
int size=buffer.length;
While(size!=-1 || size>=buffer.length){
Size=inputStream.read(buffer));
将数据读到数组buffer中。
如果读到了-1,或者 读出的数据少于buffer的尺寸,表示已经读完该批数据,不再循环读取数据了!


}


读入一批数据的操作必须对应输出一批数据的操作
读入一批数据的操作必须对应输出一批数据的操作。否则,读入数据的线程会一直阻塞,等待输出端输出下一批数据。
如果对方也需要我们提供输出数据,那么就可能会使整个流的两端的线程互相等待,死锁住。并且这个I/O流也会永远不释放,这样就会使系统的资源耗尽。

后记:
在前两天的工作中,我使用Socket在服务器和客户端执行操作时,出现了死锁的现象。为了找出问题的根源,我仔细查看了InputStream类和SocketInputStream类的源代码。找出了造成输入、输出流误用的原因。
希望这篇文章能够帮助饱受I/O输入、输出流问题困扰的Java程序员!

    
[2] 用intent兑现Activity跳转
    来源: 互联网  发布时间: 2014-02-18
用intent实现Activity跳转
   利用intent实现Activity的关键代码:
    //假设有两个Activity:Activity01和Activity02
    button.setOnClickLisener(new Button.onClickLisener(){
    @Override
    public void onClick(View v)
    {
        //新建一个intent http://www.178zhe.com
        Intent intent = new Intent();
        //指定intent要启动的类
        intent.setClass(Activity01.this, Activity02.class);
        //启动一个新的Activity
        startActivity(intent);
        //关闭当前的Activity
        Activity01.this.finish();
    }
    });

    
[3] 关于一进入程序就自动执行Spinner的OnItemSelectedListener的有关问题解决方法
    来源: 互联网  发布时间: 2014-02-18
关于一进入程序就自动执行Spinner的OnItemSelectedListener的问题解决办法

解决办法就是添加一句话

 

mySpinner.setSelection(0, true);
 

这句话的作用是预设一个一开始的选择默认值。如果不设置的话,将会自动执行OnItemSelectedListener()


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3