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包提供各种“流”类和接口,用以获取不同的数据,并通过方法输入或输出数据
分类:
-
操作数据单位:字节流(二进制文件)、字符流(文本文件)
-
数据流向 : 输入流、输出流
-
流的角色: 节点流,处理流/包装流
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相关方法:
- new FileReader(File/String)
- read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
- read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
- FileWriter相关方法:
- new FileWriter(File/String):覆盖模式,相当于流的指针在首端
- new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
- write(int):写入单个字符
- write(char[]):写入指定数组
- write(char[],off,len):写入指定数组的指定部分
- write(string):写入整个字符串
- 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();
}
}
节点流和处理流
- 节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter
2.处理流(包装流)是“连接”在已存在的流之上,为程序提供更为强大的读写功能,更加灵活,如BufferedReader、BufferedWriter
节点流与处理流区别:
- 节点流是底层流/低级流,直接跟数据源相接
- 处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
- 处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
处理流的功能主要体现在两方面:
- 性能的提高:主要增加缓冲的方式来提高输入输出的效率
- 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活
// 创建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)
序列化和反序列化:
-
序列化就是在保存数据时,保存数据的值和数据类型
-
反序列化就是恢复数据时,恢复数据的值和数据类型
-
需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类可序列化的,改该类必须实现以下两个接口之一:
-
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();
}
}
对象注意事项:
- 读写顺序要一致
- 要求实现序列化或反序列化对象,需要实现Serializable
- 序列化的类中建议添加SerialVersionUID,提高版本兼容性
- 序列化对象时,默认将里面所有的属性进行序列化,除了static 或transient修饰的成员
- 序列化对象时,要求里面属性的类型也需要实现序列化接口
- 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也默认实现序列化
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常见方法:
- load:加载配置文件的键值对到Properties对象
- list:将数据显示到指定设备
- getProperty(key):根据键获取值
- setProperty(key,value):设置键值对到Properties对象
- 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);//抛出异常
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律