java基础-IO流【示例篇】

前言

java - IO流系列文章:

一、java基础-IO流【理论篇】

二、java基础-IO流【示例篇】


本文意在整理所有流相关的代码。便于复习和快速参考,
强力推荐文章:Java的IO流总结



一、File 文件类

java.io.File类:文件和目录路径名的抽象表示形式,与平台无关。File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。File对象可以作为参数传递给流的构造函数。

1.1、File类常用方法

在这里插入图片描述

1.2、示例

代码如下(示例):

package IO;

import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.util.Date;
/*
 * java.io.File类
 * 1.凡是与输入、输出相关的类、接口等都定义在java.io包下
 * 2.File是一个类,可以有构造器创建其对象。此对象对应着一个文件(.txt .avi .doc .ppt .mp3 .jpg)或文件目录
 * 3.File类对象是与平台无关的。
 * 4.File中的方法,仅涉及到如何创建、删除、重命名等等。只要涉及文件内容的,File是无能为力的,必须由io流来完成。
 * 5.File类的对象常作为io流的具体类的构造器的形参。
 */
public class TestFile {
    /*
     * 路径:
     * 绝对路径:包括盘符在内的完整的文件路径
     * 相对路径:在当前文件目录下的文件的路径
     *
     *  getName()
        getPath()
        getAbsoluteFile()
        getAbsolutePath()
        getParent()
        renameTo(File newName)

     */
    @Test
    public void test1(){
        File file1 = new File("D:/config.txt");
        File file2 = new File("D:/co.txt");
        System.out.println(file1.getName());
        System.out.println(file1.getAbsoluteFile());
        System.out.println(file1.getAbsolutePath());
        System.out.println(file1.getPath());
        System.out.println(file1.getParent());
        System.out.println();
        System.out.println(file2.getName());
        System.out.println(file2.getAbsoluteFile());
        System.out.println(file2.getAbsolutePath());
        System.out.println(file2.getPath());
        System.out.println(file2.getParent());
        boolean b = file1.renameTo(file2);//要提供完整路径
        System.out.println(b);
    }
    /**
     * 文件检测
     * exists()
     * canWrite()
     * canRead()
     * isFile()
     * isDirectory()
     */
    @Test
    public void test2(){
        System.out.println(System.getProperty("user.dir"));//通过改行代码确定当前路径的相对位置。
        File file = new File("src/IO/config.txt");//注意File的相对路径是相对于当前的user.dir来说的,
        File dir = new File("src/IO/test");
        System.out.println(file.exists());
        System.out.println(file.canExecute());
        System.out.println(file.canRead());
        System.out.println(file.canWrite());
        System.out.println(file.isDirectory());
        System.out.println(new Date(file.lastModified()));
        System.out.println(file.length());
        System.out.println();
        System.out.println(dir.exists());
        System.out.println(dir.canExecute());
        System.out.println(dir.canRead());
        System.out.println(dir.canWrite());
        System.out.println(dir.isDirectory());
        System.out.println(new Date(dir.lastModified()));
        System.out.println(dir.length());
    }
    /*
     *  createNewFile()
        delete()
        mkDir():创建一个文件目录。只有在上层文件目录存在的情况下,才能返回true
        mkDirs():创建一个文件目录。若上层文件目录不存在,一并创建
        list()
        listFiles()
     */
    @Test
    public void test3() throws IOException {
        File file1 = new File("src/IO/a.txt");
        System.out.println(file1.createNewFile());//创建新的文件
        File file2 = new File("src/IO/a");
        file2.mkdir();//创建相对目录,如果成功返回true否则返回false,注意要保证上级目录存在
        File file3 = new File("D:/TTT/TTT");
        file3.mkdirs();//创建目录,如果上级目录不存在则一并创建。
        File file4 = new File("src/IO");
        File[] files = file4.listFiles();//返回目录下的文件列表
        for (int i = 0; i < files.length; i++) {
            System.out.println(files[i]);
        }
    }


	// 判断文件E:\Java\Java学习笔记\IO流\news1.txt 是否存在,如存在就删除。如不存在,则创建
	@Test
	public void m1(){
	    String filePath = "E:\\Java\\Java学习笔记\\IO流\\news1.txt";
	    File file = new File(filePath);
	    if(file.exists()) {
	        if(file.delete())
	            System.out.println("news1.txt 被删除!");
	        else
	            System.out.println("文件删除失败!");
	    }else{
	        try {
	            file.createNewFile();
	            System.out.println("news1.txt 被创建!");
	        } catch (IOException e) {
	            throw new RuntimeException(e);
	        }
	    }
	}

}

