Java中IO流,输入输出流概述与总结

总结的很粗糙,以后时间富裕了好好修改一下。

1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中。其中,

所有输入流类都是抽象类InputStream(字节输入流),或者抽象类Reader(字符输入流)的子类;

而所有输出流都是抽象类OutputStream(字节输出流)或者Writer(字符输出流)的子类。

【首先需要明白的是:流是干什么的???(为了永久性的保存数据)

  根据数据流向的不同分为输入流和输出流;

  根据处理数据类型的不同分为字符流和字节流;

【然后需要明白的是输入模式和输出模式是谁流向谁:

InputStream(字节输入流)和Reader(字符输入流)通俗的理解都是读(read)的。

OutputStream(字节输出流)和Writer(字符输出流)通俗的理解都是写(writer)的。

最后下面搞清楚各种流的类型的该怎么用,谁包含谁,理清思路。

2:InputStream类是字节输入流的抽象类,是所有字节输入流的父类,InputStream类具有层次结构如下图所示;

3:java中的字符是Unicode编码的,是双字节的。InputStream是用来处理字节的,在处理字符文本时很不方便。Java为字符文本的输入提供了专门的一套类Reader。Reader类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。

4:输出流OutputStream类是字节输入流的抽象类,此抽象类表示输出字节流的所有类的超类。

5:Writer类是字符输出流的抽象类,所有字符输出类的实现都是它的子类。

6:File类是IO包中唯一代表磁盘文件本身的对象。通过File来创建,删除,重命名文件。File类对象的主要作用就是用来获取文本本身的一些信息。如文本的所在的目录,文件的长度,读写权限等等。(有的需要记忆,比如isFile(),isDirectory(),exits();有的了解即可。使用的时候查看API)

详细如下:
File类(File类的概述和构造方法)
A:File类的概述
  File更应该叫做一个路径
  文件路径或者文件夹路径
  路径分为绝对路径和相对路径
    绝对路径是一个固定的路径,从盘符开始
    相对路径相对于某个位置,在eclipse下是指当前项目下,在dos下
  查看API指的是当前路径
  文件和目录路径名的抽象表示形式
B:构造方法
  File(String pathname):根据一个路径得到File对象
  File(String parent,String child):根据一个目录和一个子文件/目录得到File对象
  File(File parent,String child):根据一个父File对象和一个子文件/目录得到File对象
 
File类(File类的创建功能)
  A:创建功能
    public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
    public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
    public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来
(使用createNewFile()文件创建的时候不加.txt或者其他后缀也是文件,不是文件夹;使用mkdir()创建文件夹的时候,如果起的名字是比如aaa.txt也是文件夹不是文件;)
注意事项:
如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下。
 
File类(File类的重命名和删除功能)
  A:重命名和删除功能
    public boolean renameTo(File dest):把文件重命名为指定的文件路径
    public boolean delete():删除文件或者文件夹
  B:重命名注意事项
    如果路径名相同,就是改名。
    如果路径名不同,就是改名并剪切。
  C:删除注意事项:
    Java中的删除不走回收站。
    要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹
 
File类(File类的判断功能)
  A:判断功能
    public boolean isDirectory():判断是否是目录
    public boolean isFile():判断是否是文件
    public boolean exists():判断是否存在
    public boolean canRead():判断是否可读
    public boolean canWrite():判断是否可写
    public boolean isHidden():判断是否隐藏
File类(File类的获取功能)
  A:获取功能
    public String getAbsolutePath():获取绝对路径
    public String getPath():获取路径
    public String getName():获取名称
    public long length():获取长度。字节数
    public long lastModified():获取最后一次的修改时间,毫秒值
    public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
    public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组
 
File类(文件名称过滤器的概述及使用)
  A:文件名称过滤器的概述
    public String[] list(FilenameFilter filter)
    public File[] listFiles(FileFilter filter)

