简介
java IO操作中,对数据的传输主要是字节流和字符流2种方式,下面我们分别了解一下字节流和字符流的操作和优缺点
由于下面4个都是抽象类,所以代码例子都是使用对应的文件类(FileXXXX)实现的
字节流
顾名思义,就是用字节(byte)的方式传输数据,数据传输自然对应着输入(InputStream)和输出(OutputStream),这里输入和输出对应的对象是服务器(平时,也就是你的电脑),拿文件举例:我们代码中的文字存入磁盘的文件中,就称为输出,反之,则为输入。
OutputStream
以字节的方式作为输出是一个抽象类,不能直接实例化,他有众多子类,比如我们常用的FileOutputStream继承了2个接口,分别是Closeable(Closeable又继承了AutoCloseable)、另外一个接口Flushable
AutoCloseable:可以利用-try()-实现自动关闭资源Flushable中的flush()方法可以将内存中缓存的数据强制刷新,比如将内存中缓存的数据,在未关闭钱,强制刷新到文件中。
常用方法
output.write(int b):输出单个字节output.write(byte[] b):输出一组字节数据output.write(byte[] b,int off,int len):输出一组数据中的部分字节数据下面是FileOutPutString的使用例子,1.7之后,实现了自动关闭
File file
= new File("D:" + File
.separator
+ "file" + File
.separator
+ "out" + File
.separator
+ "bridge.txt");
if(!file
.getParentFile().exists()){
file
.getParentFile().mkdirs();
}
String str
= " Hello bridge!";
try(OutputStream out
= new FileOutputStream(file
,true)){
out
.write(str
.getBytes());
}catch (IOException e
){
e
.printStackTrace();
}
InputStream
以字节的方式读取数据是一个抽象类,不能直接实例化,他有众多子类,比如我们常用的FileInputStream同样的,它也继承了Closeable,但他没有继承Flushable
常用方法
public int read();返回一个字节,当返回值为-1时,表示结束(输入的实际内容是null)public int read(byte[] data);一块一块的读取,返回的值是读取的字节的个数,小于data.length时,则表示读完了public int read(byre[],int off, int len);返回真实读取的个数,同上面一样public byte[] readAllBytes() throws IOException;:一次性,读取全部数据,当输入数据特别大的时候,谨慎使用
File file
= new File("D:" + File
.separator
+ "file" + File
.separator
+ "out" + File
.separator
+ "bridge.txt");
if(!file
.exists()){
System
.out
.println("没有找到文件");
return ;
}
String str
= " Hello bridge!";
try(FileInputStream in
= new FileInputStream(file
)){
byte[] b
= new byte[1024];
int length
= in
.read(b
);
System
.out
.println(new String(b
,0, length
));
}catch (IOException e
){
e
.printStackTrace();
}
字符流
使用字符(char)的方式传输数据,输入(Reader)和输出(Writer),字符流是JDK1.1之后才加上的。
Writer
实现了4个接口Closeable, Flushable, AutoCloseable,Appendable。前面3个,上面已经介绍过了Appendable:表示追加的意思,是jdk1.5之后提出来的,可以将字符序列和值追加到之前的对象,在多线下,需要注意线程安全问题
常用方法
write(char[] cbuf):基本的方法和OutputSteam一样,只不过换成了char类型write(String str):这个比较常用,可以直接存String类型,非常方便
代码
File file
= new File("D:" + File
.separator
+ "hello" + File
.separator
+ "bridge.txt");
if (!file
.getParentFile().exists()) {
file
.getParentFile().mkdirs();
}
Writer out
= new FileWriter(file
) ;
String str
= "正常的内容\r\n" ;
out
.write(str
);
out
.append("我要追加内容……") ;
out
.close();
Reader
实现了3个接口Closeable, AutoCloseable, Readable。前2个上面已经介绍了,Readable:表示读取的来源可以通过字符读取
常用方法
int read(char[] cbuf):基本的方法和InputSteam一样,只不过换成了char类型public long transferTo(Writer out):这个jdk10才有的,目前jdk10普及还不高,可以作为了解
代码
如果不写关闭,数据将会在内存中,并不会保存到文件中
File file
= new File("D:" + File
.separator
+ "hello" + File
.separator
+ "bridge.txt");
if (file
.exists()) {
Reader in
= new FileReader(file
) ;
char data
[] = new char[1024];
int len
= in
.read(data
) ;
System
.out
.println("读取内容:" + new String(data
,0,len
));
}
如果不写close(),我们可以使用flush()处理,但是建议关闭资源
File file
= new File("D:" + File
.separator
+ "hello" + File
.separator
+ "bridge.txt");
if (!file
.getParentFile().exists()) {
file
.getParentFile().mkdirs();
}
Writer out
= new FileWriter(file
) ;
String str
= "追加的内容" ;
out
.write(str
);
out
.flush();
总结
理解上面4个抽象类,之后的子类就很简单了在处理中文时,字符流比字节流更方便,但是,大部分情况,比如图片、视频传输还是二进制的形式,此时就得使用字节流了接下来,我们可以了解上面4个抽象类的子类了,他们的子类都有父类的特性,针对不同的场景,使用不同的子类。