java day08

IO流

文件

文件就是保存数据的地方

文件流 : 文件在程序中是以流的形式来操作的

File文件操作
/******************创建文件************************************/
//方式1 根据路径创建对象
public void create01{
  String filePath = "e:\\news.txt";
  File file = new File(filePath);
  try{
    file.createNewFile();
  }catch(IOException e){
    e.printStackTrace();
  }
}
//方式2 根据父目录文件 + 子路径构建 new File(File file,String fileName);
public void create02{
  File parentFile = new File("e:\\");
  String fileName = "news.txt";
  File file = new File(parentFile,fileName); // 此时还处于内存,在内存中创建对象
  try{
    file.createNewFile(); // 创建文件
  }catch(IOException e){
    e.printStackTrace();
  }
}
//方式3 根据父目录 + 子路径构建 new File(String file,String fileName);
public void create03{
  File parentPath = new File("e:\\");
  String fileName = "news.txt";
  File file = new File(parentPath,fileName);
  try{
    file.createNewFile(); // 创建文件
  }catch(IOException e){
    e.printStackTrace();
  }
}

/******************获取文件的相关信息***********************************/
// getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory
//获取文件信息
public void info{
  File file = new File("e:\\test.txt");
  System.out.println(file.getName());//文件名称
  System.out.println(file.getAbsolutePath());//绝对路径
  System.out.println(file.getParent());//文件父级目录
  System.out.println(file.length());//文件大小(字节计算)
  System.out.println(file.exists());//文件是否存在
  System.out.println(file.isFile());//是不是文件
  System.out.println(file.isDirectory());//是不是目录                 
}

/******************目录操作和文件删除***********************************/
// mkdir创建一级目录、mkdirs创建多级目录、delete删除空目录或文件

public void mk1{
  //判断 e:\\new.txt 是否存在,存在就删除
  String filePath = "e:\\new.txt";
  File file = new File(filePath);
  if(file.exists()){
    file.delete();
  }
  //判断 目录是否存在,存在就删除,目录是被当做文件
  String filePath1 = "e:\\word";
  File file1 = new File(filePath1);
  if(file1.exists()){
    file1.delete();
  }
   //判断 多级目录是否存在,不存在就创建 mkdirs
  String dirPath = "d:\\demo\\a\\b\\c";
   File dir = new File(dirPath);
   if(!dir.exists()){
     if(dir.mkdirs()){
       System.out.println("创建成功!")
     }
   }
}
IO流原理及流的分类

I/O用于处理数据传输,读写文件,网络通讯等

java程序中,对数据的输入/输出操作以“流(stream)”的方式进行

java.io包提供各种“流”类和接口,用以获取不同的数据,并通过方法输入或输出数据

分类:

  1. ​ 操作数据单位:字节流(二进制文件)、字符流(文本文件)

  2. ​ 数据流向 : 输入流、输出流

  3. ​ 流的角色: 节点流,处理流/包装流

InputStream字节输入流

InputStream抽象类是所有类字节输入流的超类

  • InputStream常用字类:

    FileInputStream:文件输入流

    BufferedInputStream : 缓冲字节输入流

    ObjectInputStream : 对象字节输入流

  • IO常用类

FileInputStream与FileOutputStream
/*****************FileInputStream************************/
/*
*读取文件,单个字节读取,效率低
*/
public void readFile01(){
  String filePath = "e:\\new.txt";
  int read = 0;
  FileInputStream fileInputStream = null;
  try{
    //创建 FileInputStream
    fileInputStream = new FileInputStream(filePath);
    //从该输入流读取一个字节的数据,如果没有输入可用,此方法将阻止
    //如果返回 -1,表示读取完毕
    //read = fileInputStream.read();
    while((read = fileInputStream.read()) != -1){
      System.out.print((char)read); //转char显示(无汉字)
    }
  }catch(IOException e){
    e.printStackTrace();
  }finally{
    //关闭文件流,释放资源
    try{
      fileInputStream.close();
    }catch(IOException e){
    	e.printStackTrace();
  	}
  }
}

/**
*使用read(byte[] b)读取,提高效率
*/
public void readFile02(){
  String filePath = "e:\\new.txt";
  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 String(buf,0,readLen)); //显示
    }
  }catch(IOException e){
    e.printStackTrace();
  }finally{
    //关闭文件流,释放资源
    try{
      fileInputStream.close();
    }catch(IOException e){
    	e.printStackTrace();
  	}
  }
}


