Java教程

11.Java SE IO流

本文主要是介绍11.Java SE IO流,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

IO 流

  • 流的分类
  • FileReader、FileWriter的使用(输入、输出的标准化过程)
  • FileInputStream / FileOutStream 的使用:
  • 缓冲流
  • 转换流的使用
  • 对象流的使用
  • RandomAccessFile的使用
  • NIO

流的分类

  1. 按操作数据单位分为:字节流、字符流。
  2. 按数据流向分类分为:输入流、输出流。
  3. 按流的角色分类分为:字点流、处理流。

Java IO 流中共涉及 40 多个类,但都是有下面这四个类派生出来:在这里插入图片描述

FileReader、FileWriter的使用(输入、输出的标准化过程)

输入过程:

  1. 创建 File 类的对象,指明读取数据的来源,且此文件一定要存在。
  2. 创建相应的输入流,将 File 类的对象作为参数,传入流的构造器中。
  3. 具体读入过程:创建相应的 byte[] 或 char[]。
  4. 关闭流资源。
  5. 例子代码如下:
public void testFileReader(){
	FileReader fr = null;
	try{
		File file = new File("hello.txt");
		fr = new FileReader(file);
		char[] cbuf = new char[5];
		int len;
		//read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1
		while((len = fr.read(cbuf)) != -1){
			String str = new String(cbuf,0,len);
			System.out.print(str);
		}
	}catch(IOException e){
		e.printStackTrace();
	}finally{
		if(fr != null){
			try{
				fr.close();
			}catch (IOException e){
				e.printStackTrance();
			}
		}
	}
}

输出过程:

  1. 创建 File 类的对象,指明写出的数据位置,此文件可以不存在,没有会自动创建;有也可以覆盖。这就需要了解 FileWriter的构造器。
    ① FileWriter(file,false),对原文件覆盖,默认的。
    ② FileWriter(file,true),不会覆盖原文件,在尾部追加。
  2. 同上,作为流的参数传到构造器里。
  3. 具体的写出过程:write(char[]/byte[] buffer,0,len)
  4. 关闭资源
  5. 例子代码如下:
public void testFileWriter(){
   FileWriter fw = null;
   try{
   		File file = new File("hello1.txt");
   		fw = new FileWriter(file);
   		fw.write("Hello Java\n");
   		fw.wrrite("从入门到放弃");
   	}catch(IOException e){
   		e.printStackTrance();
   	}finally{
   		if(fw != null){
   			try{
   				fw.close();
   				}catch(IOException e){
   					e.printStackTrace();
   				}
   			}
   		}
   	}

FileInputStream / FileOutStream 的使用:

对于文本文件(.txt,java等),使用字符流处理。
对于非文本文件(.jpg,.mp4等),使用字节流处理。

两个方法:

  1. FileInputStream 中的 int read(byte b[]),从此输入流中读取最多 b.length 个字节的数据到一个字节数组中。
  2. FileOutputStream 中的 void write(byte b[],int off,int len),将字节数组中的 len 个字节从偏移量 off 开始写入此文件输出流。

例子:实现对图片的复制操作。

public void testFileInputOutputStream(){
	FileInputStream fis = null;
	FileOutputStream fos = null;
	try{
		File srcFile = new File("1.jpg");
		File destFile = new File("2.jpg");
		fis = new FileInputStream(srcFile);
		fos = new FileOutputStream(destFile);
		byte[] buffer = new byte[5];
		int len;
		while((len = fis.read(buffer)) != -1){
			fos.write(buffer,0,len);
		}
	}catch(IOException e){
		e.printStackTrace();
	}finally{
		if(fos != null){
			try{
				fos.close();
			}catch(IOException e){
				e.printStackTrace();
			}
		}
		if(fis != null){
			try{
				fis.close();
			}catch(IOException e){
				e.printStackTrace();
			}
		}
	}
}

缓冲流

涉及到的类:

BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter

作用:内部提供一个缓冲区,默认 8k;它提升流的读取、写入的速度。

例子:使用 BufferInputStream 和 BufferOutputStream :处理非文本文件。

