一:IO流
IO流:即InputOutput的缩写
特点:
1)IO流用来处理设备间的数据传输。
2)Java对数据的操作是通过流的方式。
3)Java用于操作流的对象都在IO包中。
4)流按操作数据分为两种:字节流和字符流。
5)流按流向分为:输入流和输出流。
注意:流只能操作数据,而不能操作文件,File可以操作文件和文件夹,后面会讲到。。
常用基类:
1)字节流的抽象基流:InputStream和OutputStream
2)字符流的抽象基流:Reader和Writer
二,字符流
1,字符流只用于处理文字数据,而字节流可以处理媒体数据
专门用于操作文件的Writer子类对象:FileWriter。后缀是父类名。前缀名是流对象的功能。该流对象一被初始化,就必须有被操作的文件存在。
2,字符流的读写
写入流步骤
a、创建一个FileWriter对象,该对象一被初始化,就必须要明确被操作的文件。且该目录下如果已有同名文件,则同名文件将被覆盖。其实该步就是
在明确数据要存放的目的地。
b、调用write(String s)方法,将字符串写入到流中。
c、调用flush()方法,刷新该流的缓冲,将数据刷新到目的地中。
d、调用close()方法,关闭流资源。但是关闭前会刷新一次内部的缓冲数据,并将数据刷新到目的地中。
close()和flush()区别:
flush()刷新后,流可以继续使用;
而close()刷新后,将会关闭流,不可再写入字符流。
读取流步骤
1)创建一个文件读取流对象,和指定名称的文件相关联。要保证该文件已经存在,若不存在,将会发生异常FileNotFoundException。
2)调用读取流对象的read()方法。read():一次读一个字符,且会继续往下读。
第一种方式:读取单个字符。第二种方式:通过字符数组进行读取。
3)读取后要调用close方法将流资源关闭。
三,字符缓冲区
字符流的缓冲区——BufferedReader和BufferedWriter
1,缓冲区的出现:提高了流的读写效率,所以在缓冲区创建前,要先创建流对象。即先将流对象初始化到构造函数中。
2,缓冲技术原理:此对象中封装了数组,将数据存入,再一次性取出。
3,写入流缓冲区BufferedWriter的步骤:
1)创建一个字符写入流对象。
2)为了提高字符写入流效率。加入缓冲技术。只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
3)调用write方法写入数据到指定文件
只要用到缓冲区,就要记得刷新。(关闭流同样会刷新,但为了排除意外事故,保证数据存在,建议写入一次就刷新一次)
4)其实关闭缓冲区,就是在关闭缓冲区中的流对象。
小知识:BufferedWriter缓冲区中提供了一个跨平台的换行符:newLine();可以在不同操作系统上调用,用作数据换行。
4,读取流缓冲区BufferedReader
该缓冲区提供了一个一次读一行的方法readLine,方便于堆文本数据的获取,当返回null时表示读到文件末尾。readLine方法返回的时候,只返回回车符之前的数据内容。并不返回回车符。
readLine方法原理:
无论是读一行。或者读取多个字符。其实最终都是在在硬盘上一个一个读取。所以最终使用的还是read方法一次读一个的方法。
步骤:
1)创建一个读取流对象和文件相关联
2)为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲区对象的构造函数。
3)调用该缓冲区提供的readLine方法一行一行读取,如果到达文件末尾,则返回null
4)关闭流资源
案例:
package com.cn.buffereddemo;
import java.io.BufferedReader;
import java.io.FileReader;
/*
* 字符读取缓冲对象:BufferedReader:
*该对象提供了一个readLine():这个方法每次读取一行,方便对文件的读取。
*/
public class BufferedReaderDemo {
public static void main(String[] args) {
FileReader fr=null;
BufferedReader bufr=null;
try{
//创一个文件读取流对象,同时指定要被读取的文件
fr=new FileReader("C://buf.txt");
//创建一个字符读取缓冲对象,将流对象作为参数传递给缓冲对象的构造函数里
bufr=new BufferedReader(fr);
String s=null;
//字符读取缓冲对象提供的readLine():返回值是String,当读到末尾的时候返回值为null.
while((s=bufr.readLine())!=null){
System.out.println(s);
}
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException("出现错误了");
}finally{
try{
if(bufr!=null){
bufr.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
五,字节流
概述
1,字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件。
2,由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作。
3,读写字节流:InputStream 输入流(读)
OutputStream 输出流(写)
4,InputStream特有方法:
int available();//返回文件中的字节个数
六,字节流缓冲区
读写特点:
read():会将字节byte型值提升为int型值
write():会将int型强转为byte型,即保留二进制数的最后八位。
原理:将数据拷贝一部分,读取一部分,循环,直到数据全部读取完毕。
1)先从数据中抓取固定数组长度的字节,存入定义的数组中,再通过然后再通过read()方法读取数组中的元素,存入缓冲区。
2)循环这个动作,直到最后取出一组数据存入数组,可能数组并未填满,同样也取出包含的元素。
3)每次取出的时候,都有一个指针在移动,取到数组结尾就自动回到数组头部,这样指针在自增。
4)取出的时候,数组中的元素在减少,取出一个,就减少一个,直到减到0即元素取完。
5)当文件中的全部数据都被读取出时,read()方法就返回-1。
package com.cn.stream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 复制一张图片是需要使用字节流
* 1.思路:字节读取流对象读取一张图片
* 2.通过字节写入流再去硬盘里写入一张图片
* 3.关闭流对象
**/
public class CopyPhotoDemo {
public static void main(String[] args) {
FileInputStream fis=null;
FileOutputStream fos=null;
try{
//创建一个字节读取流对象,并且指定要操作的文件
fis=new FileInputStream("c://1.jpeg");
//创建一个字节写入流对象,并指明目的地
fos=new FileOutputStream("c://2.jpeg");
byte[] b=new byte[1024];
int len=0;
while((len=fis.read(b))!=-1){
fos.write(b, 0, len);
}
}catch(IOException e){
e.printStackTrace();
}finally{
//关闭流对象
try{
if(fos!=null){
fos.close();
}
}catch(Exception e){
e.printStackTrace();
}
try{
if(fis!=null){
fis.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
七,流操作规律
标准输入输出流
System.in:对应的标准输入设备,键盘。
Ssytem.out:对应的是标准的输出设备,控制台。
System.in的类型是InputStream.
System.out的类型是PrintStream是OutputStream的子类FilterOutputStream的子类。
转换流
转换流的由来:
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转换流一样。
流操作规律
1, 明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer
2,操作的数据是否是纯文本。
是:字符流
否:字节流
3,当体系明确后,再明确要使用哪个具体的对象。通过设备来进行区分:
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
转换流什么使用?
字符和字节之间的桥梁。通常,涉及到字符编码转换时,需要用到转换流。
案例:
package com.sytemin;
import java.io.InputStream;
/*
* 将字节流转成字符流
*/
public class InputSteamReaderDemo {
public static void main(String[] args) throws Exception{
//创建一个键盘输入流对象
InputStream in=System.in;
StringBuilder sb=new StringBuilder();
while(true){
int ch=in.read();
//如果读取/r,则退出本次循环
if(ch=='\r'){
continue;
}
//如果读取到/n,那么先判断是不是读取到了over,如果是,则停止,不是就得打印出来
if(ch=='\n'){
String s=sb.toString();
if("over".equals(s)){
break;
}else{
System.out.println(s.toUpperCase());
//每次打印完以后,清空一下缓存
sb.delete(0, sb.length());
}
}else{
sb.append((char)ch);
}
}
//关闭资源
in.close();
}
}
八:File操作
1、IO的概述和File方法
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
File类在整个IO包中与文件本身有关的操作类,所有的与文件本身有关指的是创建、删除文件等操作。在java.io包中的File类本身是一个跨平台的文件操作类,所以在操作中要更多的考虑到各个操作系统的区别。
File 即指文件也指文件夹。
File对象:对文件夹或者文件的操作.
File.separator():跨平台的目录分割符方法,不管在哪个系统之下都可以执行。
代替了斜杠。\
File对象
1.创建
boolean createNewFile(): 检验是否创建文件成功,但是如果文件夹也有那个重名的文件,则创建失败。和输出流不一样,输出流对象,目录下如果有这个文件了,再去创建就会覆盖。
mkdir( ):创建文件夹
Mkdirs() :创建多级文件夹
2.删除
删除文件
boolean t=f.delete();
退出时删除文件,通常用于程序发生异常时,无法继续执行下,但是又要删除文件的时候,在程序退出就可以把文件删除。
f.deleteOnExit();
3.获取
getName();获取文件的名字
getPath():获取文件的相对路径
getParemt():获取文件的上一层目录
renameTo():将文件重命名
4.判断
boolean exists() :判断文件是否存在。
判断文件对象是文件还是文件夹,必须先去判断该文件对象是否存在。
isFile():是否是文件
isDirectory():是否是目录
isHidden():是否是隐藏文件
5. 递归:
因为目录中还有目录,只要使用同一个列出目录功能函数完成即可。
在列出过程中出现的还是目录的话,只要调用本功能函数即可
也就是函数本身调用自己
我们将这样的方法称之为递归。
使用递归:函数本身调用函数自己,即是使用了递归。
6.打印流:可以将数据原样打印出去
printStream :字节打印流
构造函数的参数类型可以是字节流,file对象,字符串
printWritet:字符打印流
构造函数的参数类型可以是字节输出流,字符输出流,file对象,字符串
File类构造方法和字段摘要
static String pathSeparator 路径分隔符,window下是";"。
static char pathSeparatorChar 路径分隔符,window下是";"。
static String separator 路径分隔符,window下是"\"。
static char separatorChar 路径分隔符,window下是"\"。
File(File parent, String child) 根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent, String child) 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(URI uri) 通过将给定的 file: /URI 转换为一个抽象路径名来创建一个新的 File 实例。
File的相关方法
String getName():返回文件名或路径名(若是路径,返回最后一级子路径名)
String getPath():返回对象对应的路径名
File getAbsoluteFile():返回绝对路径
String getAbsolutePath():返回对象对应的绝对路径
String getParent():返回文件目录的上一级目录名
boolean renameTo(File newName):重命名此File对象对应的文件或目录,若重命名成功返回true;
boolean exists():判断对象对应的文件或目录是否存在;
boolean canWrite():判断对象对应文件或目录是否可写;
boolean canRead():判断对象对应文件或目录是否可读;
boolean isFile():判断对象是文件,不是目录;
boolean isDirectory() 判断对象的文件是否是一个目录;
boolean isAbsolute() 判断对象对应文件或目录是否为绝对路径名;
boolean createNewFile() 当且仅当不存在,该方法创建一个该File对象所指定的新文件,创建成功返回true。
boolean delete():删除File对象所对应的文件或路径;
boolean mkdir() 创建File对象所对应的目录,调用该方法的File对象必须对应路径,而不是文件。
String[] list():列出File对象的所有子文件名和路径名。
File[] listFiles():列出File对象的所有子文件和路径。
static File[] listRoots():列出系统所有的根路径;
案例:使用递归查找文件夹下的所有目录
package com.cn.filedemo;
import java.io.File;
public class FileDemo5 {
/*
* 列出当前目录下的文件以及子目录下的文件和内容
* 因为目录中还有目录,只要使用同一个列出目录功能函数完成即可。
* 在列出过程中出现的还是目录的话,只要调用本功能函数即可
* 也就是函数本身调用自己
* 我们将这样的方法称之为递归。
* 使用递归:函数本身调用函数自己,即是使用了递归。
*/
public static void main(String[] args) {
File f=new File("d://computer");
method_1(f);
}
//获取一个目录
public static void method_1(File f){
//查找该目录下有多少个目录
File[] fl=f.listFiles();
System.out.println(fl);
for (int i = 0; i < fl.length; i++) {
//判断是目录还是文件,如果还是目录,就继续查找子目录。否则打印文件的文件名
if(fl[i].isDirectory()){
method_1(fl[i]);
}else{
System.out.println(fl[i]);
}
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}