IO流的使用

立山  金牌会员 | 2022-6-25 12:41:22 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 799|帖子 799|积分 2397

1. File类

介绍


  • java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关
  • File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。
  • 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
  • File对象可以作为参数传递给流的构造器
常用构造器
   public File(String pathname) public
File(String parent,String child)
public File(File parent,String child)
  路径分隔符
路径中的每级目录之间用一个路径分隔符隔开, windows和DOS系统默认使用“\”来表示,UNIX和URL使用“/”来表示。Java程序支持跨平台运行,因此路径分隔符要慎用。为了解决这个隐患,File类提供了一个常量:public static final String separator。根据操作系统,动态的提供分隔符。
常用方法



栗子:筛选出以.txt结尾的文件,并打印文件名
  1.        File data = new File("E:\\CODE\\review\\javaReview\\data");
  2.         File[] files = data.listFiles();
  3.         //帅选出后缀为.txt的文件,并打印
  4.         for (File file : files) {
  5.             String name = file.getName();
  6.             if(name.contains(".txt")){
  7.                 System.out.println(name);
  8.             }
  9.         }
复制代码
2. IO流整体介绍

概述
I/O是Input/Output的缩写, I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通讯等。Java程序中,对于数据的输入/输出操作以“流(stream)” 的
方式进行。 java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。
   输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。
  IO流的分类

IO流体系如下:

4大抽象基类的说明
输入流基类Inputstream & Reader
InputStream 和 Reader 是所有输入流的基类。InputStream的典型实现为FileInputStream,用于读取数据的常用方法如下:
  1. int read()
  2. int read(byte[] b)
  3. int read(byte[] b, int off, int len)
  4. //以上三个方法读取到流末尾时均会返回-1
复制代码
Reader的典型实现为FileReader,读取数据常用的方法如下:
  1. int read()
  2. int read(char [] c)
  3. int read(char [] c, int off, int len)
复制代码
FileInputStream 从文件系统中的某个文件中获得输入字节。FileInputStream用于读取非文本数据之类的原始字节流。要读取字符流,需要使用 FileReader。要注意的是,程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源
输出流基类 OutputStream && Writer
OutputStream 和 Writer 也非常相似,提供的常用方法主要如下:
   void write(int b/int c);
void write(byte[] b/char[] cbuf);
void write(byte[] b/char[] buff, int off, int len);
void flush();
void close(); 需要先刷新,再关闭此流
  但因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组,即以 String 对象作为参数,Writer额外的写出数据的方法如下:
   void write(String str);
void write(String str, int off, int len);
  FileOutputStream 从文件系统中的某个文件中获得输出字节。FileOutputStream用于写出非文本数据之类的原始字节流。要写出字符流,需要使用 FileWriter。
3. 节点流的使用

节点输入流:FileInputStream \ FileReader
节点输出流:FileOuputStream \ FileWriter
使用节点流读取文件的步骤:

  • 建立一个流对象,将已存在的一个文件加载进流。
  • 创建一个临时存放数据的数组。
  • 调用流对象的读取方法将流中的数据读入到数组中。
  • 关闭资源。
栗子1:使用FileReader读取文件内容并打印
  1.         FileReader reader = null;
  2.         try {
  3.             reader = new FileReader(new File("E:\\CODE\\review\\javaReview\\data\\data1.txt"));
  4.             char[] chars = new char[1024];
  5.             int len ;
  6.             while ((len = reader.read(chars)) != -1){
  7.                 System.out.println(new String(chars,0 ,len));
  8.             }
  9.         } catch (IOException e) {
  10.             e.printStackTrace();
  11.         }finally {
  12.             try {
  13.                 reader.close();
  14.             } catch (IOException e) {
  15.                 e.printStackTrace();
  16.             }
  17.         }
复制代码
栗子二:使用FileInputStream和FileOutputStream实现文件的复制
  1.         FileInputStream fin = null;
  2.         FileOutputStream fout = null;
  3.         try {
  4.             fin = new FileInputStream(new File("E:\\CODE\\review\\javaReview\\data\\01.jpg"));
  5.             fout = new FileOutputStream(new File("E:\\CODE\\review\\javaReview\\data\\02.jpg"));
  6.             byte[] buff = new byte[1024];
  7.             int len;
  8.             while ((len = fin.read(buff)) != -1){
  9.                 fout.write(buff,0, len);
  10.                 fout.flush();
  11.             }
  12.         } catch (IOException e) {
  13.             e.printStackTrace();
  14.         }finally {
  15.             try {
  16.                 fin.close();
  17.             } catch (IOException e) {
  18.                 e.printStackTrace();
  19.             }
  20.             try {
  21.                 fout.close();
  22.             } catch (IOException e) {
  23.                 e.printStackTrace();
  24.             }
  25.         }
