在细讲JavaIO之前,先了解一下文件这个概念,这里IO可以简单分解成In-Out(输入-输出),这里输入输出的对象,简单理解一下就是各式各样的文件。内存中存放的数据,在电脑关机后就会消失。如果需要长久保存文件,就需要硬盘,磁盘,光盘,U盘等存储设备,在数据存储过程中,为了区分数据类别以及方便查询,就出现了“文件”的概念。
日常使用中按功能区分为文本文件、视频文件、音频文件、图像文件等等。但是在存储介质中,本质都是一个0、1组成的比特串。
为了方便文件的管理,又出现了树形目录机制,文件夹下可以存放文件,也可以嵌套文件夹,这就便利了用户对文件的管理与使用。
Java如何实现对文件和目录的操作?
Java作为一种面向对象语言,自然是通过对象,java将文件/目录的各种信息进行封装,如此就诞生了一个对象。通过对这个对象操作,就能获取文件的各种信息,以及进行创建、删除、修改等操作。
对文件/目录的操作:
package com.bluemsun.test;
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
File file = new File("a.txt");
if(!file.exists()){
file.createNewFile();
}
/**
* File.separator代表系统默认文件目录分隔符,即我们所说的“斜线”
* 但由于在Windows系统中分隔符为“\”
* 而在Linux系统中分隔符为“/”
*/
File file1 = new File("E:"+File.separator+"JAVAIO"+File.separator+"b.txt");
if(!file1.exists()){
file1.createNewFile();
}
//文件操作常用方法
System.out.println("文件是否可读:" + file.canRead());
System.out.println("文件是否可写:" + file.canWrite());
System.out.println("获取文件的名字:" + file.getName());
System.out.println("获取该文件的上级目录:" + file.getParent());
System.out.println("是否是一个目录:" + file.isDirectory());
System.out.println("是否是一个文件:" + file.isFile());
System.out.println("是否隐藏:" + file.isHidden());
System.out.println("获取文件大小:" + file.length() );
System.out.println("是否存在:" + file.exists());
//文件路径
System.out.println("绝对路径:"+file.getAbsolutePath());
System.out.println("相对路径:"+file.getPath());
System.out.println("toString:"+file);
//
// File file = new File("src\\com\\bluemsun\\demo\\a.txt");
// if(!file.exists()){
// file.createNewFile();
// }
// SystemDemo.out.println(file.getAbsolutePath());
// SystemDemo.out.println(file);
}
}
package com.bluemsun.test;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class Test1 {
public static void main(String[] args) throws IOException {
File file = new File("resources");
if(!file.exists()){
file.mkdir();
}
//文件操作常用方法
System.out.println("文件是否可读:" + file.canRead());
System.out.println("文件是否可写:" + file.canWrite());
System.out.println("获取文件的名字:" + file.getName());
System.out.println("获取该文件的上级目录:" + file.getParent());
System.out.println("是否是一个目录:" + file.isDirectory());
System.out.println("是否是一个文件:" + file.isFile());
System.out.println("是否隐藏:" + file.isHidden());
System.out.println("获取文件大小:" + file.length() );
System.out.println("是否存在:" + file.exists());
//文件路径
System.out.println("绝对路径:"+file.getAbsolutePath());
System.out.println("相对路径:"+file.getPath());
System.out.println("toString:"+file);
System.out.println("===============================================");
for(int i = 1; i <= 5; i++){
File file1 = new File("resources\\"+i+".txt");
if(!file1.exists()){
file1.createNewFile();
}
}
File[] fileList = file.listFiles();
for(File f : fileList){
System.out.println(f.getName());
System.out.println(f);
}
}
}
-
File类主要是JAVA为文件这块的操作(如删除、新增等)而设计的相关类
-
File类的包名是java.io,其实现了Serializable, Comparable两大接口以便于其对象可序列化和比较
下面我们正式引入IO流
I/O : Input/Output的缩写,用于处理设备之间的数据的传输。
形象理解:IO流 当做一根 “管”:
处理流,也叫包装流,是在“连接”已经存在的流(节点流或者处理流)之上,为程序提供强大的读写功能,更加灵活。如BufferedReader,BufferedWriter。
一、两者的组成不同:
1、字节流的组成:字节流是由字节组成的。
2、字符流的组成:字符流是由字符组成的。
二、两者的处理不同:
1、字节流的处理:主要用在处理二进制数据,它是按字节来处理的但实际中很多的数据是文本。
2、字符流的处理:按虚拟机的encode来处理,也就是要进行字符集的转化。
Java里字符由两个字节组成. 1字符=2字节
JAVA中的字节流是采用ASCII编码的,
字符流是采用好似UTF编码,支持中文的
字节流与字符流主要的区别是他们的的处理方式
字节流是最基本的,采用ASCII编码,所有的InputStream和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的
但实际中很多的数据是文本,又提出了字符流的概念,采用Unicode编码.它是按虚拟机的encode来处理,也就是要进行字符集的转化
这两个之间通过 InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String来关联。
IO流分类:
看完了IO家族,我们先尝试着通过java程序分步完成文件的复制。
第一步:文件–->程序:FileReader
第二步:程序–->文件:FileWriter
package com.bluemsun.demo;
import java.io.*;
/**
* @author zxy
*/
public class FileWriterAndReader {
public static void main(String[] args) throws IOException {
//=====================================================================================================
File file = new File("b.txt");
FileReader reader = new FileReader(file);
if(!file.exists()){
file.createNewFile();
}
int n = reader.read();
System.out.println(n);
n = reader.read();
System.out.println(n);
// reader.close();
// int n = 0;
// while((n = reader.read()) != -1){
// SystemDemo.out.print((char)n);
// }
/**
* 缓冲数组
*/
// 3
// char[] c = new char[2];
// while((reader.read(c)) != -1){
// String string = new String(c,0,c.length);
// SystemDemo.out.print(string);
// }
// reader.close();
//======================================================================================================
// 如果file不存在,会自动创建
File file1 = new File("c.txt");
// FileWriter writer = new FileWriter(file1);
// FileWriter writer = new FileWriter(file1, true);
// String str = "Hello bluemsun";
// for(int i = 0; i < str.length(); i++){
// writer.write(str.charAt(i));
// }
// writer.close();
//======================================================================================================
FileWriter fileWriter = new FileWriter(file1, true);
// int n = -1;
while((n = reader.read()) != -1){
System.out.print((char)n);
fileWriter.write((char)n);
}
fileWriter.close();
reader.close();
// 缓冲数组
// char[] c = new char[3];
// while((n = reader.read(c)) != -1){
// fileWriter.write(c,0,n);
// }
// fileWriter.close();
// reader.close();
}
}
什么流操作什么文件?
文本文件:.txt .java .c .cpp —> 建议使用字符流操作
非文本文件:.jpg, .mp3 , .mp4 , .doc , .ppt —> 建议使用字节流操作
(doc可以插入图片、视频,因此算非文本文件)
通过字节流实现图片复制
package com.bluemsun.demo;
import java.io.*;
public class FileStream {
public static void main(String[] args) throws IOException {
File file = new File("a.jpg");
FileInputStream fis = new FileInputStream(file);
int n = -1;
// while((n = fis.read()) != -1){
// SystemDemo.out.print(n);
// }
// fis.close();
File fileCopy = new File("b.jpg");
FileOutputStream fos = new FileOutputStream(fileCopy);
long time1 = System.currentTimeMillis();
while((n = fis.read()) != -1){
fos.write(n);
}
time1 = System.currentTimeMillis()-time1;
System.out.println(time1+" ms");
System.out.println(file.length());
System.out.println(fileCopy.length());
fis.close();
fos.close();
// byte[] bytes = new byte[1024*6];
// long time1 = SystemDemo.currentTimeMillis();
// while((n = fis.read(bytes)) != -1){
// fos.write(bytes,0,n);
// }
// time1 = SystemDemo.currentTimeMillis()-time1;
// SystemDemo.out.println(time1+" ms");
// fis.close();
// fos.close();
}
}
进阶:缓冲流
想要完成上面的效果,单纯的靠FileInputStream,FileOutputStream是不能完成的,这个时候就需要功能的加强
这个加强就需要引入新的流(在FileInputStream,FileOutputStream外面再套一层流):BufferedInputStream ,BufferedOutputStream. -----> 缓冲流 是处理流的一种。
字节流+缓冲流实现图片复制:
package com.bluemsun.demo;
import java.io.*;
public class BufferedStream {
public static void main(String[] args) throws IOException {
File file = new File("a.jpg");
File fileCopy = new File("b.jpg");
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(fileCopy);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] bytes = new byte[1024*8];
int n = -1;
long time = System.currentTimeMillis();
while((n = bis.read(bytes)) != -1){
bos.write(bytes,0,n);
}
time = System.currentTimeMillis()-time;
System.out.println(time+" ms");
bos.close();
bis.close();
}
}
下面来谈一组新的流:转换流
转换流:作用:将字节流和字符流进行转换。
转换流 属于 字节流还是字符流?属于字符流
InputStreamReader 作用:字节输入流 -->字符输入流
OutputStreamWriter 作用: 字符输出流 -->字节输出流
package com.bluemsun.demo;
import java.io.*;
public class TransferStream {
public static void main(String[] args) throws IOException {
// File file = new File("b.txt");
// FileInputStream fis = new FileInputStream(file);
// InputStreamReader isr = new InputStreamReader(fis);
//
// char[] c = new char[3];
// int n = -1;
// while((n = isr.read(c)) != -1){
// SystemDemo.out.print(new String(c,0,n));
// }
//
// isr.close();
//==================================================================================================
File file = new File("b.txt");
File target = new File("c.txt");
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis,"Unicode");
FileOutputStream fos = new FileOutputStream(target,true);
OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
char[] c = new char[3];
int n = -1;
while((n = isr.read(c)) != -1){
osw.write(c,0,n);
}
isr.close();
osw.close();
}
}
System.in && System.out && Scanner
package com.bluemsun.demo;
import java.io.*;
import java.util.Scanner;
public class SystemDemo {
public static void main(String[] args) throws IOException {
// 从键盘输入
// Scanner sc = new Scanner(new File("c.txt"));
// while(sc.hasNext()){
// System.out.println(sc.next());
// }
//
// System.out.println("Hello World!");
// System.out.print("Hello World!");
// sc.close();
//=======================================================================
//属于字节流
InputStream in = System.in;
BufferedInputStream bis = new BufferedInputStream(in);
InputStreamReader isr = new InputStreamReader(bis);
BufferedReader br = new BufferedReader(isr);
//
//
File file = new File("new.txt");
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
OutputStreamWriter osw = new OutputStreamWriter(bos);
BufferedWriter bw = new BufferedWriter(osw);
//
int n = -1;
while((n = br.read()) != -1){
if(n == '0') {
break;
}
bw.write(n);
}
bw.close();
br.close();
}
}
接下来我们来看看数据流
数据流:用来操作基本数据类型和字符串的
DataInputStream:将文件中存储的基本数据类型和字符串 写入 内存的变量中
DataOutputStream: 将内存中的基本数据类型和字符串的变量 写出 文件中
package com.bluemsun.demo;
import java.io.*;
public class DataSteam {
public static void main(String[] args) throws IOException {
File file = new File("object.txt");
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
dos.writeBoolean(true);
dos.writeUTF("这是string");
dos.writeInt(18);
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);
System.out.println(dis.readBoolean());
System.out.println(dis.readUTF());
System.out.println(dis.readInt());
dis.close();
dos.close();
}
}
最后来谈谈,对象流
对象流:ObjectInputStream,ObjectInputStream
用于存储和读取基本数据类型数据或对象的处理流。
它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
package com.bluemsun.demo;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class ObjectStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("object.txt")));
User user = new User(0,"zxy");
oos.writeObject(user);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("object.txt")));
User u = (User) ois.readObject();
System.out.println(u);
oos.close();
ois.close();
}
}
package com.bluemsun.demo;
import java.io.Serializable;
public class User implements Serializable {
public static final long serialVersionUID = 412341531521L;
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
ObjectOutputStream把自定义对象转换成字节序列的形式来表示,这些字节序列包含了对象的数据和信息,一个序列化后的对象可以被写入数据库或文件中,也可以用于网络传输。
ObjectInputStream可以把序列化后的字节序列恢复成原来的java对象,这就是反序列化。
如果需要让某个对象支持序列化机制,则必须让对象所属的类其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一。否则会抛出NotSerializableException异常。
-
Serializable
-
Externallizable
Java对象可序列化条件:
- 需要实现接口:Serializable
- 当前类提供一个全局变量:serialVersionUID
- 除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性也必须是可序列化的。(默认情况下,基本数据类型可序列化)