/*****************FileOutputStream************************/
public void writeFile(){
    String filePath = "e:\\a.txt";
    FileOutputStream fileOutputStream = null;
    try{
        //new FileOutputStream(filePath)创建,写入内容会覆盖原来内容
        //new FileOutputStream(filePath,true)创建,写入内容是追加
        fileOutputStream = new FileOutputStream(filePath);
        fileOutputStream.write("H");// 写入字节
        String str = "hello, world";
        fileOutputStream.write(str.getBytes());//getBytes字符串转字节数组
        fileOutputStream.write((str.getBytes(),0,str.length());//指定字节偏移
    }catch(IOException e){
    	e.printStackTrace();
  	}finally{
    	//关闭文件流,释放资源
        try{
          fileOutputStream.close();
        }catch(IOException e){
            e.printStackTrace();
        }
    }
  }
}
                               
/*****************综合实例copy图片************************/                     
public void FileCopy{
    //例:文件拷贝 将e:\\Koa.jpg 拷贝c:\\  注意管理员权限
    // 1、创建文件的输入流,将文件读入到程序
    // 2、创建文件的输出流,将读取到的文件数据,写入到指定的文件
    String srcFilePath = "e:\\Koa.jpg";
    String destFilePath = "c:\\Koa.jpg";
    FileInputStream fileInputStream = null;
    FileOutputStream fileOutputStream = null;
    try{
      fileInputStream = new FileInputStream(srcFilePath);
      fileOutputStream = new FileOutputStream(destFilePath);
      byte[] buf = new byte[1024];//定义一个字节数组,提高读取效果
      int readLen = 0;
      while((readLen = fileInputStream.read(buf)) !=-1){
        //读取后,就写入到文件,通过fileOutputStream,边读边写
        fileOutputStream.write(buf,0,readLen);//一定要用这个方法
      }
    }catch(IOException e){
   	  e.printStackTrace();
  	}finally{
      try{
          if(fileInputStream!=null){
            fileInputStream.close(); 
          }
          if(fileInputStream!=null){
            fileInputStream.close(); 
          }
      }catch(IOException e){
   	  	e.printStackTrace();
  	  }
    }
}
FileReader与FileWriter

两者都是字符流,即按照字符来操作io

  • FileReader相关方法:
  1. ​ new FileReader(File/String)
  2. ​ read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
  3. ​ read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
  • FileWriter相关方法:
  1. ​ new FileWriter(File/String):覆盖模式,相当于流的指针在首端
  2. ​ new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
  3. ​ write(int):写入单个字符
  4. ​ write(char[]):写入指定数组
  5. ​ write(char[],off,len):写入指定数组的指定部分
  6. ​ write(string):写入整个字符串
  7. ​ write(string,off,len):写入字符串的指定部分

注意: FileWriter必须关闭或刷新,否则写入不到指定文件

/******************FileWriter*****************/
String filePath = "e:\\note.txt";
char[] chars = {'a','b'};
FileWriter fileWriter = null;
try{
  fileWriter = new FileWriter(filePath);//覆盖模式
  fileWriter.write("G"); //单个字符
  fileWriter.write(chats);//字符数组
  //...
}catch(IOException e){
  e.printStackTrace();
}finally{
  try{
    //关闭文件流,等价flush + 关闭
    fileWriter.close();
  }catch(IOException e){
    e.printStackTrace();
  }
}
节点流和处理流
  1. 节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter

2.处理流(包装流)是“连接”在已存在的流之上,为程序提供更为强大的读写功能,更加灵活,如BufferedReader、BufferedWriter

节点流与处理流区别:

  1. 节点流是底层流/低级流,直接跟数据源相接
  2. 处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
  3. 处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连

处理流的功能主要体现在两方面:

  1. 性能的提高:主要增加缓冲的方式来提高输入输出的效率
  2. 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活
// 创建Reader_抽象类
public abstract class Reader_ {
  public abstract void readFile(){}
  public void readString(){}
}
// 创建FileReader_
public class FileReader_ extends Reader_ {
  public void readFile(){
     System.out.println("对文件进行读取。。");
  }
}
// 创建StringReader_ 当节点流
public class StringReader_ extends Reader_ {
  public void readString(){
     System.out.println("对字符进行读取。。");
  }
}
// 创建BufferedReader_ 当处理流
public class BufferedReader_ extends Reader_ {
  private Reader_ reader_; //属性是 Reader_ 类型
  public BufferedReader_(Reader_ reader_){
    this.reader_ = reader_;
  }
  //封装一层
  public void readFile(){
    reader_.readFile();
  }
  //让方法更灵活,批处理
  public void readFiles(int num){
    for(int i = 0; i<num; i++){
      reader_.readFile();
    }
  }
  //扩展readString,批处理
  public void readString(int num){
    for(int i = 0; i<num; i++){
      reader_.readString();
    }
  }
}

