java字节流

前言

输入流:把数据(键盘输入、鼠标、扫描仪等等外设设备)读入到内存(程序)中

输出流:把内存(程序)中的数据输出到外设或其他地方,从文件角度简单总结就是,输入流就是读数据,输出流就是写数据。

在这个过程中,始终把内存作为参考点。

在JAVA语言中,定义了专门的类用来表示输入和输出,这些类放在java.io包中。按数据传输单位划分,可以分为字节流和字符流。

本文重点介绍字节流

InputStream:继承自InputStream的流都是用于向程序中输入数据的,且数据单位都是字节8位,类图如下
在这里插入图片描述

OutputStream:继承自OutputStream的流都是程序用于向外输出数据的,且数据单位都是字节8位

在这里插入图片描述

一、输入流

1、InputStream

此抽象类是表示字节输入流的所有类的超类

public abstract class InputStream extends Object implements Closeable

int available() 返回可从此输入流读取(或跳过)的剩余字节数。 

单字节读取

//这种读取的方式是一个字节一个字节的读。返回的是读取的字节 0 到 255 范围内的 int 字节值 ,如果因为到达流末尾而没有可用的字节,则返回值 -1。
int read() //单字节读取 

案例

String temp="abc";

byte[]b=temp.getBytes();

InputStream in= new ByteArrayInputStream(b);

int c;

while((c=in.read())!=-1){    

  System.out.print(c);//97 98 99
}

多字节读取

将数据先读入一个数组中,等数组满后,然后在一起写入
返回:数组满后读入字节的个数;如果因为已到达流末尾而不再有数据可用,则返回 -1。

//b - 读入数据的缓冲区。 
//off - 数组 b 中将写入数据的初始偏移量。
//len - 要读取的最大字节数。数组的容量 
int read(byte[] b) 		
int read(byte[] b, int off, int len) 

案例

String temp = "abc"; 

byte[] b = temp.getBytes(); 

InputStream in = new ByteArrayInputStream(b); 

byte[] arr = new byte[1]; 

int c ; 