二、输入输出流

常见的IO流如下:
在这里插入图片描述


2.1、字节流

代码如下(示例):

package IO;

import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestInputOutput {
    
    /**
    *  从硬盘读取一个文件,并写入到另一个位置。(相当于文件的复制)
    */
    @Test
    public void test(){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        long start = System.currentTimeMillis();
        try(
            fis = new FileInputStream(new File("a.jpg"));
            fos = new FileOutputStream(new File("a1.jpg"));
            //FileInputStream fis = new FileInputStream(srcPath);
            //FileOutputStream fos = new FileOutputStream(destPath);
            ){
               //数组的大小影响文件写出的效率,文件太小多次写入浪费时间,太大则浪费空间。
               byte[] b = new byte[1024*8];
               int len;
               while ((len = fis.read(b))!=-1){
                   fos.write(b,0,len);
               }

           } catch (IOException e) {
              e.printStackTrace();
           }
        
        long end = System.currentTimeMillis();
        System.out.println("时间共花了"+(end-start));
    }
}

2.2、字符流

FileReader和FileWriter用来对文本文件进行读写(注意一般指txt文件,doc文件不是文本文件),其速度效率要快于字节流读取.

文本文件,对于非文本文件(视频文件、音频文件、图片),只能使用字节流!

代码如下(示例):

package IO;

import org.junit.Test;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;


public class TestFileReaderWriter {
   @Test
    public void test() throws IOException {
       FileReader fr = null;
       FileWriter fw = null;
       try (
           fr = new FileReader(new File("src/IO/a.txt"));
           fw =new FileWriter(new File("src/IO/bb.txt"));
           ){
           char[] a = new char[8*1024];
           int len;
           while((len = fr.read(a))!=-1){
               System.out.println(len);
               System.out.println(new String(a,0,len));
               fw.write(a,0,len);
           }

       } catch (IOException e) {
           e.printStackTrace();
       } 
   }
}

2.3、缓冲流

为了提高数据的读写速度,java API提供了带缓冲功能的流,根据数据类型,缓冲流分为
字节缓冲流和字符缓冲流。

2.3.1、字节缓冲流

代码如下(示例):

package IO;

import org.junit.Test;
import java.io.*;

/*
 * 抽象基类            节点流(文件流)           缓冲流(处理流的一种,可以提升文件操作的效率)
 * InputStream        FileInputStream           BufferedInputStream
 * OutputStream       FileOutputStream          BufferedOutputStream  (flush())
 * Reader             FileReader                BufferedReader  (readLine())
 * Writer             FileWriter                BufferedWriter  (flush())
 */
public class TestBuffered {
	/*
	 * 使用缓冲流加速字节流读取非文本文件的速度
	 */
    @Test
    public void test() {
        BufferedInputStream br = null;
        BufferedOutputStream bw = null;
        FileInputStream fis = null;
        FileOutputStream fos = null;
        long start = System.currentTimeMillis();
        try (
            fis = new FileInputStream(new File("a.jpg"));
            fos = new FileOutputStream(new File("a3.jpg"));
            br = new BufferedInputStream(fis);
            bw = new BufferedOutputStream(fos);
            ){
                //数组的大小影响文件写出的效率,文件太小多次写入浪费时间,太大则浪费空间。
            	byte[] b = new byte[1024];
            	int len;
            	while ((len = br.read(b)) != -1) {
                	bw.write(b, 0, len);
            	}
            	bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        } 

        long end = System.currentTimeMillis();
        System.out.println("时间共花了" + (end - start));
    }    
}

2.3.2、字符缓冲流

代码如下(示例):

package IO;

import org.junit.Test;
import java.io.*;

