Java网络编程第二章-流
2016-11-06 16:39
281 查看
Java网络编程第二章流
概述
Java的输入输出I/O的组织与其他大多数语言都不一样。I/O基于stream之上,输入流读取数据,输出流写入数据。
还有过滤器(filter),阅读器(reader)和书写器(writer)。
过滤器(filter)能够改写数据,转换格式。
阅读器(reader)与书写器(writer),能够改写字符,文本而不是字节。
流是同步的,即一次只能处理一个事务,容易造成阻塞,但是Java支持通道和缓冲区技术,即非阻塞I/O技术,通道与缓冲区都依赖于流。
输出流
基本输出类:java.io.OutputStream向某种介质写入数据。
Fileoutputstream->写入文件
Telnetoutputstream->写入网络连接
Bytearraryoutputstream->写入字节数组()可拓展
注意:Telnetoutputstream类被隐藏在了sun包中。
Outputstream的基本方法:write(int b)b为0~255的整数。且b应该为无符号字节,因为java没有无符号类型数据,只能使用int(4字节)代替,实际上只会填入最低一个字节,即只填入了8个二进制数字。这里的int实际上被强制类型转换成byte。
Fileoutputstream 必须使用纯java实现此方法才能将字节写入数组。
Bytearraryoutputstream 则需要原生代码实现。
流也存在缓存机制,bufferedoutputstream或是bufferedwriter实现的。写入完成后flush()刷新十分重要。
Flush作用:
//以下代码是java7之前的释放模式 OutputStream out = null;//流变量须try前声明 try { out= new FileOutputStream("/tem/data.txt"); //流变量须try内初始化 //*关闭流之前要进行缓冲区清空(不是丢弃),即刷新(输出) } catch(IOException ex) { System.err.println(ex.getMessage()); } finally { //在finally块内关闭流 if(out!=null){ //关闭前需要判断是否没有输入输出 try{ out.close();//关闭流 如果还有输出输入则抛出异常 }catch(IOException ex) { //忽略 } } }//长时间未能关闭流,会泄露文件句柄,网络端口,其他资源
//以下代码是java7之后的清理模块 try(OutputStream out = out = newFileOutputStream("/tem/data.txt");) { //处理流 } catch(IOException ex) { System.err.println(ex.getMessage()); }
输入流
基本输出类:java.io.IutputStream向某种介质写入数据。
FileInputstream->读取数据
TelnetInputstream->读取网络数据
BytearraryInputstream->读取数据字节到数组()可拓展
注意:TelnetInputstream类被隐藏在了sun包中。
InputStream的基本方法是read( )无参,读入流结束则返回-1,无论是read()还是write()都较为缓慢,容易阻塞,尽量安排写入或读取工作在后面或是单独一个线程。
byte[] input = new byte[10]; for(int i=0;i<input.Lengh;i++){ intb=in.read();//每次只能读入一个字节 if(b==-1)break;//-1为流结束标志 input[i]=(byte)b;//返回int类型需要进行类型转换 } }
//也可以进行符号处理 int i=b>=0?b:256+b; //因为返回的是有符号的-128到127 而实际需要的是无符号的
介绍两个重载read():
Read(byte[] input)//尝试填满指定数组
Read(byte[] input int offset, int length)//尝试从offset开始长度为length的数组填充
这两个数组均为尝试,实际情况很是复杂,不能保证传输,所以可以使用下面的方法:
</pre><pre name="code" class="java">//确保传输准确无误 int bytesRead = 0;//已经传输 int bytesToRead = 1024;//应该传输 byte[] input = new byte[bytesToRead]; while(bytesRead<bytesToRead){ bytesRead+=in.read(input,bytesRead,bytesToRead-bytesRead); }
标记与重置
这个标记与重置,主要用于备份与重新读取数据。Mark()标记
Reset()将流重置到标记之前的位置
标记:1.只能有一个标记点 2.readAheadLimit确定标记距离(不能无限制重置距离)
有些类输入输出流不支持标记,查看能否进行标记重置,可通过marksupposed()进行查看返回,如果返回true则可以进行标记与重置。
BufferedInputStream与ByteArrayInputStream 这两个类始终支持标记与重置。
缓冲流
顾名思义就是缓冲区的流,缓冲区的进行写入与读取操作的流。从缓冲区写入底层输出流:一次多字节,与多次少字节相比,同样字节量,一次较快。
Read()方法调用时会先到缓冲区进行读取操作,如果缓冲区为空,read()会尽可能多的读取数据存入缓冲区,而不是马上就使用它所需的数据。缓冲区的作用在于,从底层流读取几百字节与读取一个字节效率一样,但是放入缓冲区就会大大提高效率。
输入流缓冲区大小默认为2048,而输出流默认大小为512.
PrintStream
过滤输出流,而system.out就是一个过滤输出流,大家接触的第一个过滤输出流。Print() 会将参数转换为字符串,使用默认编码写入底层输出流。
PrintStream是有害的,本书作者讲到。
警告:PrintStream是有害的,网络程序员应当像躲避瘟疫一样避开它!!!!(作者(译者)原话)
第一个问题是println()的输出是与平台有关的。取决于运行代码的机器,各行有时用换行符分隔,有时则用回车符或者回车/换行对来分隔。写入控制台时这不会产生问题,但对于编写必须遵循明确协议的网络客户端和服务器而言,这却是灾难。大多数网络协议(如HTTP和Gnutela)明确指定行应当以回车/换行对结束。使用println()写出的程序很有可能可以在windows上正常工作,但在UNIX和Mac上无法工作。虽然许多服务器和客户端能够“宽容”地接受而且能处理不正确的行结束符,但偶尔也有例外。
第二个问题是PrintStream假定使用所在平台的默认编码方式。不过,这种编码方式可能不是服务器或客户端所期望的。例如,一个接收XML文件的Web浏览器希望文件以UTF-8或UTF16方式编码,除非服务器另行要求。不过,一个使用PrintStream的Web服务器可能会从一个美国本地化环境的windows系统发送CP1251编码的文件,或者从日本本地化环境的系统发送SJIS编码的文件,而不管客户端是否期望或理解这些编码方式。PrintStream不提供任何改变默认编码的机制。这个问题可以通过使用相关的PrintWriter类来修补。但是其他问题依旧。
第三个问题是PrintStream吞掉了所有异常。注意PrintStream中5个标准OutputStream方法的声明没有平常的throws IOException声明:
public abstract void write(int b) public void write(byte[] data) public void write(byte[] data,intoffset,int length) public void void flush() public void close()
实际上,PrintStream要依靠一个过时的不充分的错误标志。如果底层流抛出一个异常,就会设置这个内部错误标志。要由程序员使用checkError()方法来检查这个标志的值:
public booleean checkError()
要对PrintStream完成任何错误检查,代码必须显式地检查每一个调用。此外,一旦出现在错误,就没有办法重置这个标志再进行进一步错误检测。也没有关于这个错误的更多信息。简而言之,PrintStream提供的错误通知对于不可靠的网络连接来说还远远不够。
数据流
二进制格式读写Java基本数据类型和字符串。版权说明
著作权归作者所有©。商业转载请联系作者获得授权,非商业转载请注明出处。
本文作者:Joe.Smith
发表日期:2016年11月6日
本文链接:http://blog.csdn.net/qq_26816591/article/details/53055022
来源:CSDN
更多内容:网络编程第一章
相关文章推荐
- java网络编程笔记 第二章 流
- java网络编程(三)socket
- Java网络编程之URL和URI
- JAVA网络编程【转】出处不详
- 20145208 实验五 Java网络编程
- java网络编程精解学习笔记(第二章 socket详解)
- [置顶] java网络编程—IO及相关原理(上下文切换\多路复用\Reactor\epoll)
- java之网络编程基础
- 18天Java学习---Java的Socket网络编程以及多线程
- Java网络编程笔记(三):点对点通信(Socket基于TCP协议)
- java基础9:网络编程
- Java网络编程 Ch2
- Java进阶之网络编程
- Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
- Java网络编程基础之Scoket通信
- Java网络编程基础 InetAddress类的使用
- Java 网络编程 学习笔记二 Socket 用法
- Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
- Java面向对象 网络编程 上
- 20145205 《Java程序设计》实验报告五:Java网络编程及安全