while((c=in.read(arr,0,arr.length))!=-1){       
 
  System.out.println(c);//1 1 1

跳过

boolean markSupported()//测试此 InputStream 是否支持 mark/reset。true表示可以用 mark/reset方法 
long skip(long n)//从此输入流中跳过 n 个输入字节。 

案例

String temp = "abcdefg";

byte[] b = temp.getBytes(); 

InputStream in = new ByteArrayInputStream(b); 

int c ; int flag = 0; 

while((c=in.read())!=-1){        

        System.out.print((char)c);        
        
        in.skip(2); 
} 
//adg 

标记相关的方法

void mark(int readAheadLimit)  //将缓冲区的位置重置为标记位置。 //如果没有调用mark方法,就指针就重新指流的开始位置

这个方法用于在流的当前位置做个标记,参数readLimit指定这个标记的“有效期“,如果从标记处开始往后,已经获取或者跳过了readLimit个字节,那么这个标记失效,不允许使用reset()方法重新回到这个位置 。多次调用这个方法,前面的标记会被覆盖。注意readAheadLimit的单位是字节但是在这里 我们发现readlimit参数根本就没有用,调用mark方法的时候写多少都无所谓。
在这里插入图片描述
案例1

String temp = "abcdefg"; 

byte[] b = temp.getBytes(); 

InputStream in = new ByteArrayInputStream(b); 

int c ; 

int flag = 0; 

while((c=in.read())!=-1){    

         System.out.print((char)c);    
 
        if(flag==0&&(char)c=='d'){            

            in.reset();           

                flag=1;     
     } 
} //abcdabcdefg

案例2

String temp = "abcdefg"; 

byte[] b = temp.getBytes();
 
InputStream in = new ByteArrayInputStream(b); 

int c ; 

int flag = 0; 

while((c=in.read())!=-1){      

         if((char)c=='c'){   
         
            in.mark(2);   
    
     }       
        System.out.print((char)c); 
      
        if(flag==0&&(char)c=='f'){    
        
    in.reset();            

    flag=1;       
 
   }  
} //abcdefdefg 

根据JAVA官方文档的描述,mark(int readlimit)方法表示,标记当前位置,并保证在mark以后最多可以读取readlimit字节数据,mark标记仍有效。如果在mark后读取超过readlimit字节数据,mark标记就会失效,调用reset()方法会有异常。 但实际的运行情况却和JAVA文档中的描述并不完全相符。 有时候在BufferedInputStream类中调用mark(int readlimit)方法后,即使读取超过readlimit字节的数据,mark标记仍有效,仍然能正确调用reset方法重置。

mark标记一个位置后 用reset方法后,只能从标记位置后读取,至于读取多少看readlimit值,事实上,mark在JAVA中的实现是和缓冲区相关的。只要缓冲区够大,mark后读取的数据没有超出缓冲区的大小,mark标记就不会失效。如果不够大,mark后又读取了大量的数据,导致缓冲区更新,原来标记的位置自然找不到了。

因此,mark后读取多少字节才失效,并不完全由readlimit参数确定,也和BufferedInputStream类的缓冲区大小有关。 如果BufferedInputStream类的缓冲区大小大于readlimit,在mark以后只有读取超过缓冲区大小的数据,mark标记才会失效。看下面的例子。注意BufferedInputStream的默认缓冲区值是8192;

byte[]bytes={1,2,3,4,5};//用一个ByteArrayInputStream来读取这个字节数组

ByteArrayInputStream in=new ByteArrayInputStream(bytes);//将ByteArrayInputStream包含在一个BufferedInputStream,并初始化缓冲区大小为2。

BufferedInputStream bus=new BufferedInputStream(in,2);//读取字节1

System.out.print(bis.read()+",");1,


System.out.println("mark");mark

bis.mark(1);//在字节2处做标记,同时设置readlimit参数为1

//根据JAVA文档mark以后最多只能读取1个字节,否则mark标记失效,但实际运行结果不是这样

//连续读取两个字节,mark标记仍有效

System.out.print(bis.read()+",");2,

System.out.print(bis.read()+",");3,

System.out.println("reset");reset

bis.reset();//调用reset方法,未发生异常,说明mark标记仍有效。因为,虽然readlimit参数为1,但是这个BufferedInputStream类的缓冲区大小为2,所以允许读取2字节


//reset重置后连续读取3个字节,超过了BufferedInputStream类的缓冲区大小

System.out.print(bis.read()+",");2,

System.out.print(bis.read()+",");3,

System.out.print(bis.read()+",");4,

System.out.println("resetagain");resetagain

bis.reset();//再次调用reset重置,抛出异常,说明mark后读取3个字节,mark标记失效

java.io.IOException:Resettingtoinvalidmark

/*
*连续读取3个字节,超过了缓冲区大小,mark标记失效。
*在这个例子中BufferedInputStream类的缓冲区大小大于readlimit,
*mark标记由缓冲区大小决定
*/
2、ByteArrayInputStream

ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。
关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
ByteArrayInputStream的功能是从内存中读取数据,这个数据是放在数据中的

public class ByteArrayInputStream extends InputStream

构造方法摘要

创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。(将数据放进这个数组中,然后在进行读取)

ByteArrayInputStream(byte[] buf)   
	
ByteArrayInputStream(byte[] buf, int offset(缓冲区中要读取的第一个字节的偏移量), int length(读取的最大字节数))

方法都是继承父类的

ByteArrayOutputStream或ByteArrayInputStream不需要关闭流原因分析?

ByteArrayOutputStream或ByteArrayInputStream是内存读写流,不同于指向硬盘的流,它内部是使用字节数组读内存的,这个字节数组是它的成员变量,当这个数组不再使用变成垃圾的时候,Java的垃圾回收机制会将它回收。所以不需要关流。也就是说,指向内存的流可以不用关闭,指向存储卡/硬盘的流一定要关闭

3、FileInputStream

FileInputStream 从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。
FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。

public class FileInputStream extends InputStream

构造方法摘要

//如果指定文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取,则抛出 FileNotFoundException
FileInputStream(File file) 
FileInputStream(FileDescriptor fdObj) 
FileInputStream(String name) 

自己都有方法摘要

protected void finalize() 
FileChannel getChannel() 
FileDescriptor getFD() 
4、PipedInputStream

管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。

public class PipedInputStream extends InputStream

构造方法摘要

PipedInputStream()//创建尚未连接的 PipedInputStream。 

PipedInputStream(int pipeSize)//创建一个尚未连接的 PipedInputStream,并对管道缓冲区使用指定的管道大小。 

PipedInputStream(PipedOutputStream src  ) //创建 PipedInputStream,使其连接到管道输出流 src 
//创建一个 PipedInputStream,使其连接到管道输出流 src,并对管道缓冲区使用指定的道大小。 
PipedInputStream(PipedOutputStream src, int pipeSize) 

自己方法摘要

protected void receive(int b) void connect(PipedOutputStream src)
5、BufferedInputStream

BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。java缓冲流本身不具IO功能,只是在别的流上加上缓冲提高效率,像是为别的流装上一种包装。当对文件或其他目标频繁读写或操作效率低,效能差。这时使用缓冲流能够更高效的读写信息。因为缓冲流先将数据缓存起来,然后一起写入或读取出来。所以说,缓冲流还是很重要的,在IO操作时记得加上缓冲流提升性能。

public class BufferedInputStream extends FilterInputStream

构造方法摘要

创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。创建一个长度为 size 的内部缓冲区数组并将其存储在 buf 中。

BufferedInputStream(InputStream in) 
	
BufferedInputStream(InputStream in, int size) 
6、FilterInputStream

包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。FilterInputStream 类本身只是简单地重写那些将所有请求传递给所包含输入流的 InputStream 的所有方法。FilterInputStream 的子类可进一步重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

public class FilterInputStream extends InputStream FilterInputStream

7、PushbackInputStream

在JAVA IO中所有的数据都是采用顺序的读取方式,即对于一个输入流来讲都是采用从头到尾的顺序读取的,如果在输入流中某个不需要的内容被读取进来,则只能通过程序将这些不需要的内容处理掉,为了解决这样的处理问题,在JAVA中提供了一种回退输入流
PushbackInputStream、PushbackReader),可以把读取进来的某些数据重新回退到输入流的缓冲区之中。
作用:剔除不需要的字节

