黑马程序员_IO流

来源:互联网 发布:进口化妆品数据分析 编辑:程序博客网 时间:2024/06/04 19:45
----------- android培训java培训、java学习型技术博客、期待与您交流! ------------


IO的概述和File方法


IO流用来处理设备之间的数据传输
       Java对数据的操作是通过流的方式
       Java用于操作流的对象都在IO包中

 

File类在整个IO包中与文件本身有关的操作类,所有的与文件本身有关指的是创建、删除文件等操作。在java.io包中的File类本身是一个跨平台的文件操作类,所以在操作中要更多的考虑到各个操作系统的区别。

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的相关方法

1,创建。

boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。

boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。

2,删除。

boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。

3,判断。

boolean exists() :文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();

4,获取信息。

getName():
getPath():
getParent():

getAbsolutePath() 
long lastModified() 
long length() 


递归(Recursion)

现在要求输出一个给定目录中的全部文件的路径。

本程序肯定只能依靠递归的操作完成,因为在一个给定的路径下有可能还是文件夹,那么如果是文件夹的话则肯定要继续列出,重复判断。

递归:程序调用自身的编程技巧

递归就是在方法里调用自身;

在使用递归时,必须有一个明确的递归结束条件,称为递归出口。

 

练习:列出文件夹下所有文件(包含子文件夹内)


/* * 练习:列出文件夹下所有文件(包含子文件夹内) */public class DirShowDemo {public static void main(String[] args) {File f = new File("D:\\downloads\\JAVA");show(f);}public static void show(File file) {File[] files = file.listFiles();for (int i = 0; i < files.length; i++) {if (files[i].isDirectory()) {System.out.println(files[i].getName());show(files[i]);}else{System.out.println(files[i].getName());}}}}



练习:删除一个目录(注意:要删除目录必须删除目录下的文件和子目录)


/* * 练习:删除一个目录(注意:要删除目录必须删除目录下的文件和子目录) */public class DirDeleteDemo {public static void main(String[] args) {File f = new File("D:\\downloads\\JAVA\\新建文件夹");deleteDir(f);}public static void deleteDir(File file){if(file.isFile()){file.delete();}else{File[] files = file.listFiles();for(File fi : files){deleteDir(fi);fi.delete();}}}}





数据流是一串连续不断的数据的集合,就像水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流.

数据写入程序可以使一段一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流.

 

在程序中所有的数据都是以流的方法进行传输和保存的。

Java 的IO是实现输入和输出的基础。

Java把所有传统的流类型(类或抽象类)都放在java.io包中,用以实现输入输出功能。

输入和输出是一个相对的概念,我们一般站在程序的角度来分析和处理问题的。

程序需要数据 --> 读进来    -->  输入

程序保存数据 --> 写出去    -->  输出

水流

 

最重要的:从程序的角度出发,读进来,写出去!(在储存数据的时候是把数据写出去,这时候数据就储存在了文件里面,在需要调用数据的时候就把数据读进来,这样数据就又到了程序中!)

 

流的分类

 

从不同角度分类:

流动方向的不同可以分为输入流和输出流;

处理数据的单位不同分为字节流和字符流;

功能的不同可分为节点流和处理流;

      节点流:直接操作目标设备,例如:磁盘或一块内存区域。

      处理流:通过操作节点流,从而间接完成输入或输出功能的流。处理流是的存在是建立在一个已经存在的输入流或输出流的基础之上的。

 

所有流都继承于以下四种抽象流类型的某一种:(抽象流)






操作流的步骤(重点)

 

File类本身是与文件操作有关,但是如果要想操作内容则必须使用字节流或字符流完成,但是不管是使用何种的输入输出流,其基本的操作原理是一样的(以文件流为准):

一、使用File类找到一个文件对象,得到IO操作的源或目标

二、通过字节流或字符流的子类创建对象,(得到IO操作的通道)

三、进行读或写的操作,(IO操作)

四、关闭输入/输出,

由于流的操作属于资源操作,所以在操作的最后一定要关闭以释放资源。

 

计算机访问外部设备,要比直接访问内存慢得多,若我们每一次write方法调用都是直接写到外部设备(比如磁盘上的一个文件),CPU就要花费更多的时间去等待外部设备;我们可以开辟一个内存缓冲区,程序每一次的write方法都是写到这个内存缓冲区中,只有这个缓冲区装满了之后,系统才将这个缓冲区的内容一次集中写到外部设备.

 

好处:1.有效提高了CPU的使用率;2.write方法并没有马上真正写入到外部设备,我们还有机会回滚部分写入的数据;