复制代码
节点流使用注意点


  • 定义文件路径时,注意:可以用“/”或者“\”。
  • 在写入一个文件时,如果使用构造器FileOutputStream(file),则目录下有同名文件将被覆盖。
  • 如果使用构造器FileOutputStream(file,true),则目录下的同名文件不会被覆盖,在文件内容末尾追加内容。
  • 在读取文件时,必须保证该文件已存在,否则报异常。
  • 字节流操作字节,比如:.mp3,.avi,.rmvb,mp4,.jpg,.doc,.ppt
  • 字符流操作字符,只能操作普通文本文件。最常见的文本文件:.txt,.java,.c,.cpp 等语言的源代码。尤其注意.doc,excel,ppt这些不是文本文件。
4. 处理流

4.1 缓冲流

为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:


  • BufferedInputStream 和 BufferedOutputStream
  • BufferedReader 和 BufferedWriter
当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次性从文件中读取8192个(8Kb),存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个8192个字节数组。向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法flush()可以强制将缓冲区的内容全部写入输出流。 关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流。

栗子:使用BufferReader和BufferWriter实现文本文件的复制
  1.         BufferedReader br = null;
  2.         BufferedWriter bw = null;
  3.         try {
  4.             br = new BufferedReader(new FileReader("E:\\CODE\\review\\javaReview\\data\\data1.txt"));
  5.             bw = new BufferedWriter(new FileWriter("E:\\CODE\\review\\javaReview\\data\\data3.txt"));
  6.             String buff;
  7.             while ((buff = br.readLine()) != null){
  8.                 bw.write(buff);
  9.                 bw.newLine();
  10.             }
  11.         } catch (Exception e) {
  12.             e.printStackTrace();
  13.         }finally {
  14.             try {
  15.                 br.close();
  16.             } catch (IOException e) {
  17.                 e.printStackTrace();
  18.             }
  19.             try {
  20.                 bw.close();
  21.             } catch (IOException e) {
  22.                 e.printStackTrace();
  23.             }
  24.         }
复制代码
4.2 转换流

转换流提供了在字节流和字符流之间的转换,Java API提供了两个转换流:


  • InputStreamReader:将InputStream转换为Reader
  • OutputStreamWriter:将Writer转换为OutputStream
InputStreamReader


  • 实现将字节的输入流按指定字符集转换为字符的输入流。
  • 需要和InputStream“套接”。
  • 构造器
   public InputStreamReader(InputStream in)
public InputSreamReader(InputStream in,String charsetName)
  OutputStreamWriter


  • 实现将字符的输出流按指定字符集转换为字节的输出流。
  • 需要和OutputStream“套接”。
  • 构造器
   public OutputStreamWriter(OutputStream out)
public OutputSreamWriter(OutputStream out,String charsetName)
  
  1.         FileInputStream fis = null;
  2.         FileOutputStream fos = null;
  3.         InputStreamReader isr = null;
  4.         OutputStreamWriter osw = null;
  5.         BufferedReader br = null;
  6.         BufferedWriter bw = null;
  7.         try {
  8.             fis = new FileInputStream("E:\\CODE\\review\\javaReview\\data\\data1.txt");
  9.             fos = new FileOutputStream("E:\\CODE\\review\\javaReview\\data\\data4.txt");
  10.             //使用转换流转换
  11.             isr = new InputStreamReader(fis);
  12.             osw = new OutputStreamWriter(fos);
  13.             br = new BufferedReader(isr);
  14.             bw = new BufferedWriter(osw);
  15.             String str;
  16.             while ((str = br.readLine()) != null){
  17.                 bw.write(str);
  18.                 bw.newLine();
  19.             }
  20.         } catch (Exception e) {
  21.             e.printStackTrace();
  22.         }finally {
  23.             try {
  24.                 br.close();
  25.             } catch (IOException e) {
  26.                 e.printStackTrace();
  27.             }
  28.             try {
  29.                 bw.close();
  30.             } catch (IOException e) {
  31.                 e.printStackTrace();
  32.             }
  33.         }
复制代码
4.3 对象流