public class PushbackInputStream extends FilterInputStream

构造方法摘要

使用指定 size 的推回缓冲区创建 PushbackInputStream,并保存其参数(即输入流 in),以供将来使用

PushbackInputStream(InputStream in) 
PushbackInputStream(InputStream in, int size) 	

方法摘要

void unread(byte[] b) //推回一个 byte 数组:将其复制到推回缓冲区之前。 
void unread(byte[] b, int off, int len)  //推回 byte 数组的某一部分:将其复制到推回缓冲区之前。 	
void unread(int b)  //推回一个字节:将其复制到推回缓冲区之前。

案例

String str="www.hello.wc";

ByteArrayInputStream in=new ByteArrayInputStream(str.getBytes());

PushbackInputStream back=new PushbackInputStream(in);

Int c;

while((c=in.read())!=-1){

	if((char)c=='.'){

    back.unread(c);

	back.read();
     
	}else{
	System.out.print((char)c);//wwwhellowc
	}
 }
}

8、DataInputStream

数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。DataInputStream 对于多线程访问不一定是安全的。 线程安全是可选的,它由此类方法的使用者负责。

public class DataInputStream extends FilterInputStream implements DataInput

构造方法摘要

DataInputStream(InputStream in) 

基本类型输入

byte readByte()

char readChar() 

short  readShort() 

int readInt() 

long readLong() 

float readFloat() 

double readDouble()
 
boolean readBoolean() 

引用类型输入

int read(byte[] b) 
	
int read(byte[] b, int off, int len) 
	
void readFully(byte[] b) 
	
void readFully(byte[] b, int off, int len) 
	