/* * 把一个文件的内容打印在输出台 */import java.io.*;public class IODemo {public static void main(String[] args) throws IOException {File f = new File("D:\\downloads\\JAVA\\毕向东视频Java基础源代码Codes\\代码list.txt");BufferedReader bfr = new BufferedReader(new FileReader(f));BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out));String line =null;while((line=bfr.readLine())!=null){bfw.write(line);bfw.newLine();}bfr.close();bfw.close();}}


字节流和字符流

 

二者仅仅是操作单位不一样。

InputStream和Reader是所有输入流的基类,他们都是抽象类,本身不能创建实例,但是他们是所有输入流的模板。

一般来说处理字符或字符串时使用字符流,处理字节或二进制对象时应使用字节流

备注:字符流必须关闭资源,因为它中间有缓冲区!而字节流不需要!但是一般都会(最后)关闭资源!

 

字节流

字节流主要是操作byte(字节)的类型数据:

字节输出流:OutputStream

字节输入流:InputStream

 

字符流

Java中的字符是Unicode编码,是双字节的,1个字符等于 2个字节;

使用字节来处理字符文本就不太方便了,此时可以考虑使用字符流;

字符流主要是操作char的类型数据:

字符输出流:Writer

字符输入流:Reader

 

 
字节流和字符流的区别

 

字节流和字符流在使用上的代码结构都是非常类似的,但是其内部本身也是有区别的,因为在进行字符流操作的时候会使用到缓冲区(内存中),而字节流操作的时候是不会使用到缓冲区的。

在输出的时候,OutputStream类即使最后没有关闭内容也可以输出。但是如果是Writer的话,则如果不关闭,最后一条内容是无法输出的,因为所有的内容都是保存在了缓冲区之中,每当调用了close()方法就意味着清空缓冲区了。那么可以证明字符流确实使用了缓冲区:

字节流:程序文件

字符流:程序缓冲区(内存中)文件

 

如果现在字符流即使不关闭也可以完成输出的话,则必须强制性清空缓冲区:

方法:public void flush() throws IOException

 

两者相比,肯定使用字节流更加的方便,而且在程序中像图片、MP3等都是采用字节的方式的保存,那么肯定字节流会比字符流使用的更广泛。

但是需要说明的是,但是如果要是想操作中文的话,字符流肯定是最好使的。(字节流的话可能会出现乱码(一个汉字分成了两份)!)



文件拷贝

需求:源和目标!

那么我们需要源文件和目标文件!

构建管道的时候就需要两个:输出流和输入流管道!


/* * 文件拷贝 */import java.io.*;public class FileCopyDemo {public static void main(String[] args) throws IOException {File f1 = new File("D:\\downloads\\JAVA\\代码list.txt");File f2 = new File("D:\\downloads\\JAVA\\代码list_复制.txt");BufferedReader bfr = new BufferedReader(new FileReader(f1));BufferedWriter bfw = new BufferedWriter(new FileWriter(f2));String s = null;while((s=bfr.readLine())!=null){bfw.write(s);bfw.newLine();}bfr.close();bfw.close();}}


复制图片!

文件的复制!对于本题而言,因为是图片,所以要想读出来,必须使用字节流!

字符流必须关闭资源,而字节流可以不关闭资源!但是还是建议全部的关闭,因为也不会出错,这是关闭资源的习惯!

另外:最常用的是字节流,因为字节流在内存中不需要缓冲区,图片,mp3等都是字节流!但是对于文字的话还是字符流比较好;

因为字符流可以避免在字节流操作文字时出现的乱码现象(正好读取到了自定义缓冲区的分割处);


/* * 复制图片! */import java.io.*;public class PictureCopyDemo {public static void main(String[] args) throws IOException {File f1 = new File("D:\\downloads\\JAVA\\1.jpg");File f2 = new File("D:\\downloads\\JAVA\\1_复制.jpg");FileInputStream fis = new FileInputStream(f1);FileOutputStream fos = new FileOutputStream(f2);byte[] b = new byte[1024];int len =0;while((len = fis.read(b))!=-1){fos.write(b);}fis.close();fos.close();}}


/* * 字节流缓存 */import java.io.*;public class BufferedStreamDemo {public static void main(String[] args) throws IOException {File f1 = new File("D:\\downloads\\JAVA\\1.jpg");File f2 = new File("D:\\downloads\\JAVA\\1_复制.jpg");FileInputStream fis = new FileInputStream(f1);FileOutputStream fos = new FileOutputStream(f2);BufferedInputStream bfis = new BufferedInputStream(fis);BufferedOutputStream bfos = new BufferedOutputStream(fos);byte[] b = new byte[1024];int len = 0;while((len=bfis.read(b))!=-1){bfos.write(b);}bfis.close();bfos.close();}}



字节→字符转换流

OutputStreamWriter:把字节输出流对象转成字符输出流对象

InputStreamReader:把字节输入流对象转成字符输入流对象

FileWriter和FileReader分别是OutputStreamWriter和InputStreamReader的直接子类,而不是Writer和Reader的直接子类,区别于FileInputStream 和InputStream。

 

转换流可以加入编码表

我的总结:无论使用字节流还是字符流实际上在内存中最终都是通过字节的形式来操作流的。

所以并没有字符流转换字节流。





打印流

(只有两个,PrintWriter和PrintStream)

思考:如果现在要想完成一个字符串或者是boolean型或者是字符型的数据输出使用OutputStream是否方便?

肯定是不方便的,因为OutputStream中只能操作字节数据,所以其他的数据类型很难操作,那么在JavaIO包中为了解决这种问题增加了两种类:PrintStreamPrintWriter

打印流有非常好的打印功能,可以打印任何的数据类型。如,整数,小数,字符串等。

观察PrintStream类的构造:

       public PrintStream(File file) throwsFileNotFoundException

       public PrintStream(OutputStream out)

虽然PrintStream是OutputStream的子类,但是在实例化的时候依然需要一个OutputStream的对象。

 

PrintWriterPrintStream都属于输出流,分别针对字符和字节。

PrintWriter和PrintStream重载的print()和println()用于多种数据类型的输出。

print()里的参数不能为空;println()可以

PrintWriter和PrintStream输出操作不抛出异常

PrintStream调用println方法有自动flush功能;


格式化输出

Java5后,PrintStream类多了printf()方法用于格式化输出操作。但是格式化输出的时候必须指定输出数据的类型:

 

(构造方法)

PrintStream format(String fo, Object... args) 使用指定格式字符串和参数将格式化字符串写入此输出流中。






备注:当然你也可以全部使用“%s”来表示所有的数据类型!

格式:需要格式 % 占位符


标准流

 

    标准输入流:  System.in   默认表示的是键盘录入

    标准输出流:  System.out  默认表示的是屏幕输出


/* * 标准输入流:System.in * 标准输出流:System.out */import java.io.*;public class SystemInOutDemo {public static void main(String[] args) throws IOException {BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out));String s = null;while((s=bfr.readLine())!=null){if(s.equals("over".toLowerCase())){break;}else{bfw.write(s.toUpperCase());bfw.newLine();bfw.flush();}}bfr.close();bfw.close();}}



Scanner(简单文本扫描器)

 

Scanner(File source)  构造一个新的Scanner,它生成的值是从指定文件扫描的。

备注:实现了Iterable接口


/* * Scanner(简单文本扫描器) * 猜数字游戏 */public class ScannerDemo {public static void main(String[] args) {guess();}public static void guess() {Scanner s = new Scanner(System.in);Integer num = new Random().nextInt(100) + 1;System.out.println("请输入一个1~100之间的整数");for (int i = 0; i < 10; i++) {String str = s.next();if (num.compareTo(Integer.valueOf(str)) > 0) {System.out.println("小了");}else if(num.compareTo(Integer.valueOf(str)) < 0){System.out.println("大了");}else if(num.compareTo(Integer.valueOf(str)) == 0){System.out.println("中了");break;}}s.close();}}


合并流(SequenceInputStream)

 

需要两个源文件,还有输出的目标文件

SequenceInputStream:

将两个文件的内容合并成一个文件

该类提供的方法:

SequenceInputStream(InputStreams1, InputStream s2) :根据两个字节输入流对象来创建合并流对象。

备注:谁放在前面,谁就先打印出来

package IOArea;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.Enumeration;import java.util.Vector;public class FileMerge {public static void main(String[] args) throws IOException {Vector<FileInputStream> v = new Vector<>();v.add(new FileInputStream("D:\\downloads\\JAVA\\test1.avi"));v.add(new FileInputStream("D:\\downloads\\JAVA\\test2.avi"));v.add(new FileInputStream("D:\\downloads\\JAVA\\test3.avi"));Enumeration<FileInputStream> en = v.elements();SequenceInputStream sis = new SequenceInputStream(en);FileOutputStream fos = new FileOutputStream("D:\\downloads\\JAVA\\test5.avi");byte[] arr = new byte[1024];int i = 0;while((i=sis.read(arr))!=-1){fos.write(arr);}fos.close();}}










----------- android培训java培训、java学习型技术博客、期待与您交流! ------------
0 0