您的位置:首页 > 理论基础 > 计算机网络

Java网络编程 Ch2

2018-03-13 11:15 134 查看
参阅Thinging in Java I/O流

输出流

public abstract class OutputStream
public abstract void write (int b)throws IOException
public void write(byte[] data)throws IOException
public void write(byte[] data, int offset, int length)throws IOException
// 刷新输出流。避免挂起。关闭流之前立即刷新所有输出,避免丢失缓冲区中数据。
public void flush() throws IOException
//关闭流,释放与流相关的所有资源。
public void close() throws IOException


public abstract write(int b)需要子类实现。接受0到255之间的整数,所以int(因为java没有无符号字节,所以用int代替)前3个字节被忽略。

关闭流。dispose pattern

OutputStream out = null;//必须在try块之外声明流变量。
try{
//必须在try块内初始化
out = new FileOutputStream("/tmp/data.txt");
// 处理输出流
}catch(IOException ex){
System.err.println(ex.getMessage);
}finally{
if(out!=null){
try{
out.close();
}catch(IOException ex){
//忽略(通常都希望忽略关闭流时出现的异常)
}
}
}

//”带资源的try“构造,更简洁完成清理
try(OutputStream out = new FileOutputStream("/tmp/data.txt")){
//处理输出流
}catch(IOException ex){
System.err.println(ex.getMessage)
}
//不再需要Finally子句,Java会对try块参数表中声明的所有AutoCLoseable对象自动调用close()


输入流

public abstract class InputStream
//read方法都用-1表示流的结束。
// 从源中一次读取一个字节,作为一个0到255之间的int返回,read方法会阻塞前后任何代码的执行。直到有一个字节的数据可供读取。
public abstract void read() throws IOException
//读取多个字节,尝试填充指定数组。不一定成功。返回实际读取字节数。
//真实做法时重复读取。
public void read(byte[] input) throws IOException
//流结束时返回0,如果length是0,返回0;
public void read(byte[] input, int offset, int length)throws IOException
public long skip(long n) throws IOException
public int avaliable()  throws IOException
//关闭流,释放与流相关的所有资源。
public void close() throws IOException

// 重复读取,直到数组填满
int bytesRead = 0;
int bytesToRead = 1024;
byte[] input = new byte[byteToRead];
while (bytesRead<bytesToRead){
int result = in.read(input, bytesRead, butesToRead-bytesRead);
if(result==-1) break;
bytesRead+=result;
}

//不阻塞读取,当时有多少字节数可用。在流的最后available会返回0。
int bytesAvailable = in.available();
byte[] input = new byte[bytesAvailable];
int bytesRead = in.read(input, 0, bytesAvaliable);


标记和重置

java.io中仅有的两个始终支持标记的输入流类是BufferedInputStream和ByteArrayInputStream。其他输入流如果先串链到缓冲的输入流才支持标记。

//尾流重新读取数据,使用mark标记流的当前位置。任意时刻只能存在一个标记。
public void mark(int readAheadLimit)
// reset把流重置到之前标记的位置
public void reset() throws IOException
//并不是所有流都支持标记和重置,尝试使用前用下面方法检查。
//如果不支持,调用mark什么都不做。reset抛出异常。
public booelan markSupported()


过滤器流

用于在原始字节和各种格式(比如:7位ASCII、8位Latin-1,多字节UTF-8)转换。

分为:过滤器流以及阅读器和读写器。

将过滤器串联在一起

过滤器通过构造函数和流连接

FileInputStream  fin = new FileInputStream("data.txt");
BufferedInputStream bin = new BufferedInputStream(fin);

//应当使用最后一个过滤器进行实际的读写。(其他操作可能涉及底层流,但绝不能进行读写)
BufferedInputStream bin = new BufferedInputStream(
new FileInputStream("data.txt"));


缓冲流

能够带来巨大性能提升

BufferedOutputStream将写入的数据存储在缓冲区中(一个名为buf的保护字节数组),直到缓冲区满或者刷新输出流。然后它将数据一次全部写入底层输出流。

BufferedInputStream也有一个作为缓冲区的保护字节数组,buf。当调用某个流的read方法时,它先尝试读取缓冲区中数据。只有当缓冲区没有数据时,流才从底层的源中读取数据。

//第一个参数底层流,从中读取未缓冲数据
public BufferedInputStream(InputStream in)
//第二个参数指定缓冲区中的字节数,否则默认输出流缓冲区为512字节
// 输入流为2048字节。
public BufferedInputStream(InputStream in, int bufferSize)
//或者写入缓冲的数据。
//所以输出流会将数据放在缓冲区中,而不是直接放入底层输出流。因此发送数据时
//需要刷新输出流。
public BufferedOutputStream(outputStream out)
public BufferedOutputStream(OutputStream out, int bufferSize)


PrintStream

数据流

DataInputStream和DataOutputStream类提供了一些方法,可以用二进制格式读/写Java的基本数据类型和字符串。

所有数据以big-endian格式写入。

操作系统一般是小端,通信协议是大端。

所谓大端小端,存储的时候是将数据的高位字节还是低位字节存在物理地址低的地方。

readLine()存在bug。只能识别回车或者回车/换行对,在流中检测到回车,readLine在继续之前会等待,查看下一个字符是否为换行。如果是则抛到回车和换行,返回这一行。bug在于如果回车是流的最后一个字符,readLine会一直挂起。

阅读器和书写器

PrintWriter类取代PrintStream
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java网络编程