IO流
文件
- 文件就是保存数据的地方
- 文件流:文件在程序中是以流的形式来操作的
- 输入流:数据从文件(硬盘)读取到程序(内存)
- 输出流:数据从程序(内存)写入到文件(硬盘)
常用的文件操作
- 创建文件对象相关构造器和方法
new File(String pathname)//根据路径构建一个文件
new File(File parent,String child)//根据父目录文件+子路径构建
new File(String parent,String child)//根据父路径+子路径构建
createNewFile 创建新文件
- 获取文件的相关信息
@Test
public void info() {
//创建文件对象
File file = new File("G:\\xinfan\\note\\a.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());
}
- 目录的操作和文件删除
@Test
public void m1(){
File file = new File("G:\\xinfan\\note\\a.txt");
if (file.exists()) {
if (file.delete()) {
System.out.println("文件被删除");
} else {
System.out.println("文件删除失败");
}
}
}
@Test
public void m2() {
//文件夹也是文件的一种
String path = "G:\\xinfan\\note\\a\\b\\c";
File file = new File(path);
if (file.exists()) {
System.out.println(path + "已经存在");
} else {
file.mkdirs();
System.out.println(path+"被创建");
}
}
IO流原理及流的分类
Java IO流原理
- I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件、网络通讯等
- Java程序中,对于数据的输入/输出操作以“流”的方式进行
- java.io包下提供了各种“流”接口和类,用以获取不同种类的数据,并通过方法输入和输出数据
- 输入Input:读取外部数据(存储设备的数据)到程序(内存)中
- 输出Output:将程序中处理过的数据写入存储设备
流的分类
- 按操作数据单位不同分为:字节流(用于操作二进制文件)、字符流
- 按数据流的流向不同分为:输入流、输出流
- 按流的角色的不同分为:节点流、处理流/包装流
| (抽象基类) | 字节流 | 字符流 |
|---|---|---|
| 输入流 | InputStream | Reader |
| 输出流 | OutputStream | Writer |
常用的类
InputStream/OutputStream:字节输入/出流
- FileInputStream/FileOutputStream:文件输入/出流
/**
* 读取单个字节 效率比较低
* ----------->read(byte[] b)
*/
@Test
public void read1() {
String path = "G:\\桌面\\test.txt";
FileInputStream fileInputStream = null;
int readData = 0;
try {
fileInputStream = new FileInputStream(path);
while ((readData = fileInputStream.read()) != -1) {//每次向后读一个 所以必须放在判断条件里面
System.out.print((char) (readData));//utf-8 三个字节为一个字符 所以会中文乱码
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* read(byte[] b)
*/
@Test
public void read2() {
String path = "G:\\桌面\\test.txt";
FileInputStream fileInputStream = null;
byte[] buf = new byte[3];
int length = 0;
try {
fileInputStream = new FileInputStream(path);
while ((length = fileInputStream.read(buf)) != -1) {
System.out.print(new String(buf,0,length));
/*System.out.print(new String(buf));//不截取长度最后一次会填入之前的值 不会自动清空
System.out.println();*/
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//FileOutPutStream
@Test
public void write1() {
String out = "hello000 world";
String filename = "G:\\桌面\\out.txt";
FileOutputStream fileOutputStream = null;
File file = new File(filename);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
fileOutputStream = new FileOutputStream(file);//新的内容会覆盖原来的内容
//fileOutputStream = new FileOutputStream(file,true);以追加的方式添加
/*char[] chars = out.toCharArray();
for (int i = 0; i < chars.length; i++) {
fileOutputStream.write(chars[i]);
}*/
fileOutputStream.write(out.getBytes());
// void write(byte[] b, int off, int len)
//将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- BufferedInputStream/BufferedOutputStream:缓冲字节输入/出流
package com.xinfan.io.buffered;
import java.io.*;
/**
* @Author xin
* @Date 2022/6/8 21:30
* @Version 1.0
*
* 字节处理流拷贝文件
*/
public class BufferedInputStream_ {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
String path = "G:\\桌面\\11111.png";
String des = "G:\\桌面\\1111.png";
byte[] bytes = new byte[1024];
int readLen = 0;
bis = new BufferedInputStream(new FileInputStream(path));
bos = new BufferedOutputStream(new FileOutputStream(des));
while ((readLen = bis.read(bytes)) != -1) {
bos.write(bytes,0,readLen);
}
bos.close();
bis.close();
}
}
- ObjectInputStream/ObjectOutputStream:对象字节输入/出流 提供序列化和反序列化功能
序列化和反序列化:
-
序列化就是在保存数据时,保存数据的值和数据类型
-
反序列化就是在恢复数据时,恢复数据的值和数据类型
-
需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
1.Serializable //推荐使用 这是一个标记接口 没有方法
2.Externalizable
对象处理流的注意事项
- 读写顺序要一致
- 要求实现序列化和反序列化的对象必须实现Serializable或者Externalizable接口
- 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
- 序列化对象时,默认里面所有属性都会序列化,但除了static或transient修饰的成员
- 序列化对象时,要求里面属性的类型也需要实现序列化接口
- 序列化具备可继承性,也就是如果一个类实现了序列化,那么它的所有子类默认也实现了序列化
public class ObjectInputStream_ {
public static void main(String[] args) throws IOException {
String src = "G:\\桌面\\test.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(src));
System.out.println(ois.readInt());
System.out.println(ois.readDouble());
System.out.println(ois.readChar());
System.out.println(ois.readUTF());
try {
Object object = ois.readObject();//存取顺序一定要一致否则有可能出现抓换异常
Dog dog = (Dog)object;
System.out.println(dog);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ois.close();
}
}
public class ObjectOutputStream_ {
public static void main(String[] args) throws IOException {
String des = "G:\\桌面\\test.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(des));
oos.writeInt(12);
oos.writeDouble(9.9);
oos.writeChar('中');
oos.writeUTF("写入字符串的方法为UTF");
oos.writeObject(new Dog("小黄",2));
oos.close();
}
}
public class Dog implements Serializable {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Reader/Writer
- FileReader/FileWriter
public static void main(String[] args) {
String src = "G:\\桌面\\test.txt";
char[] data = new char[1024];
int len = 0;
FileReader fileReader = null;
try {
fileReader = new FileReader(src);
while ((len = fileReader.read(data)) != -1) {
System.out.print(new String(data,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
节点流和处理流
- 节点流可以从特定的数据源读写数据,如FIleReader、FileWriter
- 处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter
节点流和处理流的区别和联系
- 节点流是底层流/低级流,直接和数据源对接
- 处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来处理输入输出
- 处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
处理流的功能主要体现在以下两个方面
- 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
- 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
处理流设计模式简单代码实现
public class BufferedReader_ extends Reader_{
private Reader_ reader_;
public BufferedReader_(Reader_ reader_) {
this.reader_ = reader_;
}
public void readFiles(int num) {
for (int i = 0; i < num; i++) {
reader_.readFile();
}
}
public void readStrings(int num) {
for (int i = 0; i < num; i++) {
reader_.readString();
}
}
public static void main(String[] args) {
BufferedReader_ bufferedReader_ = new BufferedReader_(new StringReader_());
bufferedReader_.readStrings(10);
}
}
abstract class Reader_{
public void readFile(){}
public void readString(){}
}
class FileReader1 extends Reader_{
public void readFile(){
System.out.println("文件读取流");
}
}
class StringReader_ extends Reader_{
public void readString(){
System.out.println("字符串读取流");
}
}
转换流(字节流可以设置编码格式)
- InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)
- OutputStreamWriter:Writer的子类,可以将OutputStream(字节流)包装成Writer(字符流)
- 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
- 可以在使用时指定编码格式(比如utf-8,gbk,gb2312,ISO8859-1等)
/**
* @Author xin
* @Date 2022/6/9 10:03
* @Version 1.0
* 通过转换流解决中文乱码问题
*/
public class InputStreamReader_ {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("G:\\桌面\\test.txt"),"gbk");//通过字节流指定编码
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}
输入流
System.in
编译类型:InputStream
运行类型:BufferedInoutStream
输出流
System.out
编译类型:PrintStream
运行类型:PrintStream
打印流
PrintStream和PrintWriter
public class PrintStream_ {
public static void main(String[] args) throws IOException {
PrintStream out = System.out;
//打印的底层就是调用的write方法
//public void print(String s) {
// if (s == null) {
// s = "null";
// }
// write(s);
// }
out.write("hihi".getBytes());
//指定输出位置
System.setOut(new PrintStream("G:\\桌面\\b.txt"));
System.out.println("test");
}
}
public class PrintWriter_ {
public static void main(String[] args) throws IOException {
// PrintWriter writer = new PrintWriter(System.out);
PrintWriter writer = new PrintWriter(new FileWriter("G:\\桌面\\kkk.txt"));
writer.write("test");
writer.close();//一定要关闭输出流 否则写不进去
}
}
Properties
- 专门用于读取配置文件的集合类
配置文件的格式:
键=值
键=值
- 注意:键值对不需要有空格,值不需要用引号引起来。默认类型是string
- 常见方法
-
load:加载配置文件的键值对到Properties对象中
-
list:将数据显示到指定的地方
-
getProperty(key): 根据键获取对应的值
-
setProperty(key,value):设置键值对到Properties对象中
-
store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为Unicode码
https://tool.chinaz.com/tools/unicode.aspx unicode码查询工具
传统方式读取配置文件
public class Properties_ {
public static void main(String[] args) {
//传统方法读取配置文件
tradition();
}
public static void tradition() {
BufferedReader br = null;
try {
String line;
br = new BufferedReader(new FileReader("src\\mysql.properties"));
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Properties读取/修改/保存配置文件
public class Properties2_ {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
//properties.load(new BufferedReader(new FileReader("src\\mysql.properties")));
properties.load(new BufferedReader(new InputStreamReader(new FileInputStream("src\\mysql.properties"),"utf8")));
properties.list(System.out);
String user = properties.getProperty("user");//中文乱码
System.out.println(user);
//如果已经存在该属性就是修改值
properties.setProperty("验证码","test");
//BufferedWriter bw = new BufferedWriter(new FileWriter("src\\mysql2.properties"));
properties.store(new FileOutputStream("src\\mysql2.properties"),"a");
//properties.store(bw,"a");
}
}
748

被折叠的 条评论
为什么被折叠?