/*
 * 使用缓冲流加速字节流读取非文本文件的速度
 */
    @Test
    public void test2() {
        BufferedReader br = null;
        BufferedWriter bw = null;
        FileReader fr = null;
        FileWriter fw = null;
        try (
            fr = new FileReader(new File("src/IO/a.txt"));
            fw =new FileWriter(new File("src/IO/bb.txt"));
            br = new BufferedReader(fr);
            bw = new BufferedWriter(fw);
            ){
            char[] a = new char[5];
            int len;
            while((len = br.read(a))!=-1){
                System.out.println(len);
                System.out.println(new String(a,0,len));
                bw.write(a);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
         
}

2.4、转换流

转换流可以将字节流读取到的字节,按指定字符集解码成字符
在这里插入图片描述

代码如下(示例):

@Test
    public void test() throws IOException {
    	try(
    	//解码,把字节数组变成字符流
        InputStreamReader isr = new InputStreamReader(new FileInputStream(new File("src/IO/a.txt")));
        //编码,把字符流变成字节数组
        FileOutputStream fos = new FileOutputStream(new File("src/IO/bbb.txt"));
        // 【指定字符集】
        OutputStreamWriter osr = new OutputStreamWriter(fos ,"utf-8");
        BufferedReader br = new BufferedReader(isr);
        BufferedWriter bw = new BufferedWriter(osr);
        ){
	        int len;
	        char[] c = new char[8*1024];
	        while((len = br.read(c))!=-1){
	            bw.write(c,0,len);
	            bw.flush();
	        }
        }catch(Exception ext){
        }
    }

2.5、数据流

数据流:用来处理基本数据类型、String、字节数组的数据
在这里插入图片描述

代码如下(示例):

@Test
    public void test4() throws Exception {
        DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("data.txt"));
        dataOutputStream.writeUTF("我爱你,而你不知道");
        dataOutputStream.writeBoolean(true);
        dataOutputStream.writeInt(12);
        dataOutputStream.close();//会乱码,但是再次读的时候会恢复
        DataInputStream dataInputStream = new DataInputStream(new FileInputStream(new File("data.txt")));
//        byte[] b =new byte[10];
//        int len;
//        while((len = dataInputStream.read(b))!=-1){
//            System.out.println(new String(b,0,len));
//        }
        System.out.println(dataInputStream.readUTF());
        System.out.println(dataInputStream.readBoolean());
        System.out.println(dataInputStream.readInt());
        dataInputStream.close();
    }

2.6、对象流

在这里插入图片描述

代码如下(示例):

package IO;

import org.junit.Test;

import java.io.*;

public class TestObjectInputOutputStream {

    /**
    * 对象的序列化过程:将内存中的对象通过ObjectOutputStream转换为二进制流,存储在硬盘文件中
    */
    @Test
    public void test() throws IOException {
        Person person = new Person("花花", 12, new Pet("哈哈"));
        Person person1 = new Person("瓜瓜", 22, new Pet("大大"));
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"));
        oos.writeObject(person);
        oos.flush();
        oos.writeObject(person1);
        oos.flush();
        oos.close();
    }
    
    /**
    * 对象的反序列化过程:将硬盘中的文件通过ObjectInputStream转换为相应的对象
    */
    @Test
    public void test1() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"));
        Person person = (Person) ois.readObject();
        Person person1 = (Person) ois.readObject();
        System.out.println(person);
        System.out.println(person1);
    }
}


/*
 * 要实现序列化的类: 1.要求此类是可序列化的:实现Serializable接口
 * 2.要求类的属性同样的要实现Serializable接口
 * 3.提供一个版本号:private static final long serialVersionUID
 * 4.使用static或transient修饰的属性,不可实现序列化
 */
class Person implements Serializable{
    private static final long serialVersionUID = 23456789L;
    String name;
    Integer age;
    Pet pet;
    public Person(String name, Integer age,Pet pet) {
        this.name = name;
        this.age = age;
        this.pet = pet;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", pet=" + pet +
                '}';
    }
}
class Pet implements Serializable{
    String name;

    public Pet(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Pet{" +
                "name='" + name + '\'' +
                '}';
    }
}

2.7、随机访问

在这里插入图片描述
在这里插入图片描述

代码如下(示例):

package IO;

import org.junit.Test;

import java.io.File;
import java.io.RandomAccessFile;

public class TestRandomAccessFile {
    @Test//RandomAccessFile进行文件的读写
    public void test1() throws Exception {
        RandomAccessFile randomAccessFile = new RandomAccessFile(new File("src/IO/a.txt"),"r");
        RandomAccessFile randomAccessFile1 = new RandomAccessFile(new File("src/IO/aa.txt"),"rw");
        int len;
        byte[] b = new byte[10];
        while ((len = randomAccessFile.read(b))!=-1){
            randomAccessFile1.write(b,0,len);
        }
        randomAccessFile1.close();
        randomAccessFile.close();
    }
    