// 运行
public static void main(String[] args){
  //
  BufferedReader_ bufferedReader_= new BufferedReader_(new FileReader_);
  bufferedReader_.readFile(10);
  bufferedReader_.readFile();
  //
  BufferedReader_ bufferedReader_1 = new BufferedReader_(new StringReader_);
  bufferedReader_1.readString(10);
}
BufferedReader与BufferedWriter
/*******************BufferedReader****************************/
// 文本文件
String filePath = "e:\\a.txt";
BufferedReader bufferedReader= new BufferedReader(new FileReader(filePath)); //要抛异常
//读取
String line;
//按行读取文件,当返回为空标识读取完毕
while((line=bufferedReader.readLine())!=null){
  System.out.print(line);
}
//关闭流,这里只需要关闭BufferedReader,底层会自动关闭节点流
bufferedReader.close();


/*********************BufferedWriter**********************/
String filePath = "e:\\ok.txt";
//new FileWriter(filePath) 覆盖
//new FileWriter(filePath,true) 追加
BufferedWriter bufferedWriter= new BufferedWriter(new FileWriter(filePath)); //要抛异常
bufferedWriter.write("hello,111");
bufferedWriter.newLine();//插入换行
bufferedWriter.write("hello,222");
bufferedWriter.close();

/*******************Copy文件****************************/
String srcFilePath = "e:\\a.java"; //原文件
String destFilePath = "d:\\a.java";//目的地
// BufferedReader、BufferedWriter不要操作二进制文件,可能造成文件损坏
BufferedReader br = null;
BufferedWriter bw = null;
String line;
try{
    br = new BufferedReader(new FileReader(srcFilePath)); 
    bw = new BufferedWriter(new FileWriter(destFilePath)); 
    //读取 readLine 读取一行没有换行
    while((line = br.readLine()) != null){
        // 每读取一行,就写入
        bw.write(line);
        //插入一个换行
        bw.newLine();
    }
}catch(IOException e){
    e.printStackTrace();
}finally{
    //关闭流
    try{
        if(br != null){
            br.close()
        }
        if(bw != null){
            bw.close()
        }
    }catch(IOException e){
        e.printStackTrace();
	}
}
BufferedInputStream 与 BufferedOutputStream

BufferedInputStream 是字节流,在创建BufferedInputStream 时会创建一个内部缓冲区数组

BufferedOutputStream 是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统

//Copy 图片 可以完成二进制COPY
String srcFilePath = "e:\\a.jpg"; //原文件
String destFilePath = "d:\\a.jpg";//目的地
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try{
    bis = new BufferedInputStream(new FileInputStream(srcFilePath)); 
    bos = new BufferedOutputStream(new FileOutputStream(destFilePath)); 
    byte[] buff = new byte[1024];
    int readLen = 0;
    while((readLen = bis.read(buff)) != -1){
        // 每读取一行,就写入
        bos.write(buff,0,readLen);
    }
}catch(IOException e){
    e.printStackTrace();
}finally{
    //关闭流
    try{
        if(bis != null){
            bis.close()
        }
        if(bos != null){
            bos.close()
        }
    }catch(IOException e){
        e.printStackTrace();
	}
}
ObjectInputStream 与 ObjectOutputStream

对象处理流,将基本数据类型或者对象进行序列化(ObjectOutputStream)和反序列化操作(ObjectInputStream)

序列化和反序列化:

  1. 序列化就是在保存数据时,保存数据的值和数据类型

  2. 反序列化就是恢复数据时,恢复数据的值和数据类型

  3. 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类可序列化的,改该类必须实现以下两个接口之一:

    • ​ Serializable // 标记接口

    • ​ Externalizable

