总结:
- FileInputStream
- FileOutputStream
- BufferedInputStream
- BufferedOutputStream
字节流:
InputStream OutputStream
操作的都是字节数据
需要操作图片数据,需要用到字节流。
InputStream(凡是输入的都是读) OutputStream(凡是输出的都是写)
先来看看写:
|--java.io.OutputStream
public abstract class OutputStream
extends Object此抽象类是表示输出字节流的所有类的超类。
方法都一样,有一个不同之处在于:字符流使用的是字符数组,字节流使用的是字节数组。
看父类方法,建子类对象。
找到已知子类FileOutputStream.
值得注意的是字节流不需要flush,数据直接可以写到硬盘。
构造方法摘要 | |
---|---|
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 | |
FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 | |
FileOutputStream(FileDescriptor fdObj) 创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。 | |
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。 | |
FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。 |
方法摘要 | |
---|---|
void | close() 关闭此文件输出流并释放与此流有关的所有系统资源。 |
protected void | finalize() 清理到文件的连接,并确保在不再引用此文件输出流时调用此流的 close 方法。 |
FileChannel | getChannel() 返回与此文件输出流有关的唯一 FileChannel 对象。 |
FileDescriptor | getFD() 返回与此流有关的文件描述符。 |
void | write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。 |
void | write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 |
void | write(int b) 将指定字节写入此文件输出流。 |
直接继承父类的方法:
void | flush() 刷新此输出流并强制写出所有缓冲的输出字节。 |
下面看看输入流InputStream:
|--java.io.InputStream
public abstract class InputStream
extends Object此抽象类是表示字节输入流的所有类的超类。
直接已知子类:FileInputStream
构造方法摘要 | |
---|---|
FileInputStream(File file) 通过打开一个到实际文件的连接来创建一个 FileInputStream ,该文件通过文件系统中的 File 对象file 指定。 | |
FileInputStream(FileDescriptor fdObj) 通过使用文件描述符 fdObj 创建一个 FileInputStream ,该文件描述符表示到文件系统中某个实际文件的现有连接。 | |
FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream ,该文件通过文件系统中的路径名 name 指定。 |
方法摘要 | |
---|---|
int | available() 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。 |
void | close() 关闭此文件输入流并释放与此流有关的所有系统资源。 |
protected void | finalize() 确保在不再引用文件输入流时调用其 close 方法。 |
FileChannel | getChannel() 返回与此文件输入流有关的唯一 FileChannel 对象。 |
FileDescriptor | getFD() 返回表示到文件系统中实际文件的连接的 FileDescriptor 对象,该文件系统正被此 FileInputStream 使用。 |
int | read() 从此输入流中读取一个数据字节。 |
int | read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 |
int | read(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。 |
long | skip(long n) 从输入流中跳过并丢弃 n 个字节的数据。 |
直接继承父类的方法:
void | mark(int readlimit) 在此输入流中标记当前的位置。 |
boolean | markSupported() 测试此输入流是否支持 mark 和 reset 方法。 |
void | reset() 将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。 |
示例:复制图片
import java.io.*;
class CopyPhotoDemo
{
public static void main(String[] args) throws IOException
{
FileOutputStream fos = new FileOutputStream("C:\\Users\\Think\\Desktop\\cat.jpg");
FileInputStream fis = new FileInputStream("cat.jpg");
byte[] by = new byte[1024];
int num = 0;
while((num=fis.read(by))!=-1)
{
fos.write(by,0,num);
}
fos.close();
fis.close();
}
}
字节流缓冲区:
BufferedInputStream
BufferedOutputStream
拷贝mp3文件:
import java.io.*;
class CopyMp3
{
public static void main(String[] args)
{
long start = System.currentTimeMillis();
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try
{
bis = new BufferedInputStream(new FileInputStream("C:\\Users\\Think\\Music\\1.mp3"));
bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\Think\\Desktop\\1.mp3"));
int num = 0;
while((num=bis.read())!=-1)
{
bos.write(num);
}
}
catch (IOException e)
{
new IOException("读写文件失败");
}
finally
{
try
{
if(bis!=null)
bis.close();
}
catch (IOException e)
{
new IOException("关闭读出流失败");
}
finally
{
try
{
if(bos!=null)
bos.close();
}
catch (IOException e)
{
new IOException("关闭写入流失败");
}
}
}
long end = System.currentTimeMillis();
System.out.println("timeMillis:"+(end-start));
}
}
BufferedInputStream的原理:
import java.io.*;
class BufferedInputStreamDemo
{
public static void main(String[] args) throws IOException
{
long start = System.currentTimeMillis();
MyBufferedInputStream bis = new MyBufferedInputStream(new FileInputStream("C:\\Users\\Think\\Music\\倍儿爽.mp3"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\Think\\Desktop\\倍儿爽.mp3"));
int num = 0;
while((num=bis.myRead())!=-1)
{
bos.write(num);
}
bis.myClose();
bos.close();
long end = System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
}
}
class MyBufferedInputStream
{
private InputStream is;
private byte[] buffer = new byte[1024];
int len = 0;
int point = 0;
MyBufferedInputStream(InputStream is)
{
this.is = is;
}
public int myRead() throws IOException
{
if(len==0)
{
len = is.read(buffer);
if(len<0)
return -1;
point = 0;
byte b = buffer[point];
len--;
point++;
return b&0xff;
}
else if (len>0)
{
byte b = buffer[point];
len--;
point++;
return b&0xff;
}
return -1;
}
public void myClose()throws IOException
{
is.close();
}
}
11111111-111111110000000000101001001010100101010010101001010
byte: -1 ---> int : -1;
00000000 00000000 00000000 11111111 255
11111111 11111111 11111111 11111111
11111111 -->提升了一个int类型 那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。
那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?
11111111 11111111 11111111 11111111
&00000000 00000000 00000000 11111111
------------------------------------
00000000 00000000 00000000 11111111
0000-0001
1111-1110
000000001
1111-1111 -1
结论:
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。
而在写入数据时,只写该int类型数据的最低8位。
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net