ObjectInputStream && OjbectOutputSteam对象流,用于存储和读取基本数据类型数据或对象的处理流,对象流的作用如下:
ObjectOutputStream:内存中的对象—>存储中的文件、通过网络传输出去:序列化过程
ObjectInputStream:存储中的文件、通过网络接收过来 —>内存中的对象:反序列化过程
对象的序列化
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。
对象系列化步骤:

  • 需要实现接口:Serializable
  • 当前类提供一个全局常量:serialVersionUID
  • 除了当前Person类需要实现Serializable接口之外,还必须保证其内部所属性 也必须是可序列化的。(默认情况下,基本数据类型可序列化)
栗子:
  1.     @Test
  2.     public void test1(){
  3.         //测试对象序列化
  4.         ObjectOutputStream oos = null;
  5.         try {
  6.            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
  7.            oos.writeObject(new String("我爱中国!!"));
  8.            oos.writeObject(new Student("1001","小强"));
  9.         } catch (IOException e) {
  10.             e.printStackTrace();
  11.         }finally {
  12.             try {
  13.                 oos.close();
  14.             } catch (IOException e) {
  15.                 e.printStackTrace();
  16.             }
  17.         }
  18.     }
  19.     @Test
  20.     public void test2(){
  21.         //反序列化
  22.         ObjectInputStream ois = null;
  23.         try {
  24.             ois = new ObjectInputStream(new FileInputStream("object.dat"));
  25.             String str = (String)ois.readObject();
  26.             System.out.println(str);
  27.             Student stu = (Student)ois.readObject();
  28.             System.out.println(stu);
  29.         } catch (Exception e) {
  30.             e.printStackTrace();
  31.         }finally {
  32.         }
  33.     }
  34.     public class Student implements Serializable {
  35.     private static final long serialVersionUID = 12345678765432L;
  36.     private String id;
  37.     private String name;
  38.     public Student(String id, String name) {
  39.         this.id = id;
  40.         this.name = name;
  41.     }
  42.     @Override
  43.     public String toString() {
  44.         return "Student{" +
  45.                 "id='" + id + '\'' +
  46.                 ", name='" + name + '\'' +
  47.                 '}';
  48.     }
  49. }
复制代码
4.4 随机存储文件流

RandomAccessFile 声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了DataInput、DataOutput这两个接口,也就意味着这个类既可以读也可以写。RandomAccessFile 类支持 “随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件:
   

  • 支持只访问文件的部分内容
  • 可以向已存在的文件后追加内容
  • RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。
  RandomAccessFile 类对象可以自由移动记录指针:


  • long getFilePointer():获取文件记录指针的当前位置
  • void seek(long pos):将文件记录指针定位到 pos 位置
构造器


  • public RandomAccessFile(File file, String mode)
  • public RandomAccessFile(String name, String mode)
    mode参数有如下4种:
   r: 以只读方式打开
rw:打开以便读取和写入
rwd:打开以便读取和写入;同步文件内容的更新
rws:打开以便读取和写入;同步文件内容和元数据的更新
  1. @Test
  2. public void test3() throws IOException {
  3.     RandomAccessFile raf1 = new RandomAccessFile("hello.txt","rw");
  4.     raf1.seek(3);//将指针调到角标为3的位置
  5.     //保存指针3后面的所数据到StringBuilder中
  6.     StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
  7.     byte[] buffer = new byte[20];
  8.     int len;
  9.     while((len = raf1.read(buffer)) != -1){
  10.         builder.append(new String(buffer,0,len)) ;
  11.     }
  12.     //调回指针,写入“xyz”
  13.     raf1.seek(3);
  14.     raf1.write("xyz".getBytes());
  15.     //将StringBuilder中的数据写入到文件中
  16.     raf1.write(builder.toString().getBytes());
  17.     raf1.close();
  18. }
复制代码
5. Path/Paths/Files的使用

NIO简单概述


  • Java NIO (New IO,Non-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API,可以替代标准的Java IO AP。
  • NIO与原来的IO同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。
  • NIO将以更加高效的方式进行文件的读写操作。
  • 随着 JDK 7 的发布,Java对NIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为 NIO.2。
Path类:JDK7提供
实例化方法:


  • static Path get(String first, String … more) : 用于将多个字符串串连成路径
  • static Path get(URI uri): 返回指定uri对应的Path路径
Path 常用方法:

Files类:JDK7提供
用途:用于操作文件或目录的工具类
常用方法:



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

立山

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表