I/O流操作中,如何区分输入流和输出流呢?
I/O流是相对于计算机内存来说的,
输入流,就是将文件中的内容输入到内存中,让后显示出来,所以输入流可以用来读取数据。
输出流,就是讲数据从内存当中输出到文件当中,给某个文件加上内容,所以输出流可以用来添加文件的内容。
基本的字节流:一次读取一个字节/一次读取一个字节数组
字节缓冲流:一次读取一个字节/一次读取一个字节数组
字符转换流:InputStreamReader(InputStream in)
OutputStreamWriter(OutputStream out)
一次读取一个字符/一次读取一个字符数组
转换流的便捷类
FileReader(String name)
FileWriter(String writer)
一次读取一个字符/一次读取一个字符数组
BufferedReader/BufferedWriter
一次读取一个字符/一次读取一个字符数组
特有功能一次读取一行内容
成员方法:
创建/删除/重名
public boolean createNewFile() throws IOException :表示创建文件 :如果不存在,则创建
public boolean mkdir():创建文件夹,如果不存在,则创建;否则就返回false
public boolean mkdirs():创建多个文件,如果父目录不存在,则创建
public boolean delete():删除文件或者文件夹(如果删除文件夹,文件夹必须为空目录)
public boolean renameTo(File dest):重命名
判断功能:
public boolean canRead()是否可读
public boolean canWrite()是否可写
public boolean exists():是否存在
public boolean isFile():是否是文件
public boolean isDirectory():是否是文件夹
public boolean isHidden():是否隐藏public class FileDemo2 { public static void main(String[] args) { //创建File对象,描述当前项目下的aaa.txt文件 File file = new File("aaa.txt") ; System.out.println(file.canRead()); System.out.println(file.canWrite()); System.out.println(file.exists()); System.out.println(file.isDirectory());//false System.out.println(file.isFile()); System.out.println(file.isHidden()); System.out.println(file.length()); System.out.println(file.getName());
高级获取功能:
public long length()
public String getName():获取抽象路径 名所表示的文件或者目录的名称
public File[] listFiles():获取某个目录下的所有的文件以及文件夹的File数组
public String[] list():获取某个抽象路径名所表示的文件以及目录的字符串数组需求:
获取D盘下的所有的文件夹以及文件的名称....
public class FileDemo2 { public static void main(String[] args) { // public File[] listFiles():获取某个目录下的所有的文件以及文件夹的File数组 //描述D盘 File file2 = new File("d://") ; File[] fileArray = file2.listFiles(); //防止空指针异常 if(fileArray!=null){ for(File f :fileArray){ System.out.println(f.getName()); } } System.out.println("----------------------------------"); //public String[] list():获取某个抽象路径名所表示的文件以及目录的字符串数组 String[] strArray = file2.list(); if(strArray!=null){ for(String s:strArray){ System.out.println(s); } }
需求:
1.获取D盘下所有的以.jpg结尾的文件
分析:
(1)描述下D盘
(2)public File[] listFiles():获取D盘下的所有的文件以及文件夹的File数组
(3)对获取到的数组进行非判断,如果不为null,再去判断
(4)判断File是一个文件
(5)判断:文件必须以.jpg结尾;String类 endsWith(".jpg")public class FileTest { public static void main(String[] args) { //1)描述D盘 File file = new File("D://") ; //2)获取盘符下的所有的文件以及文件夹的File数组 File[] fileArray = file.listFiles();//这一步并没有直接获取到要的.jpg文件 //后面一些判断 if(fileArray!=null){ for(File f:fileArray){ //判断f是文件 if(f.isFile()){ //是文件 //判断它的名称是否以.jpg结尾 if(f.getName().endsWith(".jpg")){ System.out.println(f.getName()); } } } } } }
2.使用过滤器[文件名称过滤器FilenameFilter:接口]
成员方法:
boolean accept(File dir,String name):测试指定文件是否包含在文件列表中,返回如果true,将文件添加到文件列表中.
(1)描述下D盘
(2) public File[] listFiles(FilenameFilter filenamefilter):
获取D盘下的File数组的时候,就已经指定文件进行过滤.public class FileTest { public static void main(String[] args) { File srcFile = new File("D://") ; //获取当前D盘下的所有文件以及文件夹File数组,并进行文件名过滤 //public File[] listFiles(FilenameFilter filter) File[] files = srcFile.listFiles(new FilenameFilter() {//接口的匿名内部类 @Override public boolean accept(File dir, String name) { //返回true:表示将指定文件添加列表文件中 //描述文件所表示抽象路径File File file = new File(dir, name); //两个条件:file是文件并且file的文件名称以".jpg结尾" return file.isFile() && file.getName().endsWith(".jpg"); } }); if(files!=null){ for(File f :files){ System.out.println(f.getName()); } } } }
二.方法递归:方法调用方法本身的一种现象(并非是方法嵌套方法 )
前提条件
(1)必须有一个成员方法
(2)必须有方法递归的出口条件(结束条件),如果没有出口条件,就是死递归...
(3)还存在一定的规律
注意事项:构造方法不存在递归
需求:
使用递归方式去删除D盘某个demo文件夹中有很多个目录,每个目录中可能还有目录,删除这些所有目录中的带.java文件的文件
分析:
(1)描述下D盘下demo文件夹 File srcFile = new File("d://demo")
(2)调用递归删除方法
递归删除多级目录中的java文件
public void deleteSrcFile(File srcFile){
获取srcFile的所有的文件夹以及文件的File数组
非空判断
判断如果是文件夹
回到到2)继续调用递归删除
否则,是文件
判断是否以.java文件
最终删除文件即可 }public class DiGuiTest { public static void main(String[] args) { //描述D盘的demo文件夹 File srcFloder = new File("d://demo") ; //调用递归删除的方法 deleteFloder(srcFloder) ; } public static void deleteFloder(File srcFloder) { //获取srcFloder下的所有的文件以及文件的File数组 File[] fileArray = srcFloder.listFiles(); if(fileArray!=null){ for(File file:fileArray){ //获取到每一个file对象 //如果file是文件夹,继续回到deleteFloder(srcFloder) ; 删除文件夹 if(file.isDirectory()){ deleteFloder(file) ; }else{ //判断是文件,必须以.java结尾 文件 if(file.getName().endsWith(".java")){ //删除的同时----获取名称 System.out.println(file.getName()+"------------"+file.delete()); } } } //删除文件夹 System.out.println(srcFloder.getName()+"----"+srcFloder.delete()); } } }
三.
1.文件数据读入(FileInputStream)----->文件中的内容读入到内存(一个字节一个字节读取)
public class test1 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("F:\\Ideaproject\\Day28\\src\\lhb.txt");
int by = 0;
while ((by=fis.read()) != -1){
System.out.print((char)by);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.文件数据读入(FileInputStream)----->文件中的内容读入到内存(字节数组读取)
public class test1 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("F:\\Ideaproject\\Day28\\src\\lhb.txt");
byte[] bytes = new byte[1024];
int len = 0;
while ((len=fis.read(bytes))!= -1){
System.out.println(new String(bytes,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
四.缓冲流的特点:提供缓冲区大写:1024的8倍 还是通过底层流提高读速度(FileInputStream)
字节缓冲输入流(BufferedInputStream)
构造方法
BufferedInputStream(InputStream in) :默认缓冲区大写 (足够大了)
提供一个指定的缓冲区大小
BufferedInputStream(InputStream in, int size)(1)一个字节一个字节读取
public class test1 { public static void main(String[] args) throws FileNotFoundException { BufferedInputStream bis = null; try { bis = new BufferedInputStream(new FileInputStream("F:\\Ideaproject\\Day28\\src\\lhb.txt")); //字节读取 int by = 0; while ((by = bis.read())!=-1){ System.out.print((char) by); } } catch (IOException e) { e.printStackTrace(); }finally { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
(2)字节数组读取
public class test1 { public static void main(String[] args) throws FileNotFoundException { BufferedInputStream bis = null; try { bis = new BufferedInputStream(new FileInputStream("F:\\Ideaproject\\Day28\\src\\lhb.txt")); //字节数组读取 byte[] bytes = new byte[1024]; int len = 0; while ((len = bis.read(bytes))!=-1){ System.out.print(new String(bytes,0,len)); } } catch (IOException e) { e.printStackTrace(); }finally { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
字节缓冲输出流(BufferedOutputStream)
BufferedOutputStream(OutputStream out)
推荐使用这个:默认缓冲区大小 足够大了 8kb
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out, int size)public class test1 { public static void main(String[] args) throws IOException { BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("xaiona.txt")); bos.write("我爱你".getBytes()); bos.close(); } }
五.
FileInputStream,FileOutputStream
基本的字节流一次读取一个字节数组------共耗时116毫秒
基本的字节流一次读取一个字节-----共耗时89021毫秒
BufferedInputStream,BufferedOutputStream
缓冲流一次读取一个字节数组------共耗时47毫秒
缓冲流一次读取一个字节-------共耗时348毫秒
需求:读取D://a.mp4,将这个文件内容复制到 当前项目下的copy.mp4中(先开的后关)
public class CopyMp4 { public static void main(String[] args) { //起始时间 long start = System.currentTimeMillis() ; //copyMp4("D://a.mp4","copy.mp4") ; //copyMp4_2("D://a.mp4","copy.mp4") ; //copyMp4_3("D://a.mp4","copy.mp4") ; copyMp4_4("D://a.mp4","copy.mp4") ; //结束时间 long end = System.currentTimeMillis() ; System.out.println("共耗时"+(end-start)+"毫秒"); } //缓冲流一次读取一个字节数组 private static void copyMp4_4(String srcFile, String destFile) { BufferedInputStream bis = null ; BufferedOutputStream bos = null ; try { bis = new BufferedInputStream(new FileInputStream(srcFile)) ; bos = new BufferedOutputStream(new FileOutputStream(destFile)) ; //读写操作 byte[] bytes = new byte[1024] ; int len = 0 ; while((len=bis.read(bytes))!=-1){ bos.write(bytes,0,len); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { bos.close(); bis.close(); } catch (IOException e) { e.printStackTrace(); } } } //缓冲流一次读取一个字节 private static void copyMp4_3(String srcFile, String destFile) { BufferedInputStream bis = null ; BufferedOutputStream bos = null ; try { bis = new BufferedInputStream(new FileInputStream(srcFile)) ; bos = new BufferedOutputStream(new FileOutputStream(destFile)) ; //读写操作 int by = 0 ; while((by=bis.read())!=-1){ bos.write(by); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { bos.close(); bis.close(); } catch (IOException e) { e.printStackTrace(); } } } //基本的字节流一次读取一个字节数组 public static void copyMp4_2(String srcFile,String destFile){ //封装源文件和目的地文件 FileInputStream fis = null ; FileOutputStream fos = null ; try { fis = new FileInputStream(srcFile) ; fos = new FileOutputStream(destFile) ; //读写复制 byte[] bytes = new byte[1024] ; int len = 0 ;//实际字节数 while((len=fis.read(bytes))!=-1){ fos.write(bytes,0,len); //强制输出流将缓冲的这字节数写出来 fos.flush(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { fos.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); } } } //基本的字节流一次读取一个字节 public static void copyMp4(String srcFile, String destFile) { //封装源文件和目的地文件 FileInputStream fis = null ; FileOutputStream fos = null ; try { fis = new FileInputStream(srcFile) ; fos = new FileOutputStream(destFile) ; //读写复制 int by = 0 ; while((by=fis.read())!=-1){ fos.write(by); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { fos.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
六.字符流的出现是在字节流的后面,可以解决中文乱码问题
Writer:抽象类
提供子类:字符转换输出流: 字节输出流通向字符输出流的桥梁
构造方法
OutputStreamWriter(OutputStream out) :使用平台默认编码集写入数据
OutputStreamWriter(OutputStream out, String charsetName) :使用指定的字符集进行编码 写入数据public class WriterDemo { public static void main(String[] args) throws Exception { //创建字符缓冲输出流对象 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt")) ;//使用平台的默认编码集(utf-8) //写入数据 /** * write(String str) * write(int ch):写入字符: 字符--->对应的ASCII码表 * write(char[] ch) * write(char[] ch,int off,int len) * write(String str,int off,int len) */ osw.write("hello,字符流我来了"); osw.write(97); char[] chs = {'A','B','C','D','E'} ; osw.write(chs); osw.write(chs,2,2); //使用flush():刷新字符输出流 osw.flush(); //关闭资源,释放相关的资源 osw.close(); //关闭之前,flush } }
Reader:抽象类
具体的子类:字符转换输入流 InputStreamReader
构造方法
InputStreamReader(InputStream in) :使用平台默认解码集进行读
InputStreamReader(InputStream in,String charset) :使用指定的解码集进行读public class test1 { public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream("f:\\lhb.txt")); char[] chars = new char[1024]; int len = 0; while ((len=isr.read(chars))!=-1){ System.out.println(new String(chars,0,len)); } isr.close(); } }
需求:
当f盘的lhb.txt文件 复制到 当前项目下的lhb2.txt
针对文本文件:优先采用字符流public class test1 { public static void main(String[] args) throws IOException { FileReader srcfile = new FileReader("f:\\lhb.txt"); FileWriter targerfile = new FileWriter("lhb2.txt"); /*int by = 0; while ((by=srcfile.read())!=-1){ targerfile.write(by); targerfile.flush(); }*/ char[] chars = new char[1024]; int len = 0; while((len = srcfile.read(chars))!=-1){ targerfile.write(chars,0,len); targerfile.flush(); } targerfile.close(); srcfile.close(); } }
BufferedReaer/BufferedWriter :读写复制操作
一次读取一个字符
一次读取一个字符数组
特有功能:
利用BufferedReader的readLine()读取一行
利用BufferedWriter写一行,然后换行一个文本文件读写复制:
阻塞流 (传统的IO流)
当一个线程如果操作的是读的动作, read(byte[] byte/char[] ..)/readLine():都属于阻塞式方法
另一个线程如果操作的是写的动作, 读的线程如果开始读,这边写的线程才能开始进行写的复制操作需求:
当f盘的lhb.txt文件 复制到 当前项目下的lhb2.txt
public class test1 { public static void main(String[] args) { BufferedReader br = null; BufferedWriter bw = null; try { br = new BufferedReader(new FileReader("f://lhb.txt")); bw = new BufferedWriter(new FileWriter("lhb2.txt")); String line = null; while ((line=br.readLine())!=null){ bw.write(line); bw.newLine(); bw.flush(); } } catch (IOException e) { e.printStackTrace(); }finally { try { bw.close(); br.close(); } catch (IOException e) { e.printStackTrace(); } } } }
七. 将两个以上的文件进行读取
public SequenceInputStream(Enumeration<? extends InputStream> e)
Vector<InputStream>
add(添加多个字节输入流对象)
需求:将f盘下的lhb.txt lhb2.txt lhb3.txt 文件进行读取,复制到当前目录下的lhb4.txtpublic class test1 { public static <vector> void main(String[] args) throws IOException { InputStream is1 = new FileInputStream("f:\\lhb.txt"); InputStream is2 = new FileInputStream("f:\\lhb2.txt"); InputStream is3 = new FileInputStream("f:\\lhb3.txt"); Vector<InputStream> vector = new Vector<>(); vector.add(is1); vector.add(is2); vector.add(is3); Enumeration<InputStream> enumeration = vector.elements(); //创建合并流对象 封装源文件 SequenceInputStream sis = new SequenceInputStream(enumeration); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("lhb4.txt")); int by = 0; while((by=sis.read())!=-1){ bos.write(by); bos.flush(); } bos.close(); sis.close(); } }