I/O详解
1、文件的基本使用
-
文件是保存数据的地方
-
文件流
- 文件在程序中是以流的形式来操作的
-
流:数据在数据源(文件)和程序(内存)之间经历的路径
-
输入流:数据从数据源(文件)到程序(内存)的路径
-
输出流:数据从程序(内存)到数据源(文件)的路径
-
常用文件操作
-
创建文件对象相关构造器和方法
-
new File(String pathname)//根据路径构建一个File对象
-
new File(File parent,String child)//根据父目录文件+子路经构建
-
new File(String parent,String child)//根据父目录+子路径构建
-
createNewFile
创建新文件
-
-
获取文件信息
getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory
2、IO流原理及流的分类
-
Java IO流原理
- I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读、写文件,网络通讯等 。
- Java程序中,对于数据的输入、输出操作以流 的方式进行。
Java.io
包下提供了各种“流”类的接口,用以获取不同种类的数据,并通过方法输入或输出数据- 输入input,读取外部数据到程序中
- 输出Output,将程序输出到磁盘中
-
流的分类
-
按操作数据单位不同分为:字节流(
8bit
)二进制文件,字符流(按字符)文本文件 -
按数据流的流向不同分为:输入流,输出流
-
按流的角色的不同为:节点流,处理流/包装流
-
1)Java的IO流共涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生。上面4个类都是抽象类,只能通过实现他们的子类创建对象
-
2)由这个四个类派生出来的子类名称都是以其父类名作为子类名后缀
-
-
InputStream:字节输入流
-
InputStream
抽象类是所有类字节输入流的超类 -
InputStream
常用子类 -
1.
FileInputStream
:文件输入流 -
2.
BufferedInputStream
:缓冲字节输入流 -
3.
ObjectInputStream
:对象字节输入流
-
/**
* 演示FileInputStream使用(字节输入流 文件->程序)
*/
public class FileInputStream01 {
//演示FileInputStream使用(字节输入流 文件->程序)
public static void main(String[] args) {
FileInputStream fis = null;
File file = new File("d:\\Hello.txt");
int readData = 0;
try {
fis = new FileInputStream(file);
//从该输入流读取一个字节的数据。如果没有输入可用,此方法将阻止。
//如何返回-1,表示读取完毕
while((readData = fis.read()) != -1){
System.out.print((char) readData);//转成char显示
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
fis.close();//强制关闭输入流
} catch (IOException e) {
e.printStackTrace();
}
}
}
//加快读取效率,一次性读取8个字节
// 演示FileInputStream使用(字节输入流 文件->程序)
public static void main(String[] args) {
File file = new File("d:\\Hello.txt");
//字节数组
byte[] bytes = new byte[8];//一次读取8个字节
int readLen = 0;
FileInputStream fis = null;
try {
//创建FileInputStream 对象,用于读取文件
fis = new FileInputStream(file);
//从该输入流读取最多b.length字节的数据到字节数组。此方法将阻塞,直到某些输入可被读取之后
//如何返回-1,表示读取完毕
//如果正常读取,返回实际读取的字节数
while((readLen = fis.read(bytes)) != -1){
System.out.print(new String(bytes,0,readLen));//显示
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
fis.close();//强制关闭输入流
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 演示使用FileOutputStream将数据写到文件中,
* 如果改文件不存在,则创建该文件
*/
//创建 FileOutputStream对象
String filePath = "d://yang.txt";
FileOutputStream fileOutputStream = null;
try {
//得到FileOutputStream对象
fileOutputStream = new FileOutputStream(filePath,true);
//1.new FileOutputStream(filePath)创建方式,当写入内容是,会覆盖原来的内容
//2.new FileOutputStream(filePath,true)创建方式,当写入内容是,是最加到文件后面
//写入一个字节
//fileOutputStream.write('a');
//写入多个字节
String str = "hello,world";
//str.getBytes()可以吧 字符串-> 字节数组
//fileOutputStream.write(str.getBytes());
// write(byte b[], int off, int len) 将len字节从位于偏移量off的指定字节数组写入此文件输入流
fileOutputStream.write(str.getBytes(),0,str.length());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//完成文件拷贝,将"F://a.jpg"拷贝"D://a.jpg"
//思路分析
//1.创建文件对的输入流,将文件读入到程序
//2.创建文件的输出流,将读取到的文件数据,写入到指定的文件
String srcfilePath = "F://a.jpg";
String filePath = "D://a.jpg";
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(srcfilePath);
fileOutputStream = new FileOutputStream(filePath);
//定义一个字节数组,提高读取效率
byte[] bytes = new byte[1024];
int readLean = 0;
while((readLean = fileInputStream.read(bytes)) != -1){
//读取到后,就写入到文件通过fileOutputStream
fileOutputStream.write(bytes,0,readLean);//读入的缓冲区的整数倍,偏移量,每次读 入的字节数
}
System.out.println("OK");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fileInputStream != null) {
fileInputStream.close();
}
if(fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
3、FileReader和FileWriter
- FileReader相关方法
- new FileReader(File/String)
- read:每次读取单个字符,返回该字符,如果到文件末尾返回-1.
- read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1.
- 相关API:
- new String(char[]):将char[]转换成String
- new String(char[],off,len):将char[]的指定部分转换成String
单个字符读取文件
String path = "f:\\a.txt";
FileReader fileReader = null;
int readLen = 0;
try {
//1.创建FileReader对象
fileReader = new FileReader(path);
//循环读取,使用read(chars),返回的是实际读取到的字符数
//如果返回-1,说明到文件结束
while ((readLen = fileReader.read()) != -1) {
System.out.print((char)readLen));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fileReader!=null){
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
字符数组读取文件
String path = "f:\\a.txt";
FileReader fileReader = null;
int readLen = 0;
char[] chars = new char[1024];
try {
//1.创建FileReader对象
fileReader = new FileReader(path);
//循环读取,使用read(chars),返回的是实际读取到的字符数
//如果返回-1,说明到文件结束
while ((readLen = fileReader.read(chars)) != -1) {
System.out.print(new String(chars,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fileReader!=null){
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
- FileWriter常用方法
-
new FileWriter(File/String):覆盖模式,相当于流的指针在首端
-
new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
-
write(int):写入单个字符
-
write(char[]):写入指定数组
-
write(char[],off,len):写入指定数组的指定部分
-
write(String):吸入整个字符串
-
write(String):写入整个字符串
-
write(String,off,len)写入字符串的指定部分
-
相关部分:String类,toCharArray:将String转换成char[]
-
(注意)FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!
-
String path = "f:\\a.txt";
FileWriter fileWriter = null;
char[] chars ={'a','b','c'};
try {
//1.创建FileWriter对象
fileWriter = new FileWriter(path);
//3)write(int):写入单个字符
fileWriter.write('Y');
//4)write(char[]):写入指定数组
fileWriter.write(chars);
//5)write(char[],off,len)写入指定数组的指定部分
fileWriter.write("杨大涛最美".toCharArray(),0,3);
//6)writ(String):写入整个字符串
fileWriter.write("你好北京~");
//7)write(String,off,len):写入字符串的指定部分
fileWriter.write("杨大涛最美",0,2);
//数据量大,用循环操作
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fileWriter!=null){
fileWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//对应FileWriter,一定要关闭流,或者flush才能真正的把数据写入到文件
}
System.out.println("程序结束...");
}
4、节点流和处理流
package writer;
public abstract class Reader_ { //抽象类
public void readFile(){
}
public void readString(){
}
}
package writer;
//节点流
public class FileReader_ extends Reader_{
public void readFile(){
System.out.println("对文件进行读取...");
}
}
package writer;
//节点流
public class StringReader_ extends Reader_ {
public void readString(){
System.out.println("读取字符串...");
}
}
package writer;
public class BufferedReader_ extends Reader_{
private Reader_ reader_ ;//属性是 Reader_类型
//接受Reader_ 子类对象
public BufferedReader_(Reader_ reader_){//封装一层
this.reader_ = reader_;
}
//让方法更灵活,多次读取文件,或者加缓冲
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();
}
}
}
package writer;
public class Test {
public static void main(String[] args) {
BufferedReader_ bufferedReader_ = new BufferedReader_(new FileReader_());
bufferedReader_.readFiles(10);
BufferedReader_ bufferedReader_1 = new BufferedReader_(new StringReader_());
bufferedReader_1.readString(4);
}
}
5、BufferedInputStream和BufferedOutStream
-
BufferedInputStream
是字节流,在创建BufferedInputStream时
,会创建一个内部缓冲区数组
-
BufferedOutStream
是字节流,实现缓冲输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统
6、BufferedReader和BufferedWriter
-
BufferedReader
和BufferedWriter
属于字符流,是按照字符来读取数据的- 关闭时处理流,只需要关闭外层流即可
public class BufferedCopy_ {
//二进制文件的拷贝(图片视频,音频)
public static void main(String[] args) {
String srcFilePath = "d:\\2.jpg";
String descFilePath = "d:\\3.jpg";
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
//创建BufferedInputStream对象和BufferedOutputStream对象
try {
bis = new BufferedInputStream(new FileInputStream(srcFilePath));
bos = new BufferedOutputStream(new FileOutputStream(descFilePath));
//循环读取文件,并写入到descFilePath
byte[] bytes = new byte[1024];
int readLine = 0;
//当返回-1时,就表示文件读取完毕
while((readLine = bis.read(bytes)) != -1){
bos.write(bytes,0,readLine);
}
System.out.println("拷贝完成...");
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭流
try {
if(bis != null) {
bis.close();
}
if(bos != null) {
bos.close();
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
}
BufferedReader
public class BufferReader_ {
//BufferedReader演示
public static void main(String[] args) throws IOException {
String pathFile = "d:\\a.txt";
//创建bufferedReader
BufferedReader bufferReader = new BufferedReader(new FileReader(pathFile));
//读取
String line; //按行读取,效率高
//说明
//1..bufferedReader.readLine()是按行读取文件
//2.当返回null时,表示文件读取完毕
while((line = bufferReader.readLine()) != null){
System.out.println(line);
}
//关闭流,这里注意,只需要关闭BufferedReader,因为底层会自动的去关闭,节点流
//FileReader.
/**
* public void close() throws IOException {
* synchronized (lock) {
* if (in == null)
* return;
* try {
* in.close(); 就是关闭的 new FileReader(pathFile)
* } finally {
* in = null;
* cb = null;
* }
* }
*/
bufferReader.close();
}
}
public class BufferedWriter_ {
//BufferedWriter的使用
public static void main(String[] args) throws IOException {
String filePath = "d:\\d.txt";
//创建BufferedWriter的对象
//1.new FileWriter(filePath,true)表示追加的方式写入
//2.new FileWriter(filePath)覆盖的方式写入
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write("杨大涛最美!!!");
bufferedWriter.newLine(); //插入一个和系统相关的换行
bufferedWriter.write("杨大涛最美!!!");
bufferedWriter.newLine(); //插入一个和系统相关的换行
bufferedWriter.write("杨大涛最美!!!");
//说明 :关闭外层流即可,传入的new FileWriter(filePath),会在底层关闭
bufferedWriter.close();
}
}
public class BufferedCopy {
//文件的Copy
public static void main(String[] args) {
//1.BufferedReader 和 BufferedWriter是按照字符操作
//2.不要去操作二进制文件,可能造成文件损坏
String srcFilePath = "d:\\a.txt";
String destFilePaht = "d:\\a2.txt";
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(srcFilePath));
bw = new BufferedWriter(new FileWriter(destFilePaht));
String s = null;
while ((s = br.readLine()) != null){
//每读取一行,就写入
bw.write(s);
//插入一个也换行
bw.newLine();
}
System.out.println("拷贝成功...");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (br != null) {
br.close();
}
if (bw != null) {
bw.close();
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
7、对象流-ObjectInputStream和ObjectOutputStream
- 功能:提供了对基本类型或对象类型的序列化和反序列化的方法
- ObjectOutputStream提供序列化功能
- ObjectInputStream提供反序列化功能
public class Dog implements Serializable {
private String name;
private int age;
//SerializableUID 序列化的版本号,可以提高兼容
// 如果增加一个属性,程序会认为是版本修改,而不是类的更改
private static final long SerialVsersionUID = 1L;
//默认将所有属性进行序列化,但除了static或transient修饰成员
private static Striing nation;
private transient String color;
//序列化对象时,要求里面属性的类型也需要实现序列胡接口
private Master mast;
public Dog(String name, int age) {
this.name = name;
this.age = 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;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ObjectOutStream {
//ObjectOutStream的使用,完成数据序列化
public static void main(String[] args) throws IOException {
//序列化后,保存的文件格式,不是纯文本,而是按照他的格式来 保存
String filePath = "d:\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到e:\\data.bat
oos.write(100);//int -> Integer(实现 Serializable)
oos.writeBoolean(true); //Boolean -> Boolean (实现 Serializable)
oos.writeChar('a'); //char -> Character(实现 Serializable)
oos.writeDouble(9.5); //double -> Double(实现 Serializable)
oos.writeUTF("韩顺平教育");//String
//保存一个dog对象
oos.writeObject(new Dog("旺财",12));
oos.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
class Dog implements Serializable {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException, EOFException {
//指定反序列化文件
String filePath = "d:\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//1.读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致
//2.否则会出现异常
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);//底层Object->Dog
Dog dog1 = (Dog)dog;
System.out.println(dog1.getName());//旺财..
//关闭流,关闭外层流即可,底层会关闭FileInputStream流
ois.close();
}
}
8、转换流-InputStreamReader和OutputStreamWriter
public static void main(String[] args) throws IOException {
String filePath = "d:\\a.txt";
//解读
//1.把FileInputStream 转成InputStreamReader
//2.指定编码UTF-8
InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath),"UTF-8");
//3.把InputStreamReader 传入 BufferedReader
BufferedReader br = new BufferedReader(isr);
//4.读取
String s = br.readLine();
System.out.println("读取内容为:"+s);
//5.关闭外层流
br.close();
}
public class OutputStreamWriter_ {
/**
* 演示使用OutputStreamWriter转换流解决中外文乱码问题
* 将字节流OutputStream转成字符流OutputStreamReader,指定编码gbk/utf-8/utf8
*/
public static void main(String[] args) throws IOException {
String filePath = "d:\\b.txt";
String cherset = "utf8";
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), cherset);
osw.write("爱你呦小朱朱,我会好好爱你的哦,虽然有时候我们避免不了的吵架,但是我绝做不出那样的事情来的哈");
System.out.println(osw);
osw.close();
}
}
public class PrintStream_ {
/**
*演示PrintStream(字节打印流、输出流)
*/
public static void main(String[] args) throws FileNotFoundException {
PrintStream out = System.out;
out.print("小朱朱最美,最乖,最可爱");
out.close();
//我们可以去修改打印流输出的位置、设备
//1.输出修改“d:\\f1.txt”
System.setOut(new PrintStream("d:\\f1.txt"));
System.out.println("杨大涛最美");
}
}
public class PrintWriter_ {
/***
* PrintWriter使用方式
*/
public static void main(String[] args) throws IOException {
//PrintWriter printWriter = new PrintWriter(System.out);
PrintWriter pw = new PrintWriter(new FileWriter("d:\\f2.txt"));
pw.print("hi,北京你好..");
pw.close();
}
}
9、Properties类
public class Properties_ {
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);
//4.根据key,获取对应的值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");
System.out.println("用户名:"+user);
System.out.println("密码:"+pwd);
}
}
public class Properties_01 {
public static void main(String[] args) throws IOException {
//使用Properties类来创建文件,修改配置文件内容
Properties properties = new Properties();
//创建
properties.setProperty("charset","utf-8");
properties.setProperty("user","汤姆");
properties.setProperty("pwd","abc111");
//将k-v存储文件中即可
properties.store(new FileOutputStream("src\\mysql2.properties"),null);
System.out.println("保存配置文件成功~");
}
}