int readUnsignedByte() 
	
int readUnsignedShort() 
	
String readUTF() 
	
static String readUTF(DataInput in)
	 
int skipBytes(int n)
9、ObjectInputStream

public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

ObjectInputStream 确保从流创建的图形中所有对象的类型与 Java 虚拟机中显示的类相匹配。使用标准机制按需加载类。

只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流读取。

readObject 方法用于从流读取对象。应该使用 Java 的安全强制转换来获取所需的类型。在 Java 中,字符串和数组都是对象,所以在序列化期间将其视为对象。读取时,需要将其强制转换为期望的类型。可以使用 DataInput 上的适当方法从流读取基本数据类型。

默认情况下,对象的反序列化机制会将每个字段的内容恢复为写入时它所具有的值和类型。反序列化进程将忽略声明为瞬态或静态的字段。对其他对象的引用使得根据需要从流中读取这些对象。使用引用共享机制能够正确地恢复对象的图形。反序列化时始终分配新对象,这样可以避免现有对象被重写。

读取对象类似于运行新对象的构造方法。为对象分配内存并将其初始化为零 (NULL)。为不可序列化类调用无参数构造方法,然后从以最接近 java.lang.object 的可序列化类开始和以对象的最特定类结束的流恢复可序列化类的字段。

构造方法摘要

protected ObjectInputStream() 

ObjectInputStream(InputStream in) 

自己的方法很多

二、输出流

1、OutputStream

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

public abstract class OutputStream extends Object implements Closeable, Flushable

void close() 关闭此输出流并释放与此流有关的所有系统资源。 
	
void flush() 刷新此输出流并强制写出所有缓冲的输出字节。 
	
void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。 
	
void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 
	
abstract void write(int b) 将指定的字节写入此输出流 

关闭方法

void close() //关闭此输出流并释放与此流有关的所有系统资源。 

注意:关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。

流的写入

void write(byte[] b) //将 b.length 个字节写入此输出流。多字节写如 
void write(byte[] b, int off, int len)//将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 
void write(int b)单字节写入 

案例1

OutputStream out = new BufferedOutputStream (new FileOutputStream("D:/hello2.txt")); 
byte[] by = "abc".getBytes(); 
out.write(by); 
out.close(); //D:/hello2.txt:abc 

案例2

OutputStream out = new BufferedOutputStream (new FileOutputStream("D:/hello2.txt")); 
byte[] by = "abc".getBytes(); 
out.write(by,0,2); 
out.close(); D:/hello2.txt:ab 

刷新流

void flush()  刷新此输出流,并强制将所有已缓冲的输出字节写入该流中。 

为什么关闭流之前要flush()?

flush()这个函数是清空的意思,用于清空缓冲区的数据流,进行流的操作时,数据先被读到内存中,然后再用数据写到文件中,那么当你数据读完时,我们如果这时调用close()方法关闭读写流,这时就可能造成数据丢失,为什么呢,因为,读入数据完成时不代表写入数据完成,一部分数据可能会留在缓存区中,为了理解这个问题,我们举一个例子:

比如,在农村,几乎每家都有抽水机,抽水机的作用是什么呢,就是把水井里的水抽到水缸中,这时我们就会用水管连接抽水机和水缸(水管就好比是缓冲区),当我们想把水井中的水都抽到水缸中时,我们就让抽水机工作抽水,如果我们发现水井里的水刚好抽完时,我们就会关掉抽水机的开关停止抽水,那么这时,管道里就会遗留一部分水,抽水就是读数据,水缸进水就是写数据,水管充当缓存区的角色,不知道这样是不是具象化了呢那么这样一来我们如果中途调用close()方法,输出区也还是有数据的,就像水缸里有水,只是在缓冲区遗留了一部分,这时如果我们先调用flush()方法,就会强制把数据输出,缓存区就清空了,最后再关闭读写流调用close()就完成了。

2、ByteArrayOutputStream

此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。

关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。

public class ByteArrayOutputStream extends OutputStream

