java中的IO流详解

IO流体系图-常用类

一、IO流体系图

二、IO流的具体使用

1.FileInputStream(字节输入流 文件->程序)

1.1fileInputStream.read()

返回的是int类型,要强制转化成char类型

从输入流中读取数据的下一个字节。返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。

子类必须提供此方法的一个实现。 返回:下一个数据字节;如果到达流的末尾,则返回 -1。

1.2fileInputStream.read(byte[]b)

 import com.sun.org.apache.xpath.internal.operations.String;
 import org.junit.jupiter.api.Test;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FilterInputStream;
 import java.io.IOException;
 ​
 //FileInputStream的使用(字节输入流 文件->程序)
 public class FileInputStream_ {
     public static void main(String[] args) {
         
     }
     /*
             演示读取文件
      */
     @Test
     public void readFile01(){
         java.lang.String filePath = "d:\\java\\hello.txt";
         int readData=0;
         FileInputStream fileInputStream=null;
         try {
             //创建FileInputStream对象,用于读取文件
             fileInputStream = new FileInputStream(filePath);
             //从该输入流读取一个字节的数据,如果没有输入可用,该方法将阻止
             //如果返回-1,表示读取完毕
             while((readData = fileInputStream.read())!=-1){
                 System.out.print((char)readData);
             }
 ​
         } catch (IOException e) {
            e.printStackTrace();
         }finally {
             //关闭文件流,释放资源
             try {
                 fileInputStream.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
 ​
     }
     /*
     使用read(byte[] b)读取文件,提高效率
      */
     @Test
     public void readFile02(){
         java.lang.String filePath="d:\\java\\hello.txt";
         int readData=0;
         //字节数组
         byte[] buf=new byte[8];//一次读取8个字节
         int readLen=0;
         FileInputStream fileInputStream=null;
         try {
             //创建FileInputStream对象,用于读取文件
             fileInputStream = new FileInputStream(filePath);
             //从该输入流读取一个字节的数据,如果没有输入可用,该方法将阻止
             //如果返回-1,表示读取完毕
             //如果读取正常,返回实际读取的字节数
             while((readLen= fileInputStream.read(buf))!=-1) {
                 //将字符数组生成字符串
                 System.out.print(new java.lang.String(buf, 0, readLen));
             }
         } catch (IOException e) {
             e.printStackTrace();
         }finally {
             //关闭文件流,释放资源
             try {
                 fileInputStream.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }
 }
 ​
 

2.FileOutputStream

创建: 1.fileOutputStream = new FileOutputStream(filePath,true);,直接在文件末尾追加,保留原内容

2.fileOutputStream = new FileOutputStream(filePath),覆盖原内容,重新写入;

2.1fileOutputStream.write()写入一个字节

2.2fileOutputStream.write(byte[b])写入一个字符数组

str.getBytes[],将一个字符串转换成字符数组

 import org.junit.jupiter.api.Test;
 ​
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 ​
 public class FileOutputStream_ {
     public static void main(String[] args) {
 ​
     }
     @Test
     public void writeFile(){
         //创建FileOutputStream
         FileOutputStream fileOutputStream=null;
         String filePath="d:\\java\\a.txt";
         try {
             //得到FileOutputStream对象
             //new FileOutputStream(filePath),创建方式,当写入内容时,会覆盖原来的内容
             //new FileOutputStream(filePath,true)创建方式,写入内容时,追加到文件后面
             fileOutputStream = new FileOutputStream(filePath,true);
             //写入一个字节
             //fileOutputStream.write('H');
             //写入一个数组
             String str="hello,world!";
             //str.getBytes()可以吧字符串->字符数组
             fileOutputStream.write(str.getBytes());
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
         }
 ​
 ​
     }
 }
 ​
 

3.FileReader和FileWriter介绍

3.1FileReader方法

(1).new FileReader(File/String)

(2).read:每次读取单个字符,返回该字符,到文件末尾返回-1

(3).read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1

字符数组转化为字符串  ​

 import org.junit.jupiter.api.Test;
 ​
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 ​
 public class FileReader_ {
     public static void main(String[] args) {
 ​
     }
     @Test
     public void readFile01(){
         String filePath="d:\\java\\story.txt";
         FileReader fileReader=null;
         int data=0;
         try {
             fileReader = new FileReader(filePath);
             //循环读取,使用read,单个字符读取
             while((data=fileReader.read())!=-1){
                 System.out.print((char)data);
             }
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
             if(fileReader!=null){
                 try {
                     fileReader.close();
                 } catch (IOException e) {
                     throw new RuntimeException(e);
                 }
             }
         }
     }
     @Test
     public void readFile02(){
         String filePath="d:\\java\\story.txt";
         FileReader fileReader=null;
         int readLen=0;
         char[] buf=new char[8];
         try {
             fileReader = new FileReader(filePath);
             //循环读取,使用read(buf),返回实际读取到的字符个数
             while((readLen=fileReader.read(buf))!=-1){
                 //不能保证每次取出的都是8个字符,所有要截取读取的长度
                 System.out.print(new String(buf,0,readLen));
             }
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
             if(fileReader!=null){
                 try {
                     fileReader.close();
                 } catch (IOException e) {
                     throw new RuntimeException(e);
                 }
             }
         }
 ​
 ​
     }
 }
 ​

3.2FileWriter方法

new String(char[]),将char[]转换成String

new String(char[],off,len),将字符串的指定部分转换成字符串

new FileWriter(File/String):覆盖模式,相当于流的指针在首端2)new FileWriter(File/String,true):追加模式,相当于流的指针在尾端 write(int):写入单个字符 write(char[]):写入指定数组 5)write(char[],off,len):写入指定数组的指定部分 6)write(string):写入整个字符串7)write(string,off,len):写入字符串的指定部分相关APl:String类:toCharArray:将String转换成char[]

 import java.io.FileWriter;
 import java.io.IOException;
 ​
 public class FileWriter_ {
     public static void main(String[] args) {
         String filePath="d:\\java\\note.txt";
         //创建FileWriter对象
         FileWriter fileWriter=null;
         char[]chars={'a','b','c'};
         try {
             fileWriter=new FileWriter(filePath);
             //写入单个字符
             fileWriter.write('H');
             //写入指定数组
             fileWriter.write(chars);
             //写入指定数组的指定部分
             fileWriter.write(" hello,world!".toCharArray(),0,6);
             //写入整个字符串
             fileWriter.write(" hihao");
             //字符串指定部分
             fileWriter.write(" 河北保定",0,3);
             //数据量时,使用循环操作
 ​
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
             //最终一定要关闭流,或者flush才能真正把数据写进去
             try {
                 fileWriter.close();
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
         }
         System.out.println("程序结束");
     }
 }
 ​

对于FileWriter,最后一定要关闭流,或者flush刷新才能将真正的数据写入到文件中

4.节点流和处理流

(1).节点流是底层流/低级流,直接和数据源相接

(2).处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的处理方法完成输入输出。

(3).处理流对节点流进行包装,使用修饰器模式,不会和数据直接相连。

4.2处理流-BufferedReader 和 BufferedWriter

bufferedReader.readLine()//;按行读取,返回读取到的字符串

 import java.io.BufferedReader;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 ​
 //演示bufferedReader的使用
 public class BufferedReader_ {
     public static void main(String[] args) throws IOException {
         String filePath="d:\\java\\story.txt";
         //创建对象
         BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
         //读取
         String line;//按行读取
         //bufferedReader.readLine();按行读取,返回读取到的字符串
         while((line=bufferedReader.readLine())!=null){
             System.out.println(line);
         }
         //关闭流,只需要关闭BufferedReader
         //底层会自动去关闭节点流
         bufferedReader.close();
 ​
     }
 }
 

1.创建BufferedWriter new FileWriter(filePath,true)表示以追加的方式写入 new FileWriter(filePath)表示以覆盖的方式写入

2.插入和系统相关的换行符

bufferedWriter.newLine();

 import java.io.BufferedWriter;
 import java.io.FileWriter;
 import java.io.IOException;
 ​
 public class BufferedWriter_ {
     public static void main(String[] args) throws IOException {
         String filePath="d:\\java\\ok.txt";
         //创建BufferedWriter
         //new FileWriter(filePath,true)表示以追加的方式写入
         //new FileWriter(filePath)表示以覆盖的方式写入
         BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
         bufferedWriter.write("hello1,world!");
         //插入一个和系统相关的换行符
         bufferedWriter.newLine();
         bufferedWriter.write("hello2,world!");
         bufferedWriter.newLine();
         bufferedWriter.write("hello3,world!");
         bufferedWriter.newLine();
         bufferedWriter.write("hello4,world!");
         bufferedWriter.newLine();
         //关闭外层流,底层会自动关闭节点流(FileWriter)
         bufferedWriter.close();
     }
 }

4.3处理流-BufferedInputStream 和 BufferedOutputStream

 import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
 //字节流可以操作二进制文件,也可以操作文本文件
 import java.io.*;
 ​
 public class BufferedCopy02 {
     public static void main(String[] args) {
         String strFilePath="d:\\java\\io.PNG";
         String destFilePath="d:\\java\\io1.jpg";
         //创建BufferedInputStream和BufferedOutputStream
          BufferedInputStream bis=null;
         BufferedOutputStream bos=null;
         try {
             bis=new BufferedInputStream(new FileInputStream(strFilePath));
             bos=new BufferedOutputStream(new FileOutputStream(destFilePath));
             int readLen=0;
             //循环读取文件,并写入到destFilePath
             byte[] buff=new byte[2024];
             //返回-1表示文件读取完毕
 ​
             while((readLen=bis.read(buff))!=-1){
                 bos.write(buff,0,readLen);
             }
             System.out.println("文件拷贝成功");
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
             //关闭流
             try {
                 if(bis!=null){
                     bis.close();
                 }
                 if(bos!=null){
                     bos.close();
                 }
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
         }
 ​
     }
 }
 ​

5.对象流-ObjectInputStream 和 ObjectOutputStream

将数据和数据类型一起保存在文件中,并且要能从文件中恢复

序列化:在保存数据时,保存数据的值和数据类型

反序列化:恢复数据时,恢复数据的值和数据类型

要想让某个对象支持序列化机制,则必须让其类是可序列化的,让某个类是可序列化的,该类要实现Serializable借口或者Externalizable接口

Serializable接口是一个标记接口,没有方法,Externalizable有方法需要实现

ObjectoutputStream方法

  1. oos.writeInt(100);//int->Integer(实现了Serializable)

  2. oos.writeBoolean(true);//boolean->Boolean(实现了Serializable)

  3. oos.writeChar('a');

  4. oos.writeDouble(9.5);//double->Double

  5. oos.writeUTF("韩顺平教育");

  6. oos.writeObject(new Dog("旺财",10,"日本","黄色"));


 ​
 import java.io.*;
 ​
 public class ObjectOutputStream_ {
     public static void main(String[] args) throws IOException {
         //序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
         String filePath="d:\\java\\data.dat";
         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
         //序列化数据到d:\java\data.dat
         oos.writeInt(100);//int->Integer(实现了Serializable)
         oos.writeBoolean(true);//boolean->Boolean(实现了Serializable)
         oos.writeChar('a');
         oos.writeDouble(9.5);//double->Double
         oos.writeUTF("韩顺平教育");
         oos.writeObject(new Dog("旺财",10,"日本","黄色"));
         oos.close();
         System.out.println("数据保存完毕(序列化形式)");
     }
 }

ObjectInputStream方法

反序列化的顺序需要和保存数据(序列化)顺序一致,否则回出现异常

 
 import com.hspedu.outputstream_.Dog;
 ​
 import java.io.*;
 import java.sql.SQLOutput;
 ​
 public class ObjectInputStream_ {
     public static void main(String[] args) throws IOException, ClassNotFoundException {
         //指定反序列化的顺序
         String filePath="d:\\java\\data.dat";
         ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
 ​
         //1.反序列化的顺序需要和保存数据(序列化)顺序一致,否则回出现异常
         System.out.println(ois.readInt());
         System.out.println(ois.readBoolean());
         System.out.println(ois.readChar());
 ​
         System.out.println(ois.readDouble());
         System.out.println(ois.readUTF());
         Object dog=ois.readObject();
         System.out.println("运行类型="+dog.getClass());
         System.out.println("dog信息="+dog);
         //调用Dog的方法,需要向下转型
         //将Dog类的定义,拷贝到可以引用的位置
         Dog dog2=(Dog)dog;
         System.out.println(dog2.getName());
 ​
 ​
 ​
         //关闭外层流,底层会自动关闭字节流
         ois.close();
     }
 }
 ​

注意事项

1.读写顺序要一致

2.要求序列化或反序列化对象,需要 实现 Serializable

3.序列化的类中建议添加SerialVersionUlD,为了提高版本的兼容性

4.序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员

5.序列化对象时,要求里面属性的类型也需要实现序列化接口

6.序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了席列化

6.标准输入输出流

标准输入输出类型默认设备
System.inInputStream键盘
System.outPrintStream显示器

7.转换流InputStreamReader和OutputStreamWriter

1.InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流)

2.OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)

3.当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流

4.可以在使用时指定编码格式(比如 utf-8,gbk1 等)

编程将字节流FileInputStream包装成字符流InputStreamReader,对文件进行读取(按照utf-8/gbk格式),进而再包装成BufferedReader

 import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
 ​
 import java.io.*;
 ​
 //InputStreamReader转换流解决中文乱码问题
 //将字节流FileInputStream转换成字符流,
 // 指定编码gbk/utf-8
 public class InputStreamReader_ {
     public static void main(String[] args) throws IOException {
         String filePath="d:\\java\\a.txt";
         //1.FileInputStream转换成InputStreamReader
         //2.指定gbk
         InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath),"gbk");
         //3.把InputStreamReader传入BufferedReader
         BufferedReader br = new BufferedReader(isr);
         //简化版
         //BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gbk"));
         String s=br.readLine();
         System.out.println("读取内容="+s);
         //关闭外层流
         br.close();
     }
 }
 

编程将 字节流 FileOutputStream 包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式,可以指定其他,比如utf-8)

 import java.io.*;
 ​
 //FileOutputStream字节流转化为字符流OutputStreamWriter
 //指定编码gbk/utf-8//utf8
 public class OutputStreamWriter_ {
     public static void main(String[] args) throws IOException {
         String filePath="d:\\java\\hsp.txt";
         String charSet="utf-8";
         OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet);
         osw.write("hi,韩顺平教育");
         osw.close();
         System.out.println("按照"+charSet+"保存文件成功");
     }
 }

8.打印流PrintStream和PrintWriter

打印流只有输出流,没有输入流

创建对象

PrintStream out=System.out;  

import java.io.IOException;
 import java.io.PrintStream;
 ​
 public class PrintStream_ {
     public static void main(String[] args) throws IOException {
         PrintStream out=System.out;
         //默认情况下,PrintStream输出数据的位置是标准输出
         //即显示屏
         out.print("john,hello");
         //字节流
         //string.getBytes()将字符串转换成字节数组
         out.write("john,hello".getBytes());
         System.setOut(new PrintStream("d:\\java\\f1.txt"));
         System.out.println("hello,world!");
         out.close();
 ​
     }
 }
 ​

print的底层就是write,可以直接调用write

 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
 ​
 public class PrintWriter_ {
     public static void main(String[] args) throws FileNotFoundException {
 //        PrintWriter printWriter = new PrintWriter(System.out);
 //        printWriter.print("hi,北京你好~~~");
 //        printWriter.close();
         PrintWriter printWriter = new PrintWriter(new FileOutputStream("d:\\java\\f2.txt"));
         printWriter.write("hi,北京你好~~~~");
         printWriter.close();
     }
 }

9.Properties类

专门用于读写配置文件的集合类

配置文件的格式:键=值

常用方法

1.load:加载配置文件的键值对到Properties对象

2.Iist:将数据显示到指定设备

3.getProperty(key):根据键获取值

4.setProperty(key,value):设置键值对到Properties对象

5.store:将Properties中的键值对存储到配置文件,在idea 中,保存信息到配置文件,如果含有中文,会存储为unicode码

例一

import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 import java.util.Properties;
 ​
 public class Properties02 {
     public static void main(String[] args) throws IOException {
         //使用Properties类来读取mysql.properties文件
         //1.创建Properties对象
         Properties properties = new Properties();
         //2.加载指定配置文件
         properties.load(new FileReader("src\\mysql.properties"));
         //3.把k-v键值对显示在控制台上
         properties.list(System.out);
         //根据key获取对应的值
         String user = properties.getProperty("user");
         String pwd = properties.getProperty("pwd");
         System.out.println("用户名="+user);
         System.out.println("密码是="+pwd);
     }
 }

mysql.properties文件

 ip=192.100.100
 user=root
 pwd=12345
 ​

例二

import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.Properties;
 ​
 public class properties03 {
     public static void main(String[] args) throws IOException {
         Properties properties = new Properties();
         //创建
         //如果该文件有key,就是修改
         //properties父类是Hashtable,底层是Hashtable,核心方法是
         //2.如果该文件有key ,就是修改
         /*
             Properties 父类是 Hashtable , 底层就是Hashtable 核心方法
             public synchronized V put(K key, V value) {
                 // Make sure the value is not null
                 if (value == null) {
                     throw new NullPointerException();
                 }
 ​
                 // Makes sure the key is not already in the hashtable.
                 Entry<?,?> tab[] = table;
                 int hash = key.hashCode();
                 int index = (hash & 0x7FFFFFFF) % tab.length;
                 @SuppressWarnings("unchecked")
                 Entry<K,V> entry = (Entry<K,V>)tab[index];
                 for(; entry != null ; entry = entry.next) {
                     if ((entry.hash == hash) && entry.key.equals(key)) {
                         V old = entry.value;
                         entry.value = value;//如果key 存在,就替换
                         return old;
                     }
                 }
 ​
                 addEntry(hash, key, value, index);//如果是新k, 就addEntry
                 return null;
             }
 ​
          */
         properties.setProperty("charset","utf-8");
         properties.setProperty("user","汤姆");//保存时,是中文的utf-8
         properties.setProperty("pwd","abc111");
         //将k-v存储在文件中
         properties.store(new FileOutputStream("src\\mysql2.properties"),null);//注解
         System.out.println("保存配置文件成功~");
     }
 }
 ​
  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值