字节流&InputStream &OutputStream
ASP.Net+Android+IO开发、.Net培训、期待与您交流!
字节流
字节流两个基类:
InputStream , OutputStream
类 OutputStream方法
输出流接受输出字节并将这些字节发送到某个接收器。 void |
write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。 |
void |
write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 |
abstract void |
write(int b) 将指定的字节写入此输出流。 |
类 FileOutputStream
FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。 |
复制一个图片
FileOutputStream fos = null; FileInputStream fis = null; try { fos = new FileOutputStream("c:\\2.bmp" ); fis = new FileInputStream("c:\\1.bmp" );
byte[] buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1) { fos.write(buf,0,len); } }
类 BufferedOutputStream
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 |
通过字节流的缓冲区完成复制mp3
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3" )); BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3" )); int by = 0;
while((by=bufis.read())!=-1) { bufos.write(by); }
bufos.close(); bufis.close();
类 ObjectOutputStream
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
public static void writeObj()throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt" ));oos.writeObject( new Person("lisi0" ,399,"kr"));
oos.close(); }
类 PipedOutputStream
可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream
对象,并由其他线程从连接的 PipedInputStream
读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于 毁坏 状态。
PipedOutputStream() 创建尚未连接到管道输入流的管道输出流。 |
PipedOutputStream(PipedInputStream snk) 创建连接到指定管道输入流的管道输出流。 |
Read r = new Read(in); Write w = new Write(out); new Thread(r).start(); new Thread(w).start();
类 DataOutputStream
可以用于操作基本数据类型的数据的流对象void |
writeInt(int v) 将一个 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。 |
public static void readData()throws IOException { DataInputStream dis = new DataInputStream(new FileInputStream("data.txt" ));
int num = dis.readInt(); boolean b = dis.readBoolean(); double d = dis.readDouble();
System. out.println("num=" +num); System. out.println("b=" +b); System. out.println("d=" +d);
dis.close(); } public static void writeData()throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt" ));
dos.writeInt(234); dos.writeBoolean( true); dos.writeDouble(9887.543);
dos.close();
ObjectOutputStream oos = null; oos.writeObject( new O());
}
类 ByteArrayOutputStream
用于操作字节数组的流对象ByteArrayInputStream :在构造的时候,需要接收数据源,。而且数据源是一个字节数组。ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。
这就是数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源。
所以,不用进行close关闭
源设备,
键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:
控制台 System.out,硬盘FileStream,内存 ArrayStream
byte[] |
toByteArray() 创建一个新分配的 byte 数组。 |
String |
toString() 使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。 |
//数据源。 ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD" .getBytes());
//数据目的 ByteArrayOutputStream bos = new ByteArrayOutputStream();
int by = 0;
while((by=bis.read())!=-1) { bos.write(by ); }
System.out.println(bos.size()); System.out.println(bos.toString());
// bos.writeTo(new FileOutputStream("a.txt"))
类 InputStream方法
int |
available() 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。 (!多线程时读取或跳过的字节数可能小于该数,试图使用此方法的返回值分配缓冲区来实现读取和跳过是不正确的)
|
abstract |
read() 从输入流中读取数据的下一个字节。 |
int |
read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。 |
FileInputStream fis = new FileInputStream("fos.txt" ); // int num = fis.available(); byte[] buf = new byte[fis.available()]; //定义一个刚刚好的缓冲区。不用在循环了。
fis.read(buf);
System. out.println(new String(buf));
fis.close();
类 FileInputStream
和InputStream相似类 BufferedInputStream
字段摘要 | |
---|---|
protected byte[] |
buf 存储数据的内部缓冲区数组。 |
protected int |
count 比缓冲区中最后一个有效字节的索引大 1 的索引。 buf[0] 到 buf[count-1] 的元素包含从底层输入流中获取的缓冲输入数据
|
protected int |
marklimit 调用 mark 方法后,在后续调用 reset 方法失败之前所允许的最大提前读取量。 |
protected int |
markpos 最后一次调用 mark 方法时 pos 字段的值。 |
protected int |
pos 缓冲区中的当前位置。 |
以下是JDK读取文件的过程
private void fill() throws IOException { byte[] buffer = getBufIfOpen(); if (markpos < 0) pos = 0; /* no mark: throw away the buffer */ else if (pos >= buffer.length) /* no room left in buffer */ if (markpos > 0) { /* can throw away early part of the buffer */ int sz = pos - markpos; System.arraycopy(buffer, markpos, buffer, 0, sz); pos = sz; markpos = 0; } else if (buffer.length >= marklimit) { markpos = -1; /* buffer got too big, invalidate mark */ pos = 0; /* drop buffer contents */ } else { /* grow buffer */ int nsz = pos * 2; if (nsz > marklimit) nsz = marklimit; byte nbuf[] = new byte[nsz]; System.arraycopy(buffer, 0, nbuf, 0, pos); if (!bufUpdater.compareAndSet(this, buffer, nbuf)) { // Can't replace buf if there was an async close. // Note: This would need to be changed if fill() // is ever made accessible to multiple threads. // But for now, the only way CAS can fail is via close. // assert buf == null; throw new IOException("Stream closed"); } buffer = nbuf; } count = pos; int n = getInIfOpen().read(buffer, pos, buffer.length - pos); if (n > 0) count = n + pos; } public synchronized int read() throws IOException { if (pos >= count) { fill(); if (pos >= count) return -1; } return getBufIfOpen()[pos++] & 0xff; }
结论:
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。
而在写入数据时,只写该int类型数据的最低8位。
类 ObjectInputStream
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。类 PipedInputStream
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从PipedInputStream
对象读取,并由其他线程将其写入到相应的 PipedOutputStream
。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。
PipedInputStream(PipedOutputStream src) 创建 PipedInputStream ,使其连接到管道输出流 src 。 |
类 DataInputStream
int |
readInt() 参见 DataInput 的 readInt 方法的常规协定。可见有两个大接口DataInput,和DataOutput
|
类 ByteArrayOutputStream
参见ByteArraysInputStream相似ASP.Net+Android+IO开发、.Net培训、期待与您交流!