ByteArrayOutputStream()创建一个新的 byte 数组输出流。 
	
ByteArrayOutputStream(int size)  //创建一个新的 byte 数组输出流,它具有指定大小的缓冲区容量(以字节为单位)。 

非继承方法说明

 int size() //返回缓冲区的当前大小。数组中读取的字节数 

案例

ByteArrayOutputStream by = new ByteArrayOutputStream(); 
	
System.out.println(by.size()); //0 
	
ByteArrayOutputStream by = new ByteArrayOutputStream(); 
	
byte[] arr = "abcd".getBytes();
	
by.write(arr); 
	
System.out.println(by.size());//4 
void reset()   清空数组 

案例

ByteArrayOutputStream by = new ByteArrayOutputStream(); 

byte[] arr = "abcd".getBytes(); 

by.write(arr); 

by.reset(); 

System.out.println(by.toString("utf-8"));//输出为空 
byte[] toByteArray()   创建一个新分配的 byte 数组。

案例

ByteArrayOutputStream by = new ByteArrayOutputStream(); 
	
byte[] arr = "abcd".getBytes(); 
	
by.write(arr); 
	
byte[] arr1 = by.toByteArray(); 
	
System.out.println(Arrays.toString(arr1));//{97, 98, 99, 100} 
String toString()  使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。 

案例

ByteArrayOutputStream by = new ByteArrayOutputStream(); 

byte[] arr = "abcd".getBytes(); 

by.write(arr); 

System.out.println(by.toString()); //abcd 
String toString (String charsetName)   使用指定的 charsetName,通过解码字节将缓冲区内容转换为字符串。 

案例

ByteArrayOutputStream by = new ByteArrayOutputStream(); 
	
byte[] arr = "abcd".getBytes(); 
	
by.write(arr); 
	
System.out.println(by.toString("utf-8")); //abcd 
void writeTo(OutputStream out) 

将此 byte 数组输出流的全部内容写入到指定的输出流参数中,这与使用 out.write(buf, 0, count)
调用该输出流的 write 方法效果一样。

3、FileOutputStream

文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。文件是否可用或能否可以被创建取决于基础平台。特别是某些平台一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。

FileOutputStream 用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用 FileWriter。

public class FileOutputStream extends OutputStream