    @Test//实际上是覆盖的效果
    public void test2() throws Exception {
        RandomAccessFile randomAccessFile1 = new RandomAccessFile(new File("src/IO/aa.txt"),"rw");
        randomAccessFile1.seek(4);
        //在第四个字符出写入xy,实则是覆盖,注意汉字一个字占两个字符,如26个字符覆盖后abcdxyghijklmnopqrstuvwxyz
        randomAccessFile1.write("xy".getBytes());
        randomAccessFile1.close();
    }
    
    @Test//处理覆盖
    public void test3() throws Exception {
        RandomAccessFile randomAccessFile1 = new RandomAccessFile(new File("src/IO/aa.txt"),"rw");
        randomAccessFile1.seek(4);
        String str = randomAccessFile1.readLine();//弊端是只能处理一行
        randomAccessFile1.seek(4);//指针已经移动,需要调整
        randomAccessFile1.write("xy".getBytes());
        randomAccessFile1.write(str.getBytes());//拿出来在追加上
        randomAccessFile1.close();//abcdxyefghijklmnopqrstuvwxyz
    }
    
    @Test//更通用
    public void test4() throws Exception {
        RandomAccessFile randomAccessFile1 = new RandomAccessFile(new File("src/IO/aa.txt"),"rw");
        randomAccessFile1.seek(4);
        byte[] b = new byte[10];
        int len;
        StringBuffer sb = new StringBuffer();
        while((len = randomAccessFile1.read(b)) != -1){
            sb.append(new String(b,0,len));
        }
        randomAccessFile1.seek(4);//指针已经移动,需要调整
        randomAccessFile1.write("xy".getBytes());
        randomAccessFile1.write(sb.toString().getBytes());//拿出来在追加上
        randomAccessFile1.close();//abcdxyefghijklmnopqrstuvwxyz
    }

}

2.8、 Properties类

代码如下(示例):

public static void main(String[] args) {
    String filePath = "E:\\Java\\Java学习笔记\\IO流\\Dir\\mysql.properties";
    // 使用 Properties 读取配置文件
    // 1. 创建Properties对象
    Properties properties = new Properties();
    try {
        // 2. 加载配置文件中的键值对
        properties.load(new FileReader(filePath));
        // 3.把键值对显示到控制台
        properties.list(System.out);
        // 4.根据key 获取对应的值
        String dbName = properties.getProperty("dbName");
        String userName = properties.getProperty("userName");
        System.out.println("dbName=" + dbName);
        System.out.println("userName=" + userName);

        System.out.println("=========================");

        // 1. 根据Properties 类修改/添加 键值对
        properties.setProperty("ip","127.0.0.1");
        properties.setProperty("dbName", "NewDbName");
        // 2. 存储到文件中
        properties.store(new FileWriter(filePath), null);  // comments  注释/注解

        // 把键值对显示到控制台
        properties.load(new FileReader(filePath));
        properties.list(System.out);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    System.out.println();
}


2.9、字节数组流

字节数组流,可以很容易获取字节数组【baos.getByteArray()】,方便输入流转输出流。

代码如下(示例):

import java.io.*;
public class DataStream {
	public static void main(String[] args) {
		ByteArrayOutputStream baos=new ByteArrayOutputStream();//创建字节数组流,同时会在内存里面创建数组
		DataOutputStream dos=new DataOutputStream(baos);//对字节数组流外封装成数据处理流
		try {
			dos.writeDouble(Math.random());//利用数据流里面的写入方法,写一个Double类型的随机数据
			dos.writeBoolean(true);
			//toByteArray()方法是创建一个新分配的字节数组。数组的大小和当前输出流的大小。这里指的是baos这个字节数组
			ByteArrayInputStream bias=new ByteArrayInputStream(baos.toByteArray());
			System.out.println(bias.available());
			DataInputStream dis=new DataInputStream(bias);
			System.out.println(dis.readDouble());
			System.out.println(dis.readBoolean());		
			dos.close();
			dis.close();
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
}

三、 Apache IO包

常用的工具类是 FileUtils 和 IOUtils


四、 常见问题

4.1、 字符串转 byte[]

String str = "hello,world";
byte[] b = str.getBytes();

参考资料:

1、【Java基础-3】吃透Java IO:字节流、字符流、缓冲流
2、Java的IO流总结
3、Java基础IO流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值