//实现文件复制的方法
public void copyFileWrithBuffered(String srcPath,String destPath){
	BufferedInputStream bis = null;
	BufferedOutputStream bos = null;
	try{
		FileInputStream fis = new FileInputStream(srcFile);
		FileOutputStream fos = new FileOutputStream(destFile);
		//造缓冲流
		bis = new BufferedInputStream(fis);
		bos = new BufferedOutputStream(fos);
		
		byte[] buffer = new byte[1024];
		int len;
		while((len = bis.read(buffer)) != -1){
			bos.write(buffer,0,len);
		}
	}catch(IOException e){
		e.printStackTrace();
	}finally{
		if(bos != null){
			try{
				bos.close();
			}catch(IOException e){
				e.printStackTrace();
			}
			if(bis != null){
			try{
				bos.close();
			}catch(IOException e){
				e.printStackTrace();
			}
		}
	}

例子:使用 BufferedReader 和 BufferedWriter:处理文本文件

 public void testBufferedReaderBufferedWriter(){
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            //创建文件和相应的流
            br = new BufferedReader(new FileReader(new File("dbcp.txt")));
            bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt")));

            //读写操作
            //方式一:使用char[]数组
//            char[] cbuf = new char[1024];
//            int len;
//            while((len = br.read(cbuf)) != -1){
//                bw.write(cbuf,0,len);
//    //            bw.flush();
//            }

            //方式二:使用String
            String data;
            while((data = br.readLine()) != null){
                //方法一:
//                bw.write(data + "\n");//data中不包含换行符
                //方法二:
                bw.write(data);//data中不包含换行符
                bw.newLine();//提供换行的操作

            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if(bw != null){

                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

    }

转换流的使用

转换流涉及到的类:输入字符流。

  1. InputStreamReader:将一个字节的输入流转换为字符的输入流
    解码:字节、字节数组 —>字符数组、字符串
  2. OutputStreamWriter:将一个字符的输出流转换为字节的输出流
    编码:字符数组、字符串 —> 字节、字节数组

说明:编码决定了解码的方式

作用:提供字节流和字符流之间的转换:在这里插入图片描述
例子:

 public void test1() throws IOException {

        FileInputStream fis = new FileInputStream("dbcp.txt");
//        InputStreamReader isr = new InputStreamReader(fis);//使用系统默认的字符集
        //参数2指明了字符集,具体使用哪个字符集,取决于文件dbcp.txt保存时使用的字符集
        InputStreamReader isr = new InputStreamReader(fis,"UTF-8");//使用系统默认的字符集

        char[] cbuf = new char[20];
        int len;
        while((len = isr.read(cbuf)) != -1){
            String str = new String(cbuf,0,len);
            System.out.print(str);
        }

        isr.close();

    }

/*
此时处理异常的话,仍然应该使用try-catch-finally

综合使用InputStreamReader和OutputStreamWriter
 */
@Test
public void test2() throws Exception {
    //1.造文件、造流
    File file1 = new File("dbcp.txt");
    File file2 = new File("dbcp_gbk.txt");

    FileInputStream fis = new FileInputStream(file1);
    FileOutputStream fos = new FileOutputStream(file2);

    InputStreamReader isr = new InputStreamReader(fis,"utf-8");
    OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");

    //2.读写过程
    char[] cbuf = new char[20];
    int len;
    while((len = isr.read(cbuf)) != -1){
        osw.write(cbuf,0,len);
    }

    //3.关闭资源
    isr.close();
    osw.close();


}

对象流的使用

  1. 对象流:ObjectInputStream 和 ObjectOutputStream

  2. 序列化和反序列化:
    ① Java 序列化就是指把 Java 对象转换为字节序列的过程。
    ② Java反序列化就是指把字节序列恢复为Java对象的过程。

  3. 作用:
    ① ObjectOutputStream:内存中的对象—>存储中的文件、通过网络传输出去:序列化过程。
    ② ObjectInputStream:存储中的文件、通过网络接收过来 —>内存中的对象:反序列化过程。

  4. 对象序列化机制:对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。

  5. 序列化代码实现:
    ① 实现序列化的对象所属的类需要满足:实现了 Serializable 接口、当前类提供一个全局常量 serialVersionUID;
    ② 除了当前类需要实现 Serializable 接口外,还必须保证内部的属性也必须是可序列化的。默认情况下,基本数据类型是可序列化。
    ③ ObjectInputStream 和 ObjectOutputStream 不能序列化 static 和 transient 修饰的成员变量。
    ④ 代码:

@Test
public void testObjectOutputStream(){
    ObjectOutputStream oos = null;

    try {
        //1.
        oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
        //2.
        oos.writeObject(new String("我爱北京天安门"));
        oos.flush();//刷新操作

         oos.writeObject(new Person("王铭",23));
        oos.flush();

        oos.writeObject(new Person("张学良",23,1001,new Account(5000)));
        oos.flush();

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(oos != null){
            //3.
            try {
                oos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}
  1. 反序列化:
@Test
public void testObjectInputStream(){
    ObjectInputStream ois = null;
    try {
        ois = new ObjectInputStream(new FileInputStream("object.dat"));

        Object obj = ois.readObject();
        String str = (String) obj;

        Person p = (Person) ois.readObject();
        Person p1 = (Person) ois.readObject();

        System.out.println(str);
        System.out.println(p);
        System.out.println(p1);

    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        if(ois != null){
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

RandomAccessFile的使用

1、随机存取文件流:RandomAccessFile
2、使用说明:

RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
如果写出到的文件存在,则会对原文件内容进行覆盖。(默认情况下,从头覆盖)
可以通过相关的操作,实现RandomAccessFile“插入”数据的效果。seek(int pos)

经典代码:

@Test
public void test1() {

    RandomAccessFile raf1 = null;
    RandomAccessFile raf2 = null;
    try {
        //1.
        raf1 = new RandomAccessFile(new File("爱情与友情.jpg"),"r");
        raf2 = new RandomAccessFile(new File("爱情与友情1.jpg"),"rw");
        //2.
        byte[] buffer = new byte[1024];
        int len;
        while((len = raf1.read(buffer)) != -1){
            raf2.write(buffer,0,len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        //3.
        if(raf1 != null){
            try {
                raf1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        if(raf2 != null){
            try {
                raf2.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

经典代码二:

/*
使用RandomAccessFile实现数据的插入效果
 */
@Test
public void test3() throws IOException {

    RandomAccessFile raf1 = new RandomAccessFile("hello.txt","rw");

    raf1.seek(3);//将指针调到角标为3的位置
    //保存指针3后面的所数据到StringBuilder中
    StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
    byte[] buffer = new byte[20];
    int len;
    while((len = raf1.read(buffer)) != -1){
        builder.append(new String(buffer,0,len)) ;
    }
    //调回指针,写入“xyz”
    raf1.seek(3);
    raf1.write("xyz".getBytes());

    //将StringBuilder中的数据写入到文件中
    raf1.write(builder.toString().getBytes());

    raf1.close();

    //思考:将StringBuilder替换为ByteArrayOutputStream
}

NIO

1、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。

2、Path的说明:

Path替换原有的File类。
3、如何实例化:
Paths类提供的静态get()方法用来获取Path对象:
static Path get(String first, String … more):用于将多个字符串串连成路径>static Path get(URl uri):返回指定uri对应的Path路径

4、常用方法:

String toString():返回调用Path 对象的字符串表示形式
boolean startsWith(String path):判断是否以path 路径开始
boolean endsWith(String path):判断是否以path 路径结束
boolean isAbsolute()∶判断是否是绝对路径
Path getParent():返回Path对象包含整个路径,不包含Path对象指定的文件路径
Path getRoot():返回调用Path 对象的根路径
Path getFileName():返回与调用Path 对象关联的文件名
int getNameCount()∶返回Path 根目录后面元素的数量
Path getName(int idx):返回指定索引位置idx的路径名称
Path toAbsolutePath():作为绝对路径返回调用Path 对象
Path resolve(Path p):合并两个路径,返回合并后的路径对应的Path对象
File toFile():将Path转化为File类的对象

5、Files工具类—jdk7提供—常用方法

Path copy(Path src,Path dest,CopyOption … how):文件的复制
Path createDirectory(Path path, FileAttribute<?> ... attr):创建一个目录Path createFile(Path path,FileAttribute<?> … arr):创建一个文件
void delete(Path path):删除一个文件/目录,如果不存在,执行报错
void deletelfExists(Path path): Path对应的文件/目录如果存在,执行删除
Path move(Path src,Path dest, CopyOption…how):将src移动到dest位置
long size(Path path):返回path 指定文件的大小
Files常用方法:用于判断
boolean exists(Path path,LinkOption … opts):判断文件是否存在
boolean isDirectory(Path path,LinkOption … opts):判断是否是目录
boolean isRegularFile(Path path, LinkOption … opts):判断是否是文件
boolean isHidden(Path path):判断是否是隐藏文件
boolean isReadable(Path path):判断文件是否可读
boolean isWritable(Path path):判断文件是否可写
boolean notExists(Path path, LinkOption … opts):判断文件是否不存在
Files常用方法:用于操作内容
SeekableByteChannel newByteChannel(Path path, OpenOption…how):获取与指定文件的连接,how指定打开方式。
DirectoryStream newDirectoryStream(Path path):打开path 指定的目录
InputStream newInputStream(Path path, OpenOption…how):获取InputStream对象
OutputStream newOutputStream(Path path, OpenOption…how):获取OutputStream对象

参考: https://www.bilibili.com/video/BV1Kb411W75N?from=search&seid=8802845884941874275&spm_id_from=333.337.0.0

这篇关于11.Java SE IO流的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!