欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

16.IO流(字节流,字符流,数据流、对象流)

程序员文章站 2024-01-20 15:44:58
...

I/O框架

1. IO框架介绍

I:input

O:output

流:

按数据流向划分:输入流、输出流

按处理单元划分:字节流,字符流

2. File类

2.1 File类构造方法

File类提供了用于操作文件和获取文件信息的一系列方法

1.File类的构造方法:

File(String pathname) :

File(File parent, String child): 根据父类路径名与子类路径名字字符串创建新的file实例(便于先处理父类路径);

File(String parent, String child): 与上式类似

2.2 File类常用方法(增删改查)

1.创建:

  • createNewFile()

  • mkdir() 创建文件夹

  • mkdirs() 创建多级文件夹,用\\或/隔开

  • renameTo(File dest) 重命名文件或文件夹,如果目标文件与源文件是在同一个路径下,那么renameTo的作用是重命名,如果目标文件与源文件不是在同一个路径下,那么renameTo的作用就是剪切,而且还不能操作文件夹。

注:

separatorChar:目录分隔符

separator包含一个separatorChar,字符串形式。

均是静态,File类直接调用

new File("C:" + File.separator + "a.txt");

2.删除:

  • delete() 删除文件或一个空文件夹(非空不能删),有返回值

  • deleteOnExit() 保证程序异常时创建的临时文件也可以被删除,无返回值,一般用于删除临时文件

3.判断

  • exists()

  • isFile()

  • isDirectory()

  • isAbsolute() 测试此抽象路径名是否为绝对路径名。

4.获取

  • getName()

  • getPath()

  • getAbsolutePath()

  • length()

  • lastModified() 获取最后一次被修改的时间(毫秒值)。

/**
 *  File类 提供了文件和目录相关的操作的方法
 *  位于java.io包
 * @author asus
 *
 */
public class TestFile {
    public static void main(String[] args) {
        File file = new File("A");
        file.mkdir(); // 创建一个文件夹 
        
        File files = new File("B/C/D");
        files.mkdirs(); 
        file.delete();
        files.delete(); // B 文件夹中有内容 不能删除    
        File file1 = new File("a.txt"); // 相对路径 相对于我们当前操作的目录而言的路径
        File file2 = new File("C:\\Users\\WHD\\Desktop\\test.txt"); // 绝对路径 具体的路径
        try {
            file1.createNewFile(); // 返回值 true表示创建成功  false表示创建失败
            file2.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        System.out.println("a.txt文件是否存在" + file1.exists());
        System.out.println("a.txt文件的相对路径" + file1.getPath());
        System.out.println("a.txt文件的绝对路径" + file1.getAbsolutePath());
        System.out.println("a.txt文件的大小" + file1.length());
        System.out.println("a.txt文件的名称" + file1.getName());
        System.out.println("a.txt是否是一个文件" + file1.isFile());
        System.out.println("a.txt是否是一个文件夹" + file1.isDirectory());
        System.out.println("是否删除成功" + file1.delete());
    }
}

3.字节流

3.1 FileInputStream

父类abstract InputStream

子类FileInputStream:基于字节的文件输入流

int read():每次读取一个字节,返回值是读取的内容的ascii码

int read(byte[] datas): 可以读取指定数组长度的内容,返回值是每次读取的长度,读取的内容存放在数组中,可以使用String类构造方法来封装为字符串 new String(byte[], int offset, int length);

int available(): 可读取的剩余字节数,即容量


/**
 *  字节输入流
 *  read() 每次读取一个字节
 *  read(byte[] datas) 读取一个byte数组 返回值是读取的长度
 * @author asus
 *
 */
public class TestFileInputStream3 {
    public static void main(String[] args) throws IOException {
        File file = new File("a.txt");
        file.createNewFile();
            
        FileInputStream fis = new FileInputStream(file);
        System.out.println(fis.available());
//      byte [] datas = new byte[100];
        byte [] datas = new byte[fis.available()];
        int dataCount = -1;
        while((dataCount = fis.read(datas)) != -1){
//          System.out.println(dataCount);
            System.out.println(new String(datas, 0, dataCount));
        }   
    }
}

3.2 FileOutputStream

父类 abstract OutputStream

void write():每次写入一个字节

void write(byte[] datas):写入一个byte数组,可以使用String类的getBytes()方法将字符串转换为byte数组

支持的参数为byte数组和int

flush() :将内容从缓存中刷新到文件中。close会自动调用。字节流中不是必须的,但字符流必须刷新

close():关闭资源

/**
 *  字节输出流 
 * @author asus
 *
 */
public class TestFileOutPutStream2 {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("c.txt", true);
            String str = "床前明月光,疑是地上霜,举头望明月,低头思故乡";
            byte [] datas = str.getBytes();
            fos.write(97);
            fos.write(datas);
            fos.flush(); // 将缓存中的内容刷新到文件
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

4.字符流

字符流若未关闭资源,必须手动调用flush,否则不会写出资源

4.1输入字符流(3种,含缓冲流Bufferedxxx)

父类:abstract Reader

1.子类FileReader:基于字符的文件输入流

int read():每次读取一个字符

int read(char[] datas):每次读取char数组长度的内容,返回值是读取的长度,读取的内容存放在数组中。(若要直接打印,可能出现字节增大,但也可以通过设置数组长度为available避免),最好的方式是new一个新的String来输出。

2.子类:BufferedReader:基于字符的输入缓冲流

在以上方法的基础上还有:

readLine() :每次读取一行

close():关闭资源

3.子类: inputStreamReader:可以指定编码格式的字符输入流 

字节流到字符流的桥梁,BufferedReader创建时需要Reader,InputStreamReader即是Reader的子类,可传它,且InputStreamReader创建时可传字节流) 多态

/**
 * 字符读取流  一次读取一个字符  也可以读取一个字符数组
 * 字符是16位   unicode编码
 * 字节   8位  byte ascii 
 * @author asus
 */
public class TestFileReader2 {
    public static void main(String[] args) {
        FileReader fReader = null;
        try {
            fReader = new FileReader("c.txt");
            char [] datas = new char[100];
            int dataCount = -1;
            while((dataCount = fReader.read(datas)) != -1){
                //System.out.println(dataCount);
                //System.out.println(datas);//若字符长度设为available即,剩余字节数,可正常打印,
                                            //否则可能打印多余的内容。即最后一次未读满,倒数第二次读的部分内容仍被输出
                System.out.println(new String(datas,0,dataCount));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fReader != null){
                try {
                    fReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
/**
 * 带有缓冲流的字符读取流
 * 可以读取一个字符  也可以一次读取一行
 * readLine()
 * @author asus
 *
 */
public class TestBufferedReader2 {
    public static void main(String[] args) {
        FileReader fr = null;
        BufferedReader bReader = null;
        try {
            fr = new FileReader("c.txt");
            bReader = new BufferedReader(fr);
            int data = -1;
            while((data = bReader.read()) != -1){
                System.out.println((char)data);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(bReader != null){
                try {
                    bReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fr != null){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

/**
 *  乱码出现的原因:
 *  编码的方式和解码的方式不一致 
 *  解决方式:
 *  1.统一编码
 *  2.可以将出现乱码的内容打散(iso-8859-1) 按照我们自己的编码方式组合
 *  常见的编码格式:
 *  GBK 国标扩展板   简体和繁体
 *  GB2312 国标版本 只支持简体
 *  ISO-8859-1 最原始的编码方式 通常用于解决乱码
 *  UTF-8 unicode万国码 包含世界大多数国家的语言编码
 *  ANSI 不具体指定某一种编码 因为在不同的操作系统上 表示对应的编码 比如 win10中文版 GBK 
 * @author asus
 */
public class TestInputStreamReader {
    public static void main(String[] args) {
        FileInputStream fis = null;
​
        try {
            fis = new FileInputStream("testCode.txt");
            InputStreamReader isr = new InputStreamReader(fis,"GBK");
            char []datas = new char[100];
            int dataCount = -1;
            while((dataCount  = isr.read(datas)) != -1) {
                System.out.println(new String(datas,0,dataCount));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            // 关闭资源
        }
    }
}

4.2输出字符流(3种,含缓冲流Bufferedxxx)

父类:abstract writer

1.子类:FileWriter

new实例时末尾添加true,表示在文本末尾追加内容

writer() : 每次写入一个字符

write(char [] datas):每次写入一个char数组

write(String str):每次写入一个字符串

2.子类:BufferedWriter

write():每次写入一个字符

write(char[] datas):每次写入一个char数组

write(String str) 每次写入一个字符串,也可设置起始位置

newLine():换行

3.子类:OutputStreamWriter 可指定编码的字符输出流

字节流到字符流的桥梁,BufferedWriter创建时需要Writer,OutputStreamWriter即是Writer的子类,可传它,且OutputStreamWriter创建时可传字节流)

write():每次写入一个字符

write(char [] datas):每次写入一个char数组

write(String str):每次写入一个字符串,也可设置起始位置

/**
 *  字符缓冲流写入流
 *  可以写入一个字符 或者字符串
 *  还可以换行
 *  newLine()
 * @author asus
 *
 */
public class TestBufferedWritet {
    public static void main(String[] args) {
        FileWriter fWriter = null;
        BufferedWriter bWriter = null;
        try {
            fWriter = new FileWriter("e.txt",true);
            bWriter = new BufferedWriter(fWriter);
            bWriter.write("hello word1");
            bWriter.newLine();
            bWriter.write("hello world2");
            bWriter.flush();//与字节流不同。。。不刷新或关闭资源不显示
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(bWriter !=null){
                try {
                    bWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fWriter != null){
                try {
                    fWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
/**
 * @author asus
 */
public class TestFileWriter {
    public static void main(String[] args) {
        FileWriter fWriter =null;
        try {
            fWriter  = new FileWriter("d.txt", true);
            fWriter.write("hello word2\n");
            
             // 将缓存中的内容刷新到文件
            fWriter.flush();//与字节流不同,若为关闭资源,必须刷新内容,否则不显示
        
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            /*if(fWriter != null){
                try {
                    fWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }*/
        }   
    }
}
public class TestOutputStreamWriter {
	public static void main(String[] args) {
		FileOutputStream fos;
		try {
			fos = new FileOutputStream("f.txt");
			OutputStreamWriter osw = new OutputStreamWriter(fos);
			osw.write("hello world");
			osw.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

5.数据流(二进制,依赖并属于字节流)

数据流属于字节流,用于读取二进制文件,比如图片、音频、视频等。。。。。

DataInputStream:基于字节的二进制文件输入流,读入只有byte存

DataOutputStream:基于字节的二进制文件输出流,输出有byte数组,或字符串,或字符多种形式

/**
 * DataInputStream  负责读取二进制文件
 * DataOutPutStream 负责写入二进制文件
 * @author asus
 */
public class TestDataStream {
	public static void main(String[] args) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		DataInputStream dis = null;
		DataOutputStream dos = null;
		
		try {
			fis = new FileInputStream("D:\\图片.png");
			dis = new DataInputStream(fis);
			fos = new FileOutputStream("copy2.png");
			dos = new DataOutputStream(fos);
			byte [] datas = new byte[fis.available()];
			int dataCount = -1;
			while((dataCount = dis.read(datas)) != -1){
				//dos.write(datas, 0, dataCount);
				dos.write(datas);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
            //关闭资源
        }
}

6.对象流(依赖并属于字节流)

对象流属于字节流,用于输入对象和输出对象

ObjectOutputStream-序列化:将对象以二进制的形式存储在文件中 readObject()

ObjectInputStream-反序列化:将保存有对象的二进制文件读取出来转换为对象 writeObject

序列化要求:被序列化的对象必须实现Serializable接口,此接口是空接口,相当于一个标识,实现此接口的类才可以序列化

/**
 * ObjectInputStream  对象输入流
 * ObjectOutputStream 对象输出流
 * 序列化:将对象写入到文件中
 * 反序列化:将存有对象的文件读取出来生成对象
 * @author asus
 *
 */
public class TestObjectStream {
	public static void main(String[] args) {
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		FileInputStream fis = null;
		ObjectInputStream ois = null;

		try {
			fos = new FileOutputStream("stu.txt");
			oos = new ObjectOutputStream(fos);
			Student stu1 = new Student("赵四", 20);
			Student stu2 = new Student("广坤", 21);
			Student stu3 = new Student("大拿", 22);
			oos.writeObject(stu1);
			oos.writeObject(stu2);
			oos.writeObject(stu3);

			fis = new FileInputStream("stu.txt");
			ois = new ObjectInputStream(fis);
			while(fis.available() > 0){
				Object obj = ois.readObject();
				if(obj instanceof Student){
					Student stuRead = (Student) obj;
					System.out.println(stuRead);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
            //关闭资源
	}
}
/**
 * Serializeable 空接口 相当于一个标识 标识此接口的类才能被序列化化
 * @author asus
 */
public class Student implements Serializable{
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}

每日问题

1.判断是否是文件

2.判断是否是目录

3.判断是否存在

4.删除文件的方法

5.文件的相对路径

6.文件的绝对路径

7.FileInputStream是什么流?

8.字节写入流是哪个对象?

9.字节流写入的方法是什么,支持参数是什么?

10.FileInputStream如何使每次读取两个字节

11.读取图片应该使用什么对象?

12.BufferedReader独有的读取文件的方法是什么

13.什么是序列化,什么是反序列化,序列化的对象有什么要求

14.实现序列化的步骤是什么

15.写入对象使用哪个对象的哪个方法

16.读取一个对象是什么方法

解答:

1.判断是否是文件 isFile();

2.判断是否是目录 isDirectory();

3.判断是否存在 exists()

4.删除文件的方法 delete();

5.文件的相对路径 getPath();

6.文件的绝对路径 getAbsolutePath();

7.FileInputStream是什么流? 字节读取流

8.字节写入流是哪个对象? FileOutputStream

9.字节流写入的方法是什么,支持参数是什么?

      write(); byte数组      int num 显示对应的ascii

10.FileInputStream如何使每次读取两个字节

      byte [] datas = new byte[2]; read(byte[] datas); 返回值是每次读取的长度,内容存放在datas数组中

11.读取图片应该使用什么对象? DataInputStream

12.BufferedReader独有的读取文件的方法是什么 readLine();

13.什么是序列化,什么是反序列化,序列化的对象有什么要求

     将对象以二进制的形式存储在 文件中 将存储有对象的二进制文件读取出来转化为对象 实现Serializable

14.实现序列化的步骤是什么

     先实现Serializable接口,然后使用ObjectOutputStream写入对象,再使用 ObjectInputStream读取对象 15.写入对象使用哪个对象的哪个方法 使用ObjectOutputStream写入对象,writeObject()

16.读取一个对象是什么方法 readObject();