//append - 如果为 true,在原有的内容后追加
//append - 如果为 false,把原有的内容清空后在写入
FileOutputStream(File file) FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(File file, boolean append) 
FileOutputStream(String name, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(FileDescriptor fdObj) 
//创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。

非继承方法

protected void finalize() 清理到文件的连接,并确保在不再引用此文件输出流时调用此流的 close 方法。
	
FileChannel getChannel() 返回与此文件输出流有关的唯一 FileChannel 对象。 FileDescriptor getFD() 返回与此流有关的文件描述符。
4、BufferedOutputStream

该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。

public class BufferedOutputStream extends FilterOutputStream

BufferedOutputStream(OutputStream out)  创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 
	
BufferedOutputStream(OutputStream out, int size)  创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流 
5、FilterOutputStream

public class FilterOutputStream extends OutputStream

此类是过滤输出流的所有类的超类。这些流位于已存在的输出流(基础 输出流)之上,它们将已存在的输出流作为其基本数据接收器,但可能直接传输数据或提供一些额外的功能。

FilterOutputStream 类本身只是简单地重写那些将所有请求传递给所包含输出流的 OutputStream 的所有方法。FilterOutputStream 的子类可进一步地重写这些方法中的一些方法,并且还可以提供一些额外的方法和字

FilterOutputStream(OutputStream out) 创建一个构建在指定基础输出流之上的输出流过滤 
6、PipedOutputStream

public class PipedOutputStream extends OutputStream

可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程

从连接的 PipedInputStream 读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于 毁坏 状态。

PipedOutputStream()   创建尚未连接到管道输入流的管道输出流。 

PipedOutputStream(PipedInputStream snk)   创建连接到指定管道输入流的管道输出流。 

非继承方法

void  connect(PipedInputStream snk) 将此管道输出流连接到接收者
7、DataOutputStream

public class DataOutputStream extends FilterOutputStream implements DataOutput

数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。

DataOutputStream(OutputStream out)  创建一个新的数据输出流,将数据写入指定基础输出流 

基本类型输出

入基础输出流中,先写入高字节。

void writeByte(int v)     
	
void writeChar(int v)      
	
void writeShort(int v)     
	
void writeInt(int v)    
	
void  writeLong(long v)    
	
void writeFloat(float v)    
	
void writeDouble(double v)    
void writeBoolean(boolean v)   

引用类型输出

void writeBytes(String s)  将字符串按字节顺序写出到基础输出流中。 

void writeChars(String s)  将字符串按字符顺序写入基础输出流 。 

void writeUTF(String str)  以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流。 

写入此数据输出流的字节数

int size()返回计数器 written 的当前值,即到目前为止写入此数据输出流的字节数。
8、PrintStream

public class PrintStream extends FilterOutputStream implements Appendable, Closeable

PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。它还提供其他两项功能。与其他输出流不同,PrintStream 永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。另外,为了自动刷新,可以创建一个 PrintStream;这意味着可在写入 byte 数组之后自动调用 flush 方法,可调用其中一个 println 方法,或写入一个换行符或字节 (’\n’)。

PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。

PrintStream(File file)    创建具有指定文件且不带自动行刷新的新打印流 

PrintStream(File file, String csn)    创建具有指定文件名称和字符集且不带自动行刷新的新打印流。csn - 受支持的字符集的名称 

PrintStream(String fileName)   创建具有指定文件名称且不带自动行刷新的新打印流。 

PrintStream(String fileName, String csn)    创建具有指定文件名称和字符集且不带自动行刷新的新打印流。csn - 受支持的字符集的名称 

PrintStream(OutputStream out)  创建新的打印流。创建新的打印流。此流将不会自动刷新。 

PrintStream(OutputStream out, boolean autoFlush )  创建新的打印流。 
//autoFlush - boolean 变量;如果为 true,则每当写入 byte 数组、调用其中一个 println 方法或写入换行符或字节 ('\n') 时都会刷新缓冲区
PrintStream(OutputStream out, boolean autoFlush, String encoding)  创建新的打印流。encoding - 受支持的字符编码的名称 

println 基本类型

void println(char x) 
void println(int x) 
void println(long x) 
void println(float x) 
void println(double x) 
void println(boolean x) 

print 基本类型

void print(char c) 
void print(int i) 
void print(float f) 
void print(double d) 
void print(long l) 
void print(boolean b) 

println 引用类型

void println(Object obj) 
void println(String s) 
void println() 
void println(char[] x) 

print 引用类型

void print(char[] s) 
void print(Object obj) 
void print(String s) 

字符添加

PrintStream append(char c)   将指定字符添加到此输出流。 

PrintStream append(CharSequence csq) 将指定字符序列添加到此输出流。

PrintStream append(CharSequence csq, int start, int end) 将指定字符序列的子序列添加到此输出流。 

格式化输出

PrintStream format(Locale l, String format, Object... args)  使用指定格式字符串和参数将格式化字符串写入此输出流中。 PrintStream 

format(String format, Object... args )   使用指定格式字符串和参数将格式化字符串写入此输出流中。 

错误状态

protected void setError()   将该流的错误状态设置为 trueboolean checkError()        刷新流并检查其错误状态。 

protected void clearError()    清除此流的内部错误状态。 
9、ObjectOutputStream

public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。

writeObject 方法用于将对象写入流中。所有对象(包括 String 和数组)都可以通过 writeObject 写入。可将多个对象或基元写入流中。必须使用与写入对象时相同的类型和顺序从相应 ObjectInputstream 中读回对象。

还可以使用 DataOutput 中的适当方法将基本数据类型写入流中。还可以使用 writeUTF 方法写入字符串。

对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字段的值。其他对象的引用(瞬态和静态字段除外)也会导致写入那些对象。可使用引用共享机制对单个对象的多个引用进行编码,这样即可将对象的图形恢复为最初写入它们时的形状。

例如,要写入可通过 ObjectInputStream 中的示例读取的对象,请执行以下操作:

FileOutputStream fos = new FileOutputStream("t.tmp");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeInt(12345);

oos.writeObject("Today");

oos.writeObject(new Date());

oos.close();

在序列化和反序列化过程中需要特殊处理的类必须实现具有下列准确签名的特殊方法:

private void readObject(java.io.ObjectInputStream stream)throws IOException, ClassNotFoundException;
		
private void writeObject(java.io.ObjectOutputStream stream)throws IOException
		
private void readObjectNoData()throws ObjectStreamException;

writeObject 方法负责写入特定类的对象状态,以便相应的 readObject 方法可以恢复它。该方法本身不必与属于对象的超类或子类的状态有关。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。

序列化操作不写出没有实现 java.io.Serializable 接口的任何对象的字段。不可序列化的 Object 的子类可以是可序列化的。在此情况下,不可序列化的类必须有一个无参数构造方法,以便允许初始化其字段。在此情况下,子类负责保存和恢复不可序列化的类的状态。经常出现的情况是,该类的字段是可访问的public、package 或 protected),或者存在可用来恢复状态的 get 和 set 方法。

