1.File文件操作类
java.io包中,File类是唯一一个与文件本身操作(创建、删除、取得信息)有关,与文件内容无关的程序类。
1.1File类(既可描述真实文件,也可是个文件夹)的基本使用
File类的两种实例化方式:
public File(String pathname) [绝对路径]
public File(String parent,String child):设置父路径和子路径
创建新文件:
public boolean createNewFile() throws IOException
路径分隔符:(separator 由不同的操作系统下的JVM来决定到底是哪个符号)
File.separator
例:创建一个新文件
public class Test2{
public static void main(String[] args) {
File file = new File("C:"+File.separator+"Users"+File.separator+
"Administrator"+File.separator+"Desktop"+
File.separator+"TestIO.java");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
判断文件是否存在:
public boolean exists()
删除文件:
public boolean delete()
例:
public class Test2{
public static void main(String[] args) {
File file = new File("C:"+File.separator+"Users"+File.separator+
"Administrator"+File.separator+"Desktop"+
File.separator+"TestIO.java");
if(file.exists()){
System.out.println("文件存在");
file.delete();
}else{
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
注意:只要删除在创建文件,后面的创建其实是一个更新操作。
1.2目录的操作
1.2.1取得父路径与父File对象
public String getParent()
public File getParentFile()
1.2.2创建目录(无论有多少级父目录,都会一次性创建)
public boolean mkdirs()
File file = new File("C:"+File.separator+"Users"+File.separator+
"Administrator"+File.separator+"Desktop"+File.separator+
"www"+File.separator+"bit"+File.separator+"Java"+File.separator+
"IO"+File.separator+"JavaIO.java");
//取得父文件对象
File parentFile = file.getParentFile();
if(!parentFile.exists()){
parentFile.mkdirs();
}
if(file.exists()){
file.delete();
}else{
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
1.3取得文件信息
判断File对象是否是文件:
public boolean isFile()
判断File对象是否是路径:
public boolean isDirectory()
取得文件大小:
public long length()
取得最后修改日期:
public long lastModified()
例:
public static void main(String[] args) {
File file = new File("C:"+File.separator+"Users"+File.separator+
"Administrator"+File.separator+"Desktop"+File.separator+
"图片.jpg");
if(file.exists() && file.isFile()){
System.out.println(file.length());
System.out.println(new Date(file.lastModified()));
}
}
列举一个目录的全部组成:
public File[] listFiles()
例:拿到当前路径下的所有文件
public class Test2{
public static void main(String[] args) {
//取得File对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+"Desktop");
System.out.println("遍历文件开始...");
long start = System.currentTimeMillis();
listAllFiles(file);
long end = System.currentTimeMillis();
System.out.println("遍历文件结束..."+(end-start)+"毫秒");
}
public static void listAllFiles(File file){
if(file.exists() && file.isFile()){
System.out.println(file);
}else{
//此时File对象为路径
File[] files = file.listFiles();
if(files != null){
for(File file1 : files){
listAllFiles(file1);
}
}
}
}
}
2.字节流与字符流
在java.io包中,流分为两种:
1.字节流(byte):InputStream、OuputStream
2.字符流(char):Reader、Writer
字节流与字符流的区别:
字节流是原生操作,而字符流是处理后的操作。一般使用字节流(无论是网络传输还是磁盘数据保存均已字节为单位),只有处理中文文本时才会用到字符流。
2.1流操作流程
无论是字节流还是字符流,操作流程几乎一样,以文本操作为例:
1.取得File对象
2.取得File对象的输入、输出流
3.进行数据的读取或写入
4.关闭流(close)
IO操作属于资源管理,所有资源管理(IO、数据库、网络)使用后都必须关闭。
2.2字节输出流(OutputStream)
观察OutputStream类的定义结构:
public abstract class OutputStream implements Closeable, Flushable
OutputStream类实现了Closeable、Flushable两个接口,这两个接口中的方法:
Closeable:public void close() throws IOException
Flushable:public void flush() throws IOException
在OutputStream类中还定义有其他方法:
2.2.1输出方法(write):
将指定的字节数组全部输出:
public void write(byte[] b) throws IOException
将部分字节数组输出:
public void write(byte[] b,int offset,int len) throws IOException
输出单个字节:
public abstract void write(int b) throws IOException
2.2.2要进行文件内容的输出,使用FileOutputStream子类:
文件内容覆盖:
public FileOutputStream(File file) throws FileNotFoundException
文件内容追加:
public FileOutputStream(File file,boolean append)
例:
public static void main(String[] args) throws IOException {
//1.取得终端对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+"Desktop"+
File.separator+"Test.txt");
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
//2.取得File对象的输出流
OutputStream outputStream = null;
try {
//OutputStream是一个抽象类,所以需要通过子类进行实例化
outputStream = new FileOutputStream(file,true);
//3.进行数据的输出
String msg = "IO课程\r\n";
outputStream.write(msg.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
//4.关闭流
outputStream.close();
}
}
当使用FileOutputStream进行文件内容的输出时,只要文件的父路径存在,FileOutputStream会自动创建文件。
2.2.3AutoCloseable自动关闭支持-JDK1.7
使用自动关闭接口有一个前提,需要结合try...catch...(需要结合try进行调用)
class Msg implements AutoCloseable{
public void print(){
System.out.println("normal method...");
}
@Override
public void close() throws Exception {
System.out.println("auto close...");
}
}
public class Test2{
public static void main(String[] args) throws IOException {
try(Msg msg = new Msg()) {
msg.print();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.3字节输入流(InputStream)
输入方法(read):
读取数据到字节数组b中:
public int read(byte[] b) throws IOException
返回值三种情况:
I.返回b长度:当读取的数据大小大于字节数组大小,返回字节数组大小
II.返回大于0但是小于b长度:读取数据大小小于字节数组大小,返回真正的读取个数
III.返回-1:数据读取完毕
读取单个字节:
public int read() throws IOException
public static void main(String[] args) throws IOException {
//1.取得FIle对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+
"Desktop"+File.separator+"Test.txt");
//2.取得输入流
InputStream in = new FileInputStream(file);
//3.读取文件内容
byte[] data = new byte[1024];
int result = in.read(data);
System.out.println(result);
System.out.println(new String(data,0,result));
//4.关闭流
in.close();
}
2.4字符流
字符输出流:Writer
相比于OutputStream,除了参数为字符数组外,多了一个传入String对象的方法
public void write(String str) throws IOException
例:
public static void main(String[] args) throws Exception {
//1.取得FIle对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+"Desktop"+File.separator+"Test.txt");
//2.取得输出流
Writer writer = new FileWriter(file);
//3.写入数据
String msg = "欢迎你";
writer.write(msg);
//4.关闭流
writer.close();
}
字符输入流:Reader
Reader类中没有方法可以直接读取字符串,只能通过字符数组来读取
在Java中一个英文字母和一个中文字母都是一个字符
例:
public static void main(String[] args) throws Exception {
//1.取得FIle对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+"Desktop"+
File.separator+"Test.txt");
//2.取得输入流
Reader reader = new FileReader(file);
//3.读取数据
char[] data = new char[1024];
int result = reader.read(data);
System.out.println(result);
System.out.println(new String(data,0,result));
//4.关闭流
reader.close();
}
2.5字节流与字符流
从实际开发来讲,字节流优先考虑,只有处理中文时才会考虑到使用字符流。所有字符流操作,无论是写入还是输出,数据都先保存在缓存中。
如果忘记关闭数据流:
字符流(没有输出结果)
public static void main(String[] args) throws Exception {
//1.取得FIle对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+"Desktop"+
File.separator+"Test.txt");
//2.取得输出流
Writer writer = new FileWriter(file);
//3.输出数据
String str = "hello world";
writer.write(str);
}
解决办法:
public static void main(String[] args) throws Exception {
//1.取得FIle对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+"Desktop"+
File.separator+"Test.txt");
//2.取得输出流
Writer out = new FileWriter(file);
//3.输出数据
String str = "hello world";
out.write(str);
//4.强制清空缓存区
out.flush();
}
字节流(有输出结果)
public static void main(String[] args) throws Exception {
//1.取得FIle对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+"Desktop"+
File.separator+"Test.txt");
//2.取得输出流
OutputStream out = new FileOutputStream(file);
//3.输出数据
String str = "hello world";
out.write(str.getBytes());
}
2.6转换流:字节流->字符流
转换流用于将底层的字节流转为字符流供子类使用:
OutputStreamWriter:字节输出流->字符输出流
InputStreamReader:字节输入流->字符输入流
首先来看这两个类的继承关系以及构造方法:
public class OutputStreamWriter extends Writer
public OutputStreamWriter(OutputStream out)
public class InputStreamReader extends Reader
public InputStreamReader(InputStream in)
例:观察字节流与字符流的转换
public class Test2{
public static void main(String[] args) throws Exception {
//1.取得终端对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+"Desktop"+
File.separator+"Test.txt");
//2.取得输出流
OutputStream outputStream = new FileOutputStream(file);
//3.进行数据的输入输出
OutputStreamWriter out = new OutputStreamWriter(outputStream);
out.write("真好");
//4.关闭流
out.close();
}
}
3.字符编码(UTF—8)
3.1GBK、GB2312:国际编码。GBK即包含简体中文也包含繁体中文,而GB2312只包含简体中文。
3.2INICODE:java提供的16进制编码,可以描述世界上任意的文字。由于采用16进制编码,导致编码的体积太大,造成网络传输负担。
3.3ISO-8859-1:浏览器默认编码,国际通用编码,不支持中文。
3.4UTF编码(UTF-8):相当于结合了ISO-8859-1和UNICODE编码,支持所有语言且体积较小。
4.内存流
除了文件之外,IO操作也可以发生在内存中,发生在内存中的操作流称为内存流。
内存流也分为两类:
字节内存流:ByteArrayInputStream、ByteArrayOutputStream
字符内存流:CharArrayReader、CharArrayWriter
观察ByteArrayInputStream和ByteArrayOutputStream的构造方法:
public ByteArrayInputStream(byte buf[])
public ByteArrayOutputStream()
public static void main(String[] args) {
//内存流实现字母转换
String msg = "hello";
//取得内存流
ByteArrayInputStream inputStream = new ByteArrayInputStream(msg.getBytes());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int len = 0;
while((len = inputStream.read()) != -1){
outputStream.write(Character.toUpperCase(len));
}
//直接将内存输出流输出
System.out.println(outputStream);
}
5.打印流
如果操作的不是二进制数据,只是想通过程序向终端目标输出信息的话,OutputStream不是很方便,其缺点为:
1.所有的数据必须转换为字节数组
2.如果要输出的是int、double等类型就不方便了
系统提供的两大打印流:
PrintStream:字节打印流
PrintWriter:字符打印流
例:使用打印流
public class Test2{
public static void main(String[] args) throws IOException {
PrintStream printStream = new PrintStream(new FileOutputStream(new File("C:"+File.separator+"Users"+
File.separator+"Administrator"+File.separator+"Desktop"+
File.separator+"Test.txt")));
printStream.print("姓名:");
printStream.println("gx");
printStream.print("年龄:");
printStream.println(18);
}
}
6.System对IO支持
输出(均是打印流PrintStream的对象)
1.标准输出(显示器) System.out
2.错误输出 System.err(输出为红色)
输入(输入流InputStream的对象)
3.标准输入(键盘) System.in
7.两种输入流
—BufferReader
—Scanner -java.Util.Scanner(重要)
判断是否有指定类型数据输入:
public boolean hasNextXXX()
取得指定类型数据:
public 数据类型 nextXXX()
自定义分隔符:
public Scanner useDelimiter(Pattern pattern)
例:
public class Test2{
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的年龄:");
if(scanner.hasNextInt()){
int age = scanner.nextInt();
System.out.println(age);
}else {
System.out.println("请输入正确的年龄");
}
}
}
8.序列化
8.1定义:将内存中的对象变为二进制流的形式进行传输或保存在文本中。(将对象变为二进制流)
8.2.实现:Java中若要被序列化输出,该类必须实现Serializable接口。该接口是一个标识接口,表示该类具有序列化的功能。
8.3.实现序列化与反序列化操作:
要想实现序列化与反序列化操作,需要额外使用io包提供的两个类ObjectOutputStream、ObjectInputStream。
对象序列化输出-ObjectOutputStream
将对象序列化输出方法:
//将obj变为二进制流输出到目标终端
public final void writeObject(Object obj) throws IOException{}
class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test2{
public static void main(String[] args) throws Exception {
//1.取得File对象
File file =
new File("C:\\Users\\Administrator\\Desktop\\Test.txt");
Person per = new Person("gx",18);
//2.取得输出流
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream(file));
//3.数据的读取
oos.writeObject(per);
//4.关闭流
oos.close();
}
}
对象的反序列化输入-ObjectInputStream
将对象反序列化输入方法
//将二进制流反序列化为对象
public final void readObject() throws IOException,classNotFoundException
public class Test2{
public static void main(String[] args) throws Exception {
//1.取得File对象
File file =
new File("C:\\Users\\Administrator\\Desktop\\Test.txt");
//2.取得输入流
ObjectInputStream ois =
new ObjectInputStream(new FileInputStream(file));
//3.数据的读取
Object result = ois.readObject();
System.out.println(result);
//4.关闭流
ois.close();
}
}
transient关键字:
使用Serializable序列化输出时,默认将对象的所有属性以及值均序列化以及反序列化。如果希望某些属性值不进行序列化输出,可以在属性前加transient关键字。