流的分类:
- 按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
- 按数据流的流向不同分为:输入流,输出流
- 按流的角色的不同分为:节点流,处理流
● 输入流input::读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
● 输出流output:将程序(内存)数据输出到磁盘、光盘等存储设 备中。
二、流的体系
抽象的基类 节点流(文件流) 处理流
InputStream FileInputStream BufferedInputStream
OutputStream FileOutputStream BufferedOutputStream
Reader FileReader BufferedReader
Writer FileWriter BufferedWriter
字符流和字节流的选择
- 对于文本文件(.txt,.java,.c,.cpp),使用字符流处理
- 对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字节流处理
字符输入流:
@Test //读取文本类文件的内容并输出到控制台public void testReadPlus(){
FileReader fr=null;
try {
File file=new File("hello.txt");
fr=new FileReader(file);
//读入操作 read(char cbuf[]):每次读入 cbuf数组中的字符个数,若读到尾部,返回-1
char[] charArr=new char[5];
int len;
while ((len=fr.read(charArr))!=-1){
//正确写法
for (int i = 0; i <len ; i++) {
System.out.print(charArr[i]);
}
//将字符数组按照指定位置转化为String字符串
String s=new String(charArr,0,len);
//len=fr.read(charArr);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭资源
if (fr!=null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1
- 异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理
- 读入的文件一定要存在,否则就会报FileNotFoundException。
字符输出流
- 输出操作:对应的File可以不存在。且不会报异常
- File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。
==>File对应的硬盘中的文件如果存在:- 如果流使用的构造器是:FileWriter(file,false) / FileWriter(file):对原有文件的覆盖
- 如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有文件末尾追加内容
- File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。
public void testWriter(){ FileWriter fw=null;
try{
File file=new File("hello.txt");
fw=new FileWriter(file,true);//此处参数填入true,不会对原有文件覆盖,而是将文本添加到文件末尾
fw.write("今天天气不错!");
fw.write("人要有梦想。");
fw.write("我的梦想是搞钱");
}catch (Exception e){
e.printStackTrace();
}finally {
if (fw!=null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符输入输出流结合:
File file=new File("hello.txt"); File file1=new File("hi.txt");
FileWriter fw=new FileWriter(file1,true);
char[] chars=new char[5];
FileReader fr=new FileReader(file);
int len;
while ((len=fr.read(chars))!=-1){
for (int i = 0; i <len ; i++) {
fw.write(chars[i]);
}
}
fw.close();
fr.close();
字节流输入输出结合:
public void testInputAndOutputStream(){ long start = System.currentTimeMillis();//获取运行开始时间戳
FileInputStream fin=null;
FileOutputStream fos=null;
try{
File srcfile = new File("C:\\Users\\19358\\Desktop\\io_1.mp4");
File descfile = new File("C:\\Users\\19358\\Desktop\\io_copy.mp4");
//1、造文件
fin=new FileInputStream(srcfile);
fos=new FileOutputStream(descfile);
//2、造流
byte[] bytes=new byte[1024];
int len;
while ((len=fin.read(bytes))!=-1){
fos.write(bytes,0,len);
//4、复制文件,读写操作 }
}catch (Exception e){
e.printStackTrace();
}finally {
fos.close();}
long end=System.currentTimeMillis();//获取运行结束时间戳
System.out.println(end-start);//计算运行时间(ms)
}
缓冲流:
- 为了提高数据读写的速度,Java API提供了带缓冲(缓存)功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,默认使用8192个字节(8Kb)的缓冲区。
缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:BufferedInputStream BufferedReader
BufferedOutputStream BufferedWriter
- 关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流
public void testWordCount(){ FileReader fr=null;//读取文件
BufferedWriter br=null; //获取的结果放进一个文件中
try{
//1、创建map集合
Map<Character,Integer> map=new HashMap<>();
//2、遍历读取的每一个字符,和出现次数放在map中
fr=new FileReader("D:\\java2112\\src\\com\\day14\\ex\\PicTest.java");
int c=0;
while ((c=fr.read())!=-1){
//还原为原来的字符
char ch= (char) c;
//判断ch在map结合在是否出现
if (map.get(ch)==null){
map.put(ch,1);
}else {
map.put(ch,map.get(ch)+1);
}
}
//将map内容写在count.txt文本
br=new BufferedWriter(new FileWriter("count.txt"));
//遍历map,将map的key和value写在文件
Set<Map.Entry<Character, Integer>> entries =
map.entrySet();
Iterator<Map.Entry<Character, Integer>> iterator =
entries.iterator();
while (iterator.hasNext()){
Map.Entry<Character, Integer> entry = iterator.next();
switch (entry.getKey()){
case ' ':
br.write("空格:"+ entry.getValue());
break;
case '\t':
br.write("tab键:"+ entry.getValue());
break;
case '\n':
br.write("换行:"+ entry.getValue());
break;
case '\r':
br.write("回车:"+ entry.getValue());
break;
default:
br.write(entry.getKey()+":"+ entry.getValue());
break;
}
br.newLine();//换行
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (br!=null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}