字节流分为两种:InputStream(输入字节流)、OutputStream(输出字节流);
如何区分是该用InputStream,还是OutputStream:
从某个文件中读取数据到终端中用InputStream;终端向某个文件中输入数据用OutputStream;而这个终端在写代码时,可以理解为:你写代码时所用的这个软件界面;
InputStream对象从文件中读取数据的方法是read,OutputStream对象向文件中输入数据的方法是write;
InputStream的**read()**方法:
public class InputAndOut {
public static void FileToFile1(String path1,String path2){
File file1=new File(path1);
File file2=new File(path2);
FileInputStream in=null;
FileOutputStream out=null;
try {
in=new FileInputStream(file1);
out=new FileOutputStream(file2);
int value=-1;
while((value=in.read())!=-1){/*当file1中有数据可读时,读出的数据赋值给value,当没有数据可读时,返回-1*/
out.write(value);/*就将从file1文件中读出的数据写入file2中*/
}
} catch (IOException e) {
e.printStackTrace();
}finally{
/*要记得关闭数据流*/
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
InputStream的**read(byte b[])**方法:每次从文件中读取b.size()个大小的数据存放在b中;该方法返回的是读取数据的长度,将读取的数据存放在b中;当无数据可读时返回-1;
上面中try{}内部的内容可以用以下代码代替
in=new FileInputStream(file1);
out=new FileOutputStream(file2);
int len=-1;
/*读取数据,也可以不一个一个字节的读取,可以使用缓存方式读取和写入*/
byte[] buff=new byte[3];//当然可以写为1024
while((len=in.read(buff))!=-1){/*每次读取3个字节存放在buff中,返回的len是读取的数据的长度*/
out.write(buff);/*将buff中的数据写入file2中*/
或者是**read(byte b[],int off,int len)**方法:
off代表起始位置,len代表长度;
in=new FileInputStream(file1);
out=new FileOutputStream(file2);
int len=-1;
/*读取数据,也可以不一个一个字节的读取,可以使用缓存方式读取和写入*/
byte[] buff=new byte[3];//当然可以写为1024
while((len=in.read(buff))!=-1){/*每次读取3个字节存放在buff中,返回的len是读取的数据的长度*/
out.write(buff,0,len);/*将buff中的从[0,len)之间的数据写入file2中*/
OutputStream的write()方法,括号中参数也是很多的:
FileOutputStream out=null;
out=new FileOutputStream(file);
out.write(1);//int型
out.write('A');//byte型
byte[] bytes=new byte[]{'a','b','c','d'};
out.write(bytes);//byte[]型
out.write(bytes,1,3);//byte[]某个范围中[1,3)之间的数据
OutputStream还继承了AutoCloseable接口,可以自动关闭字节流:
public abstract class OutputStream implements Closeable, Flushable
InputStream还继承了Closeable接口,而Closeable接口又继承了AutoCloseable,所以InputStream也是可以自动关闭字节流的:
public abstract class InputStream implements Closeable
public interface Closeable extends AutoCloseable
继承了AutoCloseable接口的类是怎么实现的呢:
//继承了AutoCloseable 接口的类
public class AutoClose implements AutoCloseable {
public void print(){
System.out.println("打印");
}
@Override
public void close() throws Exception {
System.out.println("打印完毕");
}
public static void main(String[] args) {
AutoClose autoClose=new AutoClose();
autoClose.print();
try {
autoClose.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("++++++++++++++++++++++++");
//但是,如果将AutoClose创建对象的过程放在try()括号中,则clos会自动调用
try(AutoClose p=new AutoClose()){
p.print();
}catch (Exception e){
e.printStackTrace();
}
}
}
结果:
从而可以发现继承了AutoCloseable 接口的类是可以自动关闭流的,只是要将创建对象的过程放在try()中;
所以:
File infile = new File("D:/test/input.txt");
File outfile = new File("D:/test/output.txt");
/*将输入流、输出流的创建过程写在try()内,中间用;隔开*/
try (InputStream in = new FileInputStream(infile);
OutputStream out = new FileOutputStream(outfile)) {
int value=-1;
while((value=in.read())!=-1) {
out.write(value);
}
out.write(new byte[]{'a', 'b', 'c'});
} catch (IOException e) {
e.printStackTrace();
}
但是,这样子会造成混乱,不知道到底关闭流了没,所以不建议这样使用,还是自己手动关闭流比较好;