<div class="cnblogs_code">

 1 package com.ningmeng;
 2 
 3 import java.io.File;
 4 
 5 public class Test {
 6 
 7     public static void main(String[] args) throws Exception{
 8         // TODO Auto-generated method stub
 9         File file=new File("aa.txt");//文件默认就创建在你创建的项目下面,刷新即可看到
10         System.out.println(file.exists());//判断文件是否存在
11         file.createNewFile();//创建文件,不是文件夹
12         System.out.println(file.exists());//再次判断是否存在
13         System.out.println(file.getName());//获取文件的名字
14         System.out.println(file.getAbsolutePath());//获取文件的绝对路径
15         System.out.println(file.getPath());//获取文件的相对路径
16         System.out.println(file.getParent());//获取文件的父路径
17         System.out.println(file.canRead());//文件是否可读
18         System.out.println(file.canWrite());//文件是否可写
19         System.out.println(file.length());//文件的长度
20         System.out.println(file.lastModified());//文件最后一次修改的时间
21         System.out.println(file.isDirectory());//判断文件是否是一个目录
22         System.out.println(file.isHidden());//文件是否隐藏
23         System.out.println(file.isFile());//判断文件是否存在
24     }
25 
26 }

  public String[] list():获取指定目录下的所有文件或者文件夹的名称数组

  public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组

list()获取某个目录下所有的文件或者文件夹:

1 package com.ningmeng; 2 3 import java.io.File; 4 5 public class FileTest { 6 7 public static void main(String[] args){ 8 File file=new File("D:/");//指定文件目录 9 String[] str=file.list();//获取指定目录下的所有文件或者文件夹的名称数组 10 for(String s : str){//加强for循环遍历输出 11 System.out.println(s); 12 } 13 14 } 15 }
1 package com.ningmeng; 2 3 import java.io.File; 4 5 public class FileTest { 6 7 public static void main(String[] args){ 8 File file=new File("D:/");//指定文件路径 9 File[] f=file.listFiles();//获取指定目录下的所有文件或者文件夹的File数组 10 for(File fi : f){//加强for循环遍历输出 11 System.out.println(fi); 12 } 13 14 } 15 }

案例演示:

获取某种格式的文件比如获取某种后缀的图片,并输出文件名:

1 package com.ningmeng; 2 3 import java.io.File; 4 5 public class FileTest { 6 7 public static void main(String[] args){ 8 File file=new File("C:\\Users\\biehongli\\Pictures\\xuniji"); 9 String[] str=file.list(); 10 11 for(String s : str){ 12 if(s.endsWith(".jpg") || s.endsWith(".png")){//如果后缀是这种格式的就输出 13 System.out.println(s); 14 } 15 } 16 17 18 } 19 }

下面演示获取文件夹下面子目录里面的文件获取(并没有完全获取子目录的子目录等等,仅仅获取了子一级目录):

1 package com.ningmeng; 2 3 import java.io.File; 4 5 public class FileTest { 6 7 public static void main(String[] args){ 8 File file=new File("C:\\Users\\biehongli\\Pictures\\Camera Roll"); 9 10 File[] f=file.listFiles(); 11 12 for(File fi : f){ 13 if(fi.isDirectory()){//判断如果是一个目录 14 String[] s=fi.list(); 15 for(String str : s){ 16 if(str.endsWith(".jpg")){ 17 System.out.println(str); 18 } 19 } 20 } 21 } 22 } 23 }

A:文件名称过滤器的概述

    public String[] list(FilenameFilter filter)
    public File[] listFiles(FileFilter filter)
1 package com.ningmeng; 2 3 import java.io.File; 4 import java.io.FilenameFilter; 5 6 public class FileTest { 7 8 public static void main(String[] args){ 9 File file=new File("C:\\Users\\biehongli\\Pictures\\Camera Roll"); 10 11 String[] str=file.list(new FilenameFilter() {//过滤器,匿名内部类 12 13 @Override 14 public boolean accept(File dir,String name) { 15 // TODO Auto-generated method stub 16 //System.out.println(dir);//获取文件的路径 17 //System.out.println(name);//获取文件的名字 18 File f=new File(dir,name); 19 return f.isFile() && f.getName().endsWith(".jpg"); 20 } 21 }); 22 for(String s : str){ 23 System.out.println(s); 24 } 25 26 } 27 }

7:下面以一些字节输入输出流具体的案例操作(操作的时候认清自己使用的是字节流还是字符流):

注意:read()方法读取的是一个字节,为什么返回是int,而不是byte
字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111;那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上;24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型

FileInputStream的单个字节读取:

FileOutputStream的单个字节写入:

1 package com.ningmeng; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 6 public class FileTest { 7 8 public static void main(String[] args) throws Exception{ 9 FileInputStream fis=new FileInputStream("aaa.txt"); 10 FileOutputStream fos=new FileOutputStream("bbb.txt",true); 11 //FileOutputStream()后面加true指文件后面可追加 12 13 int a=fis.read();//read()一次读取一个字节 14 System.out.println(a);//读取的一个字节输出 15 16 fos.write(101);//write()一次写一个字节 17 fis.close();//一定记得关闭流,养成好习惯 18 fos.close(); 19 } 20 }

FileInputStream和FileOutputStream进行拷贝文本或者图片或者歌曲:

1 package com.ningmeng; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 6 public class FileTest { 7 8 public static void main(String[] args) throws Exception{ 9 FileInputStream fis=new FileInputStream("aaa.txt"); 10 FileOutputStream fos=new FileOutputStream("bbb.txt"); 11 //如果没有bbb.txt,会创建出一个 12 13 int b; 14 while((b=fis.read())!=-1){ 15 fos.write(b); 16 } 17 fis.close(); 18 fos.close(); 19 } 20 }

FileInputStream和FileOutputStream定义小数组进行读写操作:

1 package com.ningmeng; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 6 public class FileTest { 7 8 public static void main(String[] args) throws Exception{ 9 FileInputStream fis = new FileInputStream("aaa.txt"); 10 FileOutputStream fos = new FileOutputStream("bbb.txt"); 11 int len; 12 byte[] arr = new byte[1024 * 8];//自定义字节数组 13 14 while((len = fis.read(arr)) != -1) { 15 //fos.write(arr); 16 fos.write(arr,len);//写出字节数组写出有效个字节个数 17 } 18 //IO流(定义小数组) 19 //write(byte[] b) 20 //write(byte[] b,int off,int len)写出有效的字节个数 21 22 fis.close(); 23 fos.close(); 24 } 25 }

 IO流(BufferedInputStream和BufferOutputStream拷贝)

* A:缓冲思想
  * 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
  * 这是加入了数组这样的缓冲区效果,java本身在设计的时候,
  * 也考虑到了这样的设计思想,所以提供了字节缓冲区流
* B.BufferedInputStream
  * BufferedInputStream内置了一个缓冲区(数组)
  * 从BufferedInputStream中读取一个字节时
  * BufferedInputStream会一次性从文件中读取8192个,存在缓冲区中,返回给程序一个
  * 程序再次读取时,就不用找文件了,直接从缓冲区中获取
  * 直到缓冲区中所有的都被使用过,才重新从文件中读取8192个
* C.BufferedOutputStream
  * BufferedOutputStream也内置了一个缓冲区(数组)
  * 程序向流中写出字节时,不会直接写到文件,先写到缓冲区中
  * 直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写到文件里

<div class="cnblogs_code">

 1 package com.ningmeng;
 2 
 3 import java.io.BufferedInputStream;
 4 import java.io.BufferedOutputStream;
 5 import java.io.FileInputStream;
 6 import java.io.FileOutputStream;
 7 
 8 public class FileTest {
 9 
10     public static void main(String[] args) throws Exception{
11         FileInputStream fis = new FileInputStream("aaa.txt");
12         FileOutputStream fos = new FileOutputStream("bbb.txt");
13         
14         BufferedInputStream bis=new BufferedInputStream(fis);
15         //使用装饰模式,把fis装饰进去bis中。使用缓冲读取速度变快
16         BufferedOutputStream bos=new BufferedOutputStream(fos);
17         
18         int b;
19         while((b=bis.read())!=-1){
20             bos.write(b);
21         }
22         bis.close();
23         bos.close();
24     }
25 }

 面试题:小数组的读写和带Buffered的读取哪个更快?

  * 定义小数组如果是8192个字节大小和Buffered比较的话
  * 定义小数组会略胜一筹,因为读和写操作的是同一个数组
  * 而Buffered操作的是两个数组
IO流(flush和close方法的区别)
flush()方法: 用来刷新缓冲区的,刷新后可以再次写出(字节缓冲流内置缓冲区,如果没有读取出来,可以使用flush()刷新来)
close()方法:用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出
8:字符流FileReader和FileWriter
字符流是什么
  * 字符流是可以直接读写字符的IO流
  * 字符流读取字符,就要先读取到字节数据,然后转为字符. 如果要写出字符,需要把字符转为字节再写出.    
IO流(什么情况下使用字符流)
* 字符流也可以拷贝文本文件,但不推荐使用. 因为读取时会把字节转为字符,写出时还要把字符转回字节.
* 程序需要读取一段文本,或者需要写出一段文本的时候可以使用字符流
* 读取的时候是按照字符的大小读取的,不会出现半个中文
* 写出的时候可以直接将字符串写出,不用转换为字节数组
 
IO流(字符流是否可以拷贝非纯文本的文件)
* 不可以拷贝非纯文本的文件
* 因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用?代替,写出的时候会将字符转换成字节写出去
* 如果是?,直接写出,这样写出之后的文件就乱了,看不了了
 1 package com.ningmeng;
 2 
 3 import java.io.FileReader;
 4 import java.io.FileWriter;
 5 
 6 public class FileTest {
 7 
 8     public static void main(String[] args) throws Exception{
 9         //FileReader类的read()方法可以按照字符大小读取
10         FileReader fr=new FileReader("aaa.txt");
11         int b;
12         while((b=fr.read())!=-1){
13             System.out.println((char)b);//int类型转为字符型
14         }
15         fr.close();
16         
17         //FileWriter类的write()方法可以自动把字符转为字节写出
18         FileWriter fw = new FileWriter("aaa.txt",true);
19         fw.write("aaa");
20         fw.close();
21         
22         //字符流的拷贝
23         FileReader fr2 = new FileReader("aaa.txt");
24         FileWriter fw2 = new FileWriter("bbb.txt");
25         
26         int ch;
27         while((ch = fr2.read()) != -1) {
28             fw2.write(ch);
29         }
30 
31         fr2.close();
32         fw2.close();
33     }
34 }
1 package com.ningmeng; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileReader; 6 import java.io.FileWriter; 7 8 public class FileTest { 9 10 public static void main(String[] args) throws Exception{ 11 BufferedReader br=new BufferedReader(new FileReader("aaa.txt")); 12 BufferedWriter bw=new BufferedWriter(new FileWriter("bbb.txt")); 13 //BufferedReader和BufferedWriter的使用: 14 int b; 15 while((b=br.read())!=-1){ 16 bw.write((char)b); 17 } 18 br.close(); 19 bw.close(); 20 } 21 }

 先写到这里吧,内容比较多,以后有时间再总结,也方便自己脑补     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


在 Java 语言中,提高程序的执行效率有两种实现方法,一个是使用线程、另一个是使用线程池。而在生产环境下,我们通常会采用后者。为什么会这样呢?今天我们就来聊聊线程池的优点,以及池化技术及其应用。 1.池化技术 池化技术指的是提前准备一些资源,在需要时可以重复使用这些预先准备的资源。 池化技术的优点
在 Java 中停止线程的实现方法有以下 3 种: 自定义中断标识符,停止线程。 使用线程中断方法 interrupt 停止线程。 使用 stop 停止线程。 其中 stop 方法为 @Deprecated 修饰的过期方法,也就是不推荐使用的过期方法,因为 stop 方法会直接停止线程,这样就没有给
在多线程编程中,wait 方法是让当前线程进入休眠状态,直到另一个线程调用了 notify 或 notifyAll 方法之后,才能继续恢复执行。而在 Java 中,wait 和 notify/notifyAll 有着一套自己的使用格式要求,也就是在使用 wait 和 notify(notifyAll
在 Java 语言中,并发编程都是通过创建线程池来实现的,而线程池的创建方式也有很多种,每种线程池的创建方式都对应了不同的使用场景,总体来说线程池的创建可以分为以下两类: 通过 ThreadPoolExecutor 手动创建线程池。 通过 Executors 执行器自动创建线程池。 而以上两类创建线
sleep 方法和 wait 方法都是用来将线程进入休眠状态的,并且 sleep 和 wait 方法都可以响应 interrupt 中断,也就是线程在休眠的过程中,如果收到中断信号,都可以进行响应,并抛出 InterruptedException 异常。那 sleep 和 wait 的区别都有哪些呢
在 Java 中,线程的创建方法有 7 种,分为以下 3 大类: 继承 Thread 类的方式,它有 2 种实现方法。 实现 Runnable 接口的方式,它有 3 种实现方法。 实现 Callable 接口的方式,它有 2 种实现方法。 接下来我们一个一个来看。 1.继承Thread类 继承 Th
所谓的线程池的 7 大参数是指,在使用 ThreadPoolExecutor 创建线程池时所设置的 7 个参数,如以下源码所示: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
在 Java 语言中,线程分为两类:用户线程和守护线程,默认情况下我们创建的线程或线程池都是用户线程,所以用户线程也被称之为普通线程。 想要查看线程到底是用户线程还是守护线程,可以通过 Thread.isDaemon() 方法来判断,如果返回的结果是 true 则为守护线程,反之则为用户线程。 我们
聊到线程池就一定会聊到线程池的执行流程,也就是当有一个任务进入线程池之后,线程池是如何执行的?我们今天就来聊聊这个话题。线程池是如何执行的?线程池的拒绝策略有哪些? 线程池执行流程 想要真正的了解线程池的执行流程,就得先从线程池的执行方法 execute() 说起,execute() 实现源码如下:
单例模式是面试中的常客了,它的常见写法有 4 种:饿汉模式、懒汉模式、静态内部类和枚举,接下来我们一一来看。 1.饿汉模式 饿汉模式也叫预加载模式,它是在类加载时直接创建并初始化单例对象,所以它并不存在线程安全的问题。它是依靠 ClassLoader 类机制,在程序启动时只加载一次,因此不存在线程安
线程安全是指某个方法或某段代码,在多线程中能够正确的执行,不会出现数据不一致或数据污染的情况,我们把这样的程序称之为线程安全的,反之则为非线程安全的。在 Java 中,解决线程安全问题有以下 3 种手段: 使用线程安全类,比如 AtomicInteger。 加锁排队执行 使用 synchronize
在 Java 语言中,保证线程安全性的主要手段是加锁,而 Java 中的锁主要有两种:synchronized 和 Lock,我们今天重点来看一下 synchronized 的几种用法。 用法简介 使用 synchronized 无需手动执行加锁和释放锁的操作,我们只需要声明 synchronize
在 Java 语言中,有两个线程池可以执行定时任务:ScheduledThreadPool 和 SingleThreadScheduledExecutor,其中 SingleThreadScheduledExecutor 可以看做是 ScheduledThreadPool 的单线程版本,它的用法和
从公平的角度来说,Java 中的锁总共可分为两类:公平锁和非公平锁。但公平锁和非公平锁有哪些区别?孰优孰劣呢?在 Java 中的应用场景又有哪些呢?接下来我们一起来看。 正文 公平锁:每个线程获取锁的顺序是按照线程访问锁的先后顺序获取的,最前面的线程总是最先获取到锁。 非公平锁:每个线程获取锁的顺序
单例模式的实现方法有很多种,如饿汉模式、懒汉模式、静态内部类和枚举等,当面试官问到“为什么单例模式一定要加 volatile?”时,那么他指的是为什么懒汉模式中的私有变量要加 volatile? 懒汉模式指的是对象的创建是懒加载的方式,并不是在程序启动时就创建对象,而是第一次被真正使用时才创建对象。
读写锁(Readers-Writer Lock)顾名思义是一把锁分为两部分:读锁和写锁,其中读锁允许多个线程同时获得,因为读操作本身是线程安全的,而写锁则是互斥锁,不允许多个线程同时获得写锁,并且写操作和读操作也是互斥的。总结来说,读写锁的特点是:读读不互斥、读写互斥、写写互斥。 1.读写锁使用 在
很多场景下,我们需要等待线程池的所有任务都执行完,然后再进行下一步操作。对于线程 Thread 来说,很好实现,加一个 join 方法就解决了,然而对于线程池的判断就比较麻烦了。 我们本文提供 4 种判断线程池任务是否执行完的方法: 使用 isTerminated 方法判断。 使用 getCompl
在 Java 中,线程池的状态和线程的状态是完全不同的,线程有 6 种状态:NEW:初始化状态、RUNNABLE:可运行/运行状态、BLOCKED:阻塞状态、WAITING:无时限等待状态、TIMED_WAITING:有时限等待状态和 TERMINATED:终止状态。而线程池的状态有以下 5 种:
volatile 是 Java 并发编程的重要组成部分,也是常见的面试题之一,它的主要作用有两个:保证内存的可见性和禁止指令重排序。下面我们具体来看这两个功能。 内存可见性 说到内存可见性问题就不得不提 Java 内存模型,Java 内存模型(Java Memory Model)简称为 JMM,主要
1.第一范式 第一范式规定表中的每个列都应该是不可分割的最小单元。比如以下表中的 address 字段就不是不可分割的最小单元,如下图所示: 其中 address 还可以拆分为国家和城市,如下图所示: 这样改造之后,上面的表就满足第一范式了。 2.第二范式 第二范式是在满足第一范式的基础上,规定表中