在 writeObject 和 readObject 方法的实现中抛出 NotSerializableException,可以阻止对象的序列化。ObjectOutputStream 将捕获异常并中止序列化进程。

实现 Externalizable 接口允许对象假定可以完全控制对象的序列化形式的内容和格式。调用 Externalizable 接口的方法(writeExternal 和 readExternal)来保存和恢复对象的状态。通过类实现时,它们可以使用 ObjectOutput 和 ObjectInput 的所有方法读写它们自己的状态。对象负责处理出现的任何版本控制。

Enum 常量的序列化不同于普通的 serializable 或 externalizable 对象。enum 常量的序列化形式只包含其名称;常量的字段值不被传送。为了序列化 enum 常量,ObjectOutputStream 需要写入由常量的名称方法返回的字符串。与其他 serializable 或 externalizable 对象一样,enum 常量可以作为序列化流中后续出现的 back 引用的目标。用于序列化 enum 常量的进程不可定制;在序列化期间,由 enum 类型定义的所有类特定的 writeObject 和 writeReplace 方法都将被忽略。类似地,任何 serialPersistentFields 或 serialVersionUID 字段声明也将被忽略,所有 enum 类型都有一个 0L 的固定的 serialVersionUID。

基本数据(不包括 serializable 字段和 externalizable 数据)以块数据记录的形式写入 ObjectOutputStream 中。块数据记录由头部和数据组成。块数据部分

包括标记和跟在部分后面的字节数。连续的基本写入数据被合并在一个块数据记录中。块数据记录的分块因子为 1024 字节。每个块数据记录都将填满 1024 字节,或者在终止块数据模式时被写入。调用 ObjectOutputStream 方法 writeObject、defaultWriteObject 和 writeFields 最初只是终止所有现有块数据记录。

protected ObjectOutputStream() 
protected ObjectOutputStream(OutputStream out)

基本类型输出

void  write(int val)   写入一个字节。 

void  writeBytes(String str)    以字节序列形式写入一个 String。 

void  writeChars(String str)char 序列形式写入一个 String。 

基本类型输出

void  writeByte(int val)   写入一个 8 位字节。 
	
void  writeChar(int val) 

void  writeShort(int val) 

void  writeInt(int val) 

void  writeLong(long val) 

void  writeFloat(float val) 

void writeDouble(double val) 

void  writeBoolean(boolean val)  

引用类型输出

void  writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。 

void  writeFields() 将已缓冲的字段写入流中。 

void  writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。 

void  writeUnshared(Object obj) 将“未共享”对象写入 ObjectOutputStream。 

void  writeUTF(String str) 以 UTF-8 修改版格式写入此 String 的基本数据 void 

default WriteObject() 将当前类的非静态和非瞬态字段写入此流。 

还有其他方法

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值