第3节 IO(上)

一、File类与文件基本操作

在程序中经常需要用到文件的操作,Java有专门的类来进行文件的操作——File类。

1.1 File类概述

它是对文件和目录路径名的抽象表示。 即它本身不是一个文件,只是一个抽象表示,一个用于操作文件的对象(实现后)。

用户界面和操作系统使用依赖于系统的路径名字符串来命名文件和目录。此类提供了一个抽象的,与系统无关的分层路径名视图。

1.2 绝对路径于相对路径

  • 绝对路径 :从盘符开始,是一个完整的路径,例如:c://a.txt;

  • 相对路径 :在Java代码中是相对于项目目录路径 ,这是一个不完整的便捷路径,在Java开发中很常用。

看一个例子就明白了:

package com.kaikeba.coreclasslibrary.io;import java.io.File;public class path {public static void main(String[] args) {File file1 = new File("c://a.txt");File file2 = new File("a.txt");System.out.println("file1的路径:"+file1.getAbsolutePath());System.out.println("file2的路径:"+file2.getAbsolutePath());}
}结果如下:
file1的路径:c:\a.txt
file2的路径:E:\JAVAEE开发工程师\code\classcode\a.txt

其中项目的路径就是E:\JAVAEE开发工程师\code\classcode

1.3 File类字段

这边的路径分隔符和默认名称分隔符是为了适应不同的os,因为在不同的os上它们是不一样的,为了避免经常修改这些,可以利用File类给出的这些字段,在不同的os上会给出相应的分隔符,下面看一下Windows上的分隔符是什么:

System.out.println(File.pathSeparator);
System.out.println(File.separator);结果如下:
;
\

1.4 构造方法

parent和child构造的方法,parent是目录,child是具体文件名。

1.5 方法

1、三个测试:

2、比较两个抽象路径名:

3、在该路径下创建文件:存在则不新建

4、删除文件:

5、判断是否存在该文件:

6、得到绝对路径:可以是File类或String字符串

7、得到文件或目录名称:

8、测试是否是绝对路径、目录、文件、隐藏文件:

9、返回文件的长度(大小):

10、列出该目录下的所有文件或字符串路径:

11、新建目录或递归新建目录

上述就是一些常用方法。

1.6 文件遍历与文件过滤器

1.6.1 文件遍历(充分利用File类的方法)

如何在一个路径下找出所有的PDF文件?这就需要遍历路径下的所有文件和目录,遇到目录还要在进目录继续遍历:

代码如下:

package com.kaikeba.coreclasslibrary.io;import java.io.File;public class listfiles {public static void main(String[] args) {File e = new File("e:\\");File[] files = e.listFiles();listFiles(files);}private static void listFiles(File[] files) {if(files != null && files.length > 0) {for(File file:files) {if(file.isFile()) {//文件if(file.getName().endsWith(".pdf")) {//找到了一个大于10M的PDF文件if(file.length()>10*1024*1024) {System.out.println(file.getAbsolutePath());}}}else {//文件夹,继续递归遍历File[] files2 = file.listFiles();listFiles(files2);}}}}
}结果就是遍历的所有在E盘下的PDF的路径...

1.6.2 文件过滤器

上述遍历的框架已经有了,但是在判断是否是我们要找的文件时if判断是我们自己写的,还有一种方法,虽然不常用,但是也可以了解。

listFiles方法的参数里有一个FileFilter类型的filefilter变量:

FileFilter是一个接口,只有一个抽象方法:

可以把判断条件写在accept里面,如果返回true就保存该文件,返回false就不保留该文件,例子如下:

package com.kaikeba.coreclasslibrary.io;import java.io.File;
import java.io.FileFilter;public class filefilter2 {public static void main(String[] args) {File e = new File("e:\\");listFiles(e);}private static void listFiles(File file) {//1.    创建一个过滤器规则 并 描述规则//2.    通过文件获取子文件夹File[] files = file.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {if(pathname.getName().endsWith(".pdf") || pathname.isDirectory()) {return true;}return false;}});if(files != null || files.length > 0) {for (File f : files) {if (f.isDirectory()) {listFiles(f);} else {System.out.println(f.getAbsolutePath());}}}}
}返回结果如上述代码一致。

二、流(输入输出)概述

计算机中的任何数据(文本,图片,视频,音乐等等)都是以二进制形式存储的。在数据传输时,也都是以二进制形式存储的。后续学习的任何流,在传输时底层都是二进制。

可以将数据传输的操作,看做一种数据的流动。按照流动的方向,分为输入Input和输出Output。

Java中的IO操作主要指的是java.io包下的一些常用类的使用,通过这些类,对数据进行读取(输入Input)和写出(Output)。

IO流的分类:

  • 按照流的方向来分,可以分为:输入流和输出流

  • 按照流动的数据类型来分,可以分为:字节流和字符流

字节流:

  • 输入流:InputStream

  • 输出流:OutputStream

字符流:

  • 输入流:Reader

  • 输出流:Writer

三、字节流

3.1 字节输出流OutputStream类

3.1.1 OutputStream类概述

此抽象类是表示输出字节流的所有类的超类,输出流接收输出字节并将它们发送到某个接收器。它的实现子类最常用的就是:FileOutputStream类。

方法:

1、关闭输出流:

2、刷新缓存,强制写出:

3、写出操作:将字节数组或字节写出

3.1.2 FileOutputStream类

OutputStream类最常用的一个实现类。

构造方法:

指定要输出写入的文件对象或String路径(文件不存在会自动创建),append表示是否追加写入,true为追加模式,false为清空内容从头写入。

方法: 基本就是使用OutPutStream类的方法。

看个例子:

package com.kaikeba.coreclasslibrary.io;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class outputstream {public static void main(String[] args) throws IOException {//FileOutputStreamFileOutputStream fos = new FileOutputStream("a.txt");
//        byte[] bytes = {65,66,67,68,69};
//        fos.write(65);byte[] bytes = "ABCDEF".getBytes();
//        fos.write(bytes);fos.write(bytes, 1, 2);fos.close();System.out.println("已经写出");}
}结果为:
BC

3.2 字节输入流InputStream类

3.2.1 InputStream类概述

此抽象类是表示输入字节流的所有类的超类。最常见的子类是FileInputStream类。

方法:

1、关闭输入流:

2、读取下一个字节:

3、读取一些字节:

4、读取一些字节,并指定开始位置和读取个数:

注意: 读取的方法返回的都是读取到的有效字节的个数如果已经到文件末尾,将会返回-1

5、其他一些读取方法:

6、跳过并丢弃输入流的n字节数据:

3.2.2 FileInputStream类

InputStream类最常用的一个子类。

构造方法:

给定要读取的文件。

方法:

看一个例子:

首先在a.txt文件中写有Hello InputStream的内容。下面来将其文件中的内容读取到程序中:

package com.kaikeba.coreclasslibrary.io;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;public class inputstream {public static void main(String[] args) throws IOException {//FileInputStreamInputStream fis = new FileInputStream("a.txt");while(true) {byte b = (byte)fis.read();//b如果为-1,表示已经读取到文件末尾,读取完毕if(b == -1) {break;}System.out.print((char)b);}}
}结果为:
Hello InputStream

但是这种方式每次只读取一个字节,需要很多次读取(read)操作,与文件的连接次数太多会拖慢程序的速度,所以可以使用read的另一个方法:

package com.kaikeba.coreclasslibrary.io;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;public class inputstream {public static void main(String[] args) throws IOException {//FileInputStreamInputStream fis = new FileInputStream("a.txt");//推荐下面这种方式读取,因为读取的次数较少byte[] bytes = new byte[10];int len = fis.read(bytes);System.out.println(new String(bytes,0,len));len = fis.read(bytes);System.out.println(new String(bytes,0,len));len = fis.read(bytes);System.out.println(len);fis.close();}
}结果如下:
Hello Inpu
tStream
-1

用一个字节数组来接收读取到的固定长度的数据,但是要注意,读到最后,如果不满10个字节了,那么返回的将不是希望的结果,因为是将新读取到的覆盖数组,未满10个最后几个后面将不会被覆盖,即多出几个没用的字节。

解决:按照上述的写法,将成功读取到的字节个数接收,并用String的bytes数组指定长度的构造方法来输出。

优点:这样大大减少了连接文件的次数,加速了程序的运行。

3.2.3 字节流读取文字

如果将上述a.txt中的内容换成中文,比如 锄禾日当午,汗滴禾下土 ,再来看上述代码的输出:

锄禾日�
��午,�
�滴禾下

这并不是乱码,因为中文编码一般不是一个字节来表示一个字,所以它10个字节可能读到的是3个半字,那半个字是无法恢复的,它比乱码更加可怕 ,这就是字节流的缺点所在,后续学习字符流就是专门解决读取文字的问题。

四、字符流

字符流与字节流的区别就是字节流是一个字节一个字节的传输,但是字符流不太一样,虽然内部还是传输的字节,但是因为一个字符,比如一些非英文文字,需要几个字节来表示一个字符,所以它会一次读或写一个字符,这样就可以避免3.2.3出现的问题。

4.1 字符输出流Writer类

4.1.1 Writer类概述

用于写入字符流的抽象类。最常用的子类为OutputStreamWriter下的FileWriter。其中OutputStreamWriter后续介绍。

方法:

比较常用的有:

1、append:将字符或序列追加到此Writer,注意它的返回类型为Writer,即追加完后的文件自己。

其实它内部调用的还是write方法,但是write方法没有返回,这就使得append方法可以连续操作(当然用write也可以达到一样的效果)。

2、close:关闭流,关闭之前先刷新缓存

3、flush:刷新缓存,如果不刷新,内容是写在缓存区的,还没有真正写入文件:

close方法中已经调用了flush,这里我们不使用close,只看使用flush和不使用flush的区别:

目前b.txt是空的,下面调用:

public class flush {public static void main(String[] args) throws IOException {FileWriter fw = new FileWriter("b.txt", true);fw.append("锄禾日当午").append(",").append("汗滴禾下土");}
}

结果还是空的,因为没有刷新缓冲区:

如果加上flush:

FileWriter fw = new FileWriter("b.txt", true);
fw.append("锄禾日当午").append(",").append("汗滴禾下土");
fw.flush();

结果为:

4、write:写一个字符数组,字符数组的一部分,一个字符,一个字符串,字符串的一部分:

4.1.2 FileWriter类

   使用默认缓冲区大小将文本写入字符文件。

构造方法:

参数:

1、File file / String fileName:要将内容写入的文件;

2、Charset charset:指定编码集,常见的有"gbk"、“uft8”;

3、boolean append:是否是追加模式写入;

方法没有新的,都是用的或重写的父类方法。

看个例子:

package com.kaikeba.coreclasslibrary.io;import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;public class writer {public static void main(String[] args) throws IOException {//Writer//FileWriterFileWriter fw = new FileWriter("b.txt");fw.write('a');fw.write("锄禾日当午");//注意append的用法,因为它返回文件本身fw.append(",").append("汗滴禾下土");fw.close();}
}b.txt中的内容为:
a锄禾日当午,汗滴禾下土

4.2 字符输入流Reader类

4.2.1 Reader类概述

用于读取字符流的抽象类。常用的子类为InputStreamReader下的FileReader类。

方法:

常用的有:

1、close:关闭流

2、read:读入一个字符,返回的就是它的int型编码

3、将字符读入数组(一部分)或指定缓冲区

4.2.2 FileReader类

使用默认缓冲区大小从字符文件中读取文本,使用指定的编码集或默认编码集。

构造方法:

参数:

1、File file / String fileName:从哪个文件读取;

2、Charset charset:指定编码集。

方法也没有新的。

看个例子:

package com.kaikeba.coreclasslibrary.io;import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;public class reader {public static void main(String[] args) throws IOException {//ReaderFileReader fr = new FileReader("b.txt");/*while(true) {int c = fr.read();if(c == -1) {break;}System.out.print((char)c);}*/System.out.println("a:"+fr.read());System.out.println("锄:"+fr.read());char[] chars = new char[100];int len = fr.read(chars);System.out.println(new String(chars, 0, len));fr.close();}
}结果如下:
a:97
锄:38148
禾日当午,汗滴禾下土

五、字节流转换字符流

5.1 InputStreamReader类

InputStreamReader类是从字节流到字符流的桥接器,这也是比较常用的,比如从外界接收到的流一般都是字节流,如果要正确读取文字的话,需要转为字符流。每次调用read方法都可能导致从底层字节输入流中读取一个或者多个字节。

它是Reader类的一个子类,是FileReader的父类。

构造方法:

主要的参数是要传入一个字节输入流InputStream

方法:

主要是read方法,可以读取一个字符或者将字符输入数组的一部分。

看一个例子:

public class zhuanhuanliu {public static void main(String[] args) throws IOException {//字节流 ‘装饰’为 字符流 :使用了装饰者设计模式//自己新建一个字节输入流,用于模仿外界接收到的FileInputStream fis = new FileInputStream("b.txt");//将字节输入流,转换为字符输入流//参数1:要转换的字节流//参数2:指定编码名称InputStreamReader isr = new InputStreamReader(fis,"utf8");while(true) {int c = isr.read();if(c == -1) {break;}System.out.print((char)c);}}
}结果就是将b.txt中的内容全部输出

5.2 OutputStreamWriter类

OutputStreamWriter是从字符流到字节流的桥接器,使用指定的charset将写入其中的字符编码为字节。调用write方法都会导致在给定字符上调用编码转换器,生成的字节在写入底层输出流之前在缓冲区中累积。

它是Writer类的子类,是FileWriter类的父类。

构造方法:

主要参数是要转换的输出字节流。

方法:

写一个字符或字符串或字符数组的一部分。

看一个例子:

public class zhuanhuanliu2 {public static void main(String[] args) throws IOException {//转换流//字符流 ‘装饰’为 字节流 :使用了装饰者设计模式FileOutputStream fos = new FileOutputStream("b.txt");OutputStreamWriter osw = new OutputStreamWriter(fos);osw.write("床前明月光");osw.close();}
}即将“床前明月光”写入b.txt。

六、打印流与缓存流

6.1 PrintStream类

PrintStream类向另一个输出流添加功能,即能够方便地打印各种数据值的表示。

构造方法:

传入的参数主要是要写入的文件,可以是File型,String型或者字节输出流。

方法:

1、追加:

2、关闭、刷新:

3、打印

4、打印并换行:

5、写入:

看个例子:

public class print_bufferedreader {public static void main(String[] args) throws IOException {//(字符输出)打印流,注意它会自动刷新PrintStream ps = new PrintStream("b.txt");ps.println("锄禾日当午1");ps.println("锄禾日当午2");ps.println("锄禾日当午3");}
}b.txt中的内容就是:
锄禾日当午1
锄禾日当午2
锄禾日当午3

6.2 PrintWriter类

它和PrintStream类基本上差不多,主要的区别是写入的时候不会自动刷新。

public class print_bufferedreader {public static void main(String[] args) throws IOException {PrintWriter pw = new PrintWriter("b.txt");pw.println("锄禾日当午1");pw.println("锄禾日当午2");pw.println("锄禾日当午3");pw.flush();}
}b.txt中的内容就是:
锄禾日当午1
锄禾日当午2
锄禾日当午3

也可以用输出流作为参数:

public class print_bufferedreader {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("b.txt");PrintWriter pw = new PrintWriter(fos);pw.println("勇敢牛牛");pw.close();}
}b.txt中的内容就是:
勇敢牛牛

6.3 BufferedReader类

从字符输入流中读取文本,缓冲字符,以便有效地读取字符,数组和行。可以指定缓冲区大小,或者可以使用默认大小。

构造方法:

方法:

它比较独特的一个方法是readLine方法:读取一行文字,看一个例子:

public class print_bufferedreader {public static void main(String[] args) throws IOException {//缓存读取流,将字符输入流 转换为带有缓存 可以一次读取一行的缓存字符读取流FileReader fw = new FileReader("b.txt");BufferedReader br = new BufferedReader(fw);String text = br.readLine();System.out.println(text);}
}结果解释读取b.txt中的一行文字。

七、收集异常日志

在程序运行过程中,不可能一直看着屏幕上的输出,所以当出现异常的时候,利用IO我们可以将这些异常写到指定的文件中,后续有时间打开这个记录异常的文件查看即可。

看一个例子:

public class printstacktrace {public static void main(String[] args) throws FileNotFoundException {try{//将可能出现异常的内容用try捕捉String s = null;s.toString();}catch (Exception e) {//新建打印流,指定输出的文件PrintWriter pw = new PrintWriter("b.txt");//把时间也记录下来SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");pw.println(sdf.format(new Date()));//将异常输出到打印流中e.printStackTrace(pw);//关闭打印流pw.close();}}
}b.txt中的内容就是异常:
2021-09-13 19:57
java.lang.NullPointerExceptionat com.kaikeba.coreclasslibrary.io.printstacktrace.main(printstacktrace.java:12)

JavaSE——IO(上)(File、字节流、字符流、转换流、打印流、缓存流)相关推荐

  1. Buffered缓存流

    处理流: 处理流是对一个已经存在的流的连接和封装,利用的是装饰设计模式,通过所封装后的流进行功能调用实现数据读写,例如BufferedInputStream,处理流的构造器总是需要带一个其他流的对象作 ...

  2. Java基础---认识IO流---字节流、字符流---缓冲流---转换流

    一.认识IO流 I/O就是用于设备之间进行数据交互的对象所属的类型 IO流的体系结构:根据分类,有四种流对象类型 字节流:可以直接操作字节信息的流对象 字节输入流:InputStream 字节输出流: ...

  3. java基础 io流 字节流 字符流 节点流 包装流 转换流 缓冲流 对象流 打印流 Properties类

    目录 1.概念 2.常用的文件操作 2.1 创建文件 2.2 获取文件相关信息 2.3 目录的操作和文件删除 3. IO流原理及流的分类 3.1 流的分类 4.InputStream 字节输入流 4. ...

  4. io包下 文件类 字节流 字符流 缓冲流 转换流 序列化流 打印流

    第一章 File类 1.1 概述 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 1.2 构造方法 public File(String pat ...

  5. Java基础IO流概述、字符流、字节流、流操作规律、File类、Properties类、打印流、序列流

    IO流:(Input Output)流 字符流的由来:其实就是字节流读取文字字节数据后,不直接操作而是先查指定的码表,获取对应的文字进行操作 简单说:字符流 = 字节流 + 编码表 字节流的两个顶层父 ...

  6. -1-4 java io java流 常用流 分类 File类 文件 字节流 字符流 缓冲流 内存操作流 合并序列流...

    File类 •文件和目录路径名的抽象表示形式 构造方法 •public File(String pathname) •public File(String parent,Stringchild) •p ...

  7. io字符流和字节流之间的转换和基本应用练习

    流的操作规律,及其总结: 基本: InputStream OutputStream:对于字节流分别进行输入输出操作 Reader Writer:对于字符流分别进行输入输出操作 转换流: InputSt ...

  8. Java全栈(二)JavaSE:25.File类和IO流

    1 java.io.File类 1.1 概述 File类是java.io包下代表与平台无关的文件和目录,也就是说如果希望在程序中操作文件和目录都可以通过File类来完成,File类能新建.删除.重命名 ...

  9. 【Java10】lambda表达式(函数式编程),Stream流,File类,字节/字符流,乱码,缓冲/转换/序列化/打印流,Properties

    文章目录 1.lambda表达式标准语法:()->{} 2.lambda表达式简略语法:可推导即可省略 3.lambda表达式原理:lambda效率比匿名内部类高 4.两个函数式接口:Consu ...

最新文章

  1. h3c交换机端口加入vlan命令_华为交换机批量加入 Vlan 方法
  2. 输出四位完全平方数_LeetCode 题解 | 279. 完全平方数
  3. python word 1_Python word | 学步园
  4. 连接池Connection Pool 单例设计
  5. c语言stl模板,c/c++开发分享C++ 标准模板库 STL 顺序容器详解
  6. B 站硬件大佬在 GitHub 上开源了一款神器
  7. Java多线程(七)之同步器基础:AQS框架深入分析
  8. CSUOJ 1196- Staginner 去爬山
  9. myeclipse怎么导入mysql驱动_myeclipse sql导入数据库驱动包
  10. ASP.NET几种安全验证方法(一)
  11. poi comment
  12. C语言真题考研pdf,中财信息学院C语言程序设计1999年考研真题.pdf
  13. redis 慢消费_Redis精进:List的使用和应用场景
  14. Shell编程入门学习
  15. 我国4G标准拓展国际市场取得重要突破
  16. 微信也能开门?微信开门解决方案来了
  17. wdf中的两个宏WDF_DECLARE_CONTEXT_TYPE WDF_DECLARE_CONTEXT_TYPE_WITH_NAME
  18. 如何进行代理上网以及ccproxy设置
  19. Android 关机时的radio相关关闭流程
  20. 利用ENVI实现图像几何校正

热门文章

  1. 修改mysql文件的存储路径
  2. android stackview,Android StackView 使用示例
  3. 3d点击_3D打印服务加工在医疗器械行业的应用
  4. 乐学python_【IT专家】铁乐学python
  5. pygame render怎么显示中文_Pygame游戏——贪吃蛇(完结)
  6. 【小夕精选】YJango 7分钟带你领略你未曾想过的线性代数+微积分
  7. 应用实践 | 网络智能运维下的知识图谱
  8. 玩转算法值面试-第五章 -在链表中穿针引线
  9. 数据库的方向 - 行vs列(转自: IBM i 中国开发团队)
  10. nlp5-n-gram/语言模型(数据平滑方法