-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
一、IO流
IO流:
字节流
字节输入流 读取数据 InputStream
字节输出流 写入数据 OutputStream
字符流
字符输入流 读取数据 Reader
字符输出流 写入数据 Writer
IO流的概述:
Java程序通过流来完成输入和输出,流是输入或输出信息的抽象。流通过Java的输入/输出系统与外设连接进行数据通信。流是抽象的对象,具体实现代码在java.io包中。
IO流的常用基类:
1、 字节流的抽象基流:InputStream和OutputStream
2、 字符流的抽象基流:Reader和Writer
二、字符流
通过字符流写入输出数据,通过查看API,我们发现,Writer是一个抽象类。所以,使用他的子类FileWriter
FileWriter构造方法:FileWriter(File file)
FileWriter(String fileName)
字符输出流操作步骤:
A:创建字符输出流对象
B:调用对象的写入数据方法,并刷新缓冲区
C:释放资源
问题1:为什么FileWriter没有无参构造方法?
因为写数据的时候,一定要明确写道哪里去。
问题2:flush()和close()的区别?
flush():只刷新缓冲区,流对象还可以继续使用。
close():先刷新缓冲区,在关闭流对象。流对象不可以继续被使用。
问题3:难道每次调用方法的时候,都需要刷新吗?或者说,不用刷,直接等到close()来解决,行不行?
这两种方式都不可取。
写入数据的方式,有5种。
write(int ch)
write(char[] chs,int index,int len)
write(char[] chs)
write(String str,int index,int len)
write(String str)
数据没次都把以前的给覆盖了,如果我想追加写入,怎么办?
构造的时候,用带两个参数的。
public FileWriter(String fileName,boolean append)
字符输入流读取数据步骤:
A:创建字符输入流对象
B:调用读取数据功能,并显示
C:释放资源
一次读取一个字符数组
public int read(char[] cbuf)每次读取数据,把数据存储到字符数组中,返回值是实际读取长度。
通过字节流往文件中写数据。
字节输出流操作步骤:
A:创建字节输出流对象
B:调用写数据的方法
C:释放资源
字节输入流操作步骤:
A:创建字节输入流对象
B:调用读取数据的方式,并显示
C:释放资源
字符缓冲流:提高了流的读写效率,所以在缓冲区创建前,要先创建流对象。即先将流对象初始化到构造函数中。
字符缓冲流读取数据
构造方法:BufferedWriter(Writer out)
普通方法:
BufferedWriter:
public void newLine():根据系统平台写入行分隔符
BufferedReader:
public String readLine():一次读取一行的数据。但是不包含换行符。
练习:把D盘下所有.java文件改名.jad并复制到D盘.jad文件下
public class CopyCopyCopy {
public static void main(String[] args) throws IOException {
File srcFile=new File("d:\\java");
File[]fileArray=srcFile.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
// TODO Auto-generated method stub
return new File(dir,name).isFile()&&name.endsWith(".java");
}
});
File deskFile=new File("d:\\jad");
if(!deskFile.exists()){
deskFile.mkdirs();
}
for(File file:fileArray){
String name=file.getName();
String newName=name.replace(".java", ".jad");
File newFile=new File(deskFile,newName);
BufferedReader br=new BufferedReader(new FileReader(file));
BufferedWriter bw=new BufferedWriter(new FileWriter(newFile));
String line=null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
}
}
二、字节流
1、字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件。
2、因为字节流操作的是图片,视频,音频等媒体文件这些数据都是以字节存储的,所以字节流对象可以直接对文件写入数据,不用再刷新动作
3、读写字节流 输入流(读InputStream ) 输出流(写OutputStream)
字节流缓冲区
和字符流缓冲区一样,提高了效率。
自定义读取字节流缓冲区
需求:根据字节流缓冲区的原理,自定义一个字节流缓冲区。
注意:
1、字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。而在写入数据时,只写该int类型数据的最低8位。
2、byte类型的-1提升为int类型时还是-1。原因:因为在bit8个1前面补的全是1导致的。如果在bit8个1前面补0,即可以保留原字节数据不变,又可以避免-1的出现。这时将byte型数据&0xff即255即可。
代码:
三、标准输入输出流
System.in:对应的标准输入设备,键盘。
Ssytem.out:对应的是标准的输出设备,控制台。
System.in的类型是InputStream.
System.out的类型是PrintStream是OutputStream的子类FilterOutputStream的子类。
整行录入
当使用输入流进行键盘录入时,只能一个字节一个字节进行录入。为了提高效率,可以自定义一个数组将一行字节进行存储。当一行录入完毕,再将一行数据进行显示。这种正行录入的方式,和字符流读一行数据的原理是一样的。也就是readLine方法。
那么能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?readLine方法是字符流BufferedReader类中方法。而键盘录入的read方法是字节流InputStream的方法。
那么能不能将字节流转成字符流再使用字符流缓冲区的readLine方法呢?这就需要用到转换流了。
四、转换流
1转换流的由来:
a、字符流与字节流之间的桥梁
b、方便了字符流与字节流之间的操作
转换流的应用:
字节流中的数据都是字符时,转成字符流操作更高效。
InputStreamReader将字节流通向字符流
a、获取键盘录入对象。
InputStream in=System.in;
b、将字节流对象转成字符流对象,使用转换流。
InputStreamReaderisr=new InputStreamReader(in);
c、为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
BufferedReaderbr=new BufferedReader(isr);
//键盘录入最常见写法
BufferedReaderin=new BufferedReader(new InputStreamReader(System.in));
OutputStreamWriter字符流通向字节流
字符通向字节:录入的是字符,存到硬盘上的是字节。步骤和InputStreamReader转换流一样。
public class SystemInDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
InputStream is = System.in;
/*
* 这个时候,我们拥有的是标准键盘录入。
* 而字节的输入流有两种读取方式:
* 方式1:一次读取一个字节,但是,这样的话,我们每次都需要对读取到的数据进行保存,将来判断是否一行结束,麻烦。
* 方式2:一次读取一个字节数组,但是,这个时候,最大的问题是,数组的长度定义为多大不好确定。
* 所以,我们觉得这两种方式都不够好。
* 我们就想有没有这样的一种方案,直接一次读取一行数据。
* 我们就想到了字符缓冲输入流的:readLine()方法。
* 我们就按照默认的写法去做了这件事情,但是,发现报错了。
* 因为BufferedReader需要的是一个字符流,而你现在有的确实一个字节流。
* 假如能有一个流对象能够实现字节流转成字符流,我们就可以用了。
* 转换流:InputStreamReader
*/
//InputStreamReader(InputStream in)
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
// 封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
String line = null;
while((line=br.readLine())!=null){
//只要是键盘录入,就的自己定义结束条件
if("over".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
}
public class SystemOutDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
// 封装目的地
OutputStream os = System.out;
/*
* 这个时候,往控制台写数据的时候,我们又的方式一次写一个字节,或者一次写一个字节数组。
* 但是,我们获取到的确实一个字符串数据。
* 所以,我们就想能不能直接写一个字符串在控制台呢?
* A:把字符串转换字节数组输出,但是,不满足我的要求。
* B:使用字符缓冲流写出一个字符串。
*/
//能实现,但是不满足我的要求
// String line = null;
// while((line=br.readLine())!=null){
// os.write(line.concat("\r\n").getBytes());
// }
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String line = null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
System.out.println();
bw.close();
br.close();
}
}