// ObjectOutputStream 序列化
String filePath = "e:\\Date.txt"; //序列化后保存文件格式不是纯文本
try{
  ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
  //序列化数据到 e:\\Date.txt
  oos.writeInt(100);// int > Integer(实现了Serializable)
  oos.writeBoolean(true);
  oos.writeChar("a");
  oos.writeDouble(9.7);
  oos.writeUTF("assd");// string
  oos.writeObject(new Dog("旺财"10));// Dog必须实现 Serializable,否则异常
}catch(IOException e){
    e.printStackTrace();
}finally{
   try{
  	oos.clode();
   }catch(IOException e){
    e.printStackTrace();
	}
}
public class Dog implements Serializable {
  ....
}
//ObjectInputStream 反序列化
String filePath = "e:\\Date.txt";
try{
	ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
  // 读取(反序列)的顺序需要和保存数据的顺序一致
  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.getClass = ois.readObject();
  System.out.println(dog.getClass());
  System.out.println(dog); // dog 要定义toString
}catch(IOException e){
    e.printStackTrace();
}finally{
   try{
  	ois.clode();
   }catch(IOException e){
    e.printStackTrace();
	 }
}

对象注意事项:

  1. 读写顺序要一致
  2. 要求实现序列化或反序列化对象,需要实现Serializable
  3. 序列化的类中建议添加SerialVersionUID,提高版本兼容性
  4. 序列化对象时,默认将里面所有的属性进行序列化,除了static 或transient修饰的成员
  5. 序列化对象时,要求里面属性的类型也需要实现序列化接口
  6. 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也默认实现序列化
System.in 与 System.out

标准输入输出流

System.in 标准输入,InputStream 编译类型,BufferedInputStream 运行类型,默认设备键盘

System.out 标准输出,PrintStream 编译类型,PrintStream运行类型,默认设备显示器

//System.in
//System 类的 public final static InputStream in = null;
System.out.println(System.in.getClass());
Scanner scanner = new Scanner(System.in);
String next = scanner.next();
System.out.println(next);
//System.out
//System 类的 public final static PrintStream in = null;
System.out.println(System.out.getClass());
System.out.println();// 标准的out,显示
InputStreamReader 与 OutputStreamWriter

转换流,解决文件乱码

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

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

当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文乱码问题

可以在使用时指定编码格式

//InputStreamReader
String filePath = "e:\\Date.txt";
try{
  InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath),"gbk");//指定编码gbk
 	BufferedReader br = new BufferedReader(isr);
  //	BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gbk"));
  br.readLine();
}catch(IOException e){
    e.printStackTrace();
}finally{
   try{
  	br.clode();
   }catch(IOException e){
    e.printStackTrace();
	}
}

//OutputStreamWriter
String filePath = "e:\\Date.txt";
String charset = "gbk";
try{
  OutputStreamWriter osw = new OutputStreamWriter(new File OutputStream(filePath),charset);//指定编码gbk
  osw.write("djjj汉");
}catch(IOException e){
    e.printStackTrace();
}finally{
   try{
  	osw.close();
   }catch(IOException e){
    e.printStackTrace();
	}
}
PrintStream 与 PrintWrite

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

// PrintStream 字节打印流
PrintStream out = System.out;//默认情况下,PrintStream输出数据的位置是标准输出,即显示器
out.print("dd");
//print的底层使用的write,所以可直接调用write进行打印/输出
out.write("kkkk")
out.close();

//修改打印流的位置/设备
System.setOut(new PrintStream("e\\f.txt"));
System.out.print("水水水水");

// PrintWrite 字符打印流
//PrintWrite pw = new PrintWrite(System.out);
PrintWrite pw = new PrintWrite(new FileWrite("e\\f2.txt"));//抛出异常
pw.print("jl");
pw.close();//flush + colse 这里是真正写数据的地方,一定要colse
Properties类

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

配置文件的格式: 键=值

注意:键值对不需要空格,值不需要引号,默认String类型

Properties常见方法:

  1. load:加载配置文件的键值对到Properties对象
  2. list:将数据显示到指定设备
  3. getProperty(key):根据键获取值
  4. setProperty(key,value):设置键值对到Properties对象
  5. store:将Properties中的键值对存储到配置文件
//传统方法 读取mysql.properties文件,ip,user,pwd
BufferedReader br = new BufferedReader(new FileReader("src\\mysql.properties"));//抛异常
String line = ""
while((line = br.readLine())!= null){
  System.out.print(line);
  String[] str = line.split("=");
  System.out.print(str[0] +"值是" + str[1]);
}
br.close();

//使用Properties类 读取mysql.properties文件,ip,user,pwd
Properties properties = new Properties();
properties.load(new FileReader("src\\mysql.properties"));//抛出异常
properties.list(System.out);//输出到控制台
properties.getProperty("user");

//使用Properties类 添加键值对到mysql.properties
properties.set("charset","utf8");//如果,没有key就是创建,有key就是修改
properties.store(new FileReader("src\\mysql.properties"),null);//抛出异常

posted @   MrGeng  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示