输入/输出流
1.File类
File类可以使用文件路径字符串来创建File实例,该文件路径字符串可以是绝对路径,也可以是相对路径。
1.1访问文件名
方法 | 描述 |
---|---|
String getName() | 返回File对象的文件名或者路径名 |
String getPath() | 返回File对象对应的路径名 |
File getAbsoluteFile() | 返回File对象的绝对路径 |
String getAbsolutePath() | 返回File对象的绝对路径名 |
String getParent() | 返回File对象的父目录 |
boolean renameTo(File newName) | 重命名文件 |
代码示例:
//返回File对象的文件名或者路径名
String name = file.getName();
System.out.println(name);
//相对路径
String path = file.getPath();
System.out.println(path);
//绝对路径
String f1 = file.getAbsolutePath();
System.out.println(f1);
//上一级目录
String parent = file.getParent();
System.out.println(parent);
//重命名文件
File file2 = new File("D://2019xx");
boolean b= file.renameTo(file2);
System.out.println(b);
//返回File对象的绝对路径
File file3 = file.getAbsoluteFile();
System.out.println(file3);
1.2 文件检测
方法 | 描述 |
---|---|
boolean exists() | 判断File对象所对应的文件或目录是否存在 |
boolean canWrite() | 判断文件和目录是否可写 |
boolean canRead() | 判断文件和目录是否可读 |
boolean isFile() | 判断是否是文件 |
boolean isDirectory() | 判断是否是目录 |
boolean isAbsolute() | 判断是否是绝对路径 |
boolean isHidden() | 判断文件是否隐藏 |
代码示例:
//判断可读
System.out.println(file.canRead());
//判断可写
System.out.println(file.canWrite());
//判断是否存在
System.out.println(file.exists());
//判断是否是绝对的
System.out.println(file.isAbsolute());
//判断是否是文件
System.out.println(file.isFile());
//判断是否是目录
System.out.println(file.isDirectory());
//判断是否是隐藏文件
System.out.println(file.isHidden());
1.3 获取文件信息
方法 | 描述 |
---|---|
long lastModified() | 最后一次修改时间 |
long length() | 获取文件长度 |
代码示例:
File file= new File("D://1//2//111.txt");
//最后一次修改时间
long l = file.lastModified();
Date d= new Date(l);
SimpleDateFormat s= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String string = s.format(d);
System.out.println(string);
//获取文件长度
long length = file.length();
System.out.println(length);
1.4文件操作
方法 | 描述 |
---|---|
boolean createNewFile() | 当File对象对应的文件不存在时, 该方法新建一个File对象指定的新文件。成功返回true |
boolean delete() | 删除文件 |
代码示例:
public static void main(String[] args) throws IOException {
File file = new File("D://1//2//3");
//创建文件夹
boolean b = file.mkdirs();
System.out.println(b);
//删除文件
boolean delete = file.delete();
System.out.println(delete);
File f1 = new File("D://1//2//1.png");
//当File对象对应的文件不存在时,该方法新建一个File对象指定的新文件。成功返回true
boolean b1 = f1.createNewFile();
System.out.println(b1);
}
1.5 目录操作
方法 | 描述 |
---|---|
boolean mkdir() | 创建新目录 |
boolean mkdirs() | 创建多层目录 |
String[] list() | 列出File对象子文件名和路径名,返回String数组 |
File[] listFiles() | 列出File对象的所有子文件和路径 |
static File[] listRoots() | 获取系统根路径(获取分区) |
代码示例:
//创建一层文件夹
boolean b = file.mkdir();
System.out.println(b);
//创建多层文件夹
boolean b1 = file.mkdirs();
System.out.println(b1);
File file = new File("D://2019px");
//只获取目录和文件名称
String[] list = file.list();
for (String string : list) {
System.out.println(string);
}
//获取磁盘分区(根目录)
File[] listRoots = File.listRoots();
for (File file2 : listRoots) {
System.out.println(file2);
}
//获取目录的子目录,文件
File[] files = file.listFiles();
for (File f1 : files) {
System.out.println(f1);
}
1.6 获取分区大小
方法 | 描述 |
---|---|
long getTotalSpace() | 获取分区大小 |
long getFreeSpace() | 获取分区空闲大小 |
long getUsableSpace() | 获取分区可用大小 |
代码示例:
File f1= new File("D://");
//获取分区大小
long totalSpace = f1.getTotalSpace();
System.out.println(totalSpace/1024/1024/1024);
//获取分区空闲大小
long freeSpace = f1.getFreeSpace();
System.out.println(freeSpace/1024/1024/1024);
//获取分区可用大小
long usableSpace = f1.getUsableSpace();
System.out.println(usableSpace/1024/1024/1024);
2.InputStream和OutputStream
2.1FileInputStream
方法 | 描述 |
---|---|
FileInputSteam(File f) | 构造方法,传入File对象 |
FileInputSteam(String path) | 构造方法,传入文件路径 |
int read() | 一次读1字节,逐个读取,文件末尾返回-1 |
int read(byte[] b) | 一次读取b.length长度字节 |
int read( byte[ ] b,int offset,int len) | 从输入流中读取最多len长度的字节, 保存到字节数组b中, 保存的位置从offset开始 |
void close() | 关闭此输入流并释放与流相关联的任何系统资源。 |
int available() | 返回从该输入流中可以读取(或跳过)的字节数的估计值, 而不会被下一次调用此输入流的方法阻塞。 |
代码示例:
public static void main(String[] args) {
FileInputStream fis = null;
try {
File file = new File("D://1//2//111.txt");
fis = new FileInputStream(file);
//fis.available()判断文件可读取的字节数
//利用缓冲区byte数组加快输出速率
byte[] bs = new byte[fis.available()];
int i;
读取下一个字节数据,并存入缓冲区数组中,返回实际读取的字节数
while ((i = fis.read(bs)) > -1) {
//将byte数组转换为String类型
System.out.println(new String(bs));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2FileOutputStream
方法 | 描述 |
---|---|
FileOutputStream(File file) | 创建文件输出流以写入由指定的File对象表示的文件 |
FileOutputStream(File file, boolean append) | 创建文件输出流以写入由指定的File对象表示的文件 |
FileOutputStream(String name) | 创建文件输出流以指定的名称写入文件 |
FileOutputStream(String name, boolean append) | 创建文件输出流以指定的名称写入文件 |
void write() | 将指定的字节数据写入此输出流中 |
void write( byte[ ] b ) | 将b.length个字节从指定的字节数组写入此文件输出流 |
void write( byte[ ] b , int offset , int len ) | 将len字节从位于偏移量 offset的指定字节数组写入此文件输出流 |
void close() | 关闭此文件输出流并释放与此流相关联的任何系统资源 |
代码示例:
public class OutputTest1 {
public static void printFile(File file) throws IOException {
//true表示在文本末尾添加数据,为false表示覆盖源文件内容
FileOutputStream fos = new FileOutputStream("D://1//log1.txt", true);
//如若文件夹不存在,则创建
File f1 = new File("D://1//");
if (!(f1.exists())) {
f1.mkdir();
}
//如若文件不存在,则创建
File f2 = new File("D://1//log1.txt");
if (!(f2.exists())) {
f2.createNewFile();
}
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files == null) {
return;
}
for (File file2 : files) {
byte[] bs = (file2.getAbsolutePath() + "\r\n").getBytes();
fos.write(bs);
printFile(file2);
}
}
fos.close();
}
public static void main(String[] args) throws IOException {
// 获取所有的根目录
long s = System.currentTimeMillis();
//遍历所有磁盘分区
/* File[] files = File.listRoots();
for (int i = 0; i < files.length; i++) {
try {
printFile(files[i]);
} catch (IOException e1) {
e1.printStackTrace();
}
}*/
printFile(new File("D://"));
long e = System.currentTimeMillis();
System.out.println("耗时"+(e - s) / 1000+"秒");
}
}
2.4BufferedInputStream
方法 | 描述 |
---|---|
BufferedInputStream(InputStream in) | 创建一个BufferedInputStream并保存其参数,输入流 in |
int available() | 返回从该输入流中可以读取(或跳过)的字节数的估计值 而不会被下一次调用此输入流的方法阻塞 |
int read() | 读取1字节文件 |
int read(byte[ ] b) | 读取b.length长度的字节数据 |
int read(byte[ ] b, int off, int len) | 从给定的偏移开始,将字节输入流中的字节读入指定的字节数组 |
void close() | 关闭此输入流并释放与流相关联的任何系统资源。 |
代码示例:
public static void main(String[] args) {
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
//定义读取对象
fis = new FileInputStream("D://1//2.txt");
//缓存输读取流包装输出读取的对象
bis = new BufferedInputStream(fis);
int i = 0;
//bis.available()判断文件可读取的字节数
byte[] bs = new byte[bis.available()];
while ((i = bis.read(bs)) > -1) {
// 将byte数组装换为String类型
String string = new String(bs);
System.out.println(string);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.5BufferedOutputStream
方法 | 描述 |
---|---|
BufferedOutputStream(OutputStream out) | 创建一个新的缓冲输出流,以将数据写入指定的底层输出流 |
void flush() | 刷新缓冲输出流 |
void write(int b) | 将指定的字节写入缓冲的输出流 |
void write(byte[] b) | 将b.length个字节从指定的字节数组写入此文件输出流 |
void write(byte[] b, int off, int len) | 从指定的字节数组写入len个字节, 从偏移 off开始到缓冲的输出流 |
代码示例:
public static void main(String[] args) {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
//定义写入对象
fos = new FileOutputStream("D:/1/3.txt",true);
//缓存输出流包装输出写入对象
bos = new BufferedOutputStream(fos);
String s = new String("路漫漫其修远兮,吾将上下而求索.");
//将字符串装换成Byte数组
byte[] bytes = s.getBytes();
//以bytes.length长度写入文件
bos.write(bytes);
//写入文件
//bos.write(bytes, 0, bytes.length);
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
} finally {
try {
bos.flush();
fos.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
InputStream is = null;
BufferedInputStream bis = null;
OutputStream os = null;
BufferedOutputStream bos = null;
try {
is = new FileInputStream("D://zl//myeclipse10.zip");
bis = new BufferedInputStream(is);
os = new FileOutputStream("D://1//2//1.zip");
bos = new BufferedOutputStream(os);
int i;
byte[] bs = new byte[1024 * 2];
long s = System.currentTimeMillis();
while ((i = bis.read(bs)) > -1) {
bos.write(bs);
}
long e = System.currentTimeMillis();
System.out.println("耗时" + (e - s) / 1000 + "s");
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
try {
bos.flush();
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.Reader和Writer
3.1FileReader
方法 | 描述 |
---|---|
FileReader(File file) | 创建一个新的 FileReader,给出 File读取。 |
FileReader(String fileName) | 创建一个新的 FileReader,给定要读取的文件的名称。 |
int read() | 读入单个字符 |
int read(char[ ] c) | 将c.length长度字符读入数组中 |
int read(char[ ] c, int offset, int length) | 从给定的偏移开始,将字符输入流中的字符读入指定的字符数组 |
void close() | 关闭此文件输出流并释放与此流相关联的任何系统资源 |
3.2FileWriter
方法 | 描述 |
---|---|
FileWriter(File file) | 给一个File对象构造一个FileWriter对象 |
FileWriter(String fileName) | 构造一个给定文件名的FileWriter对象 |
FileWriter(File file, boolean append) | 给一个File对象构造一个FileWriter对象 |
FileWriter(String fileName, boolean append) | 构造一个FileWriter对象, 给出一个带有布尔值的文件名,表示是否附加写入的数据 |
void write(int c) | 写一个字符 |
void write(char[] c) | 写入c.length长度的字符 |
void write(char[] c, int off, int len) | 写入字符的一部分 |
void write(String s, int off, int len) | 写入一个字符串的一部分 |
Write append(char c) | 文件末尾追加字符 |
void flush() | 刷新流 |
void close() | 关闭流,先刷新 |
代码示例:
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader(new File("D:/1/2/111.txt"));
FileWriter fw = new FileWriter(new File("D:/1/2.txt"));
int i = 0;
char[] cs = new char[1024];
while ((i = fr.read(cs)) > -1) {
// 读取文本信息
// System.out.println(new String(cs));
// 写入文件2.txt中
fw.write(cs, 0, cs.length);
}
fr.close();
fw.close();
}
3.3BufferedReader
方法 | 描述 |
---|---|
BufferedReader(Reader in) | 创建使用默认大小的输入缓冲区的缓冲字符输入流 |
int read() | 读一个字符 |
int read(char[ ] c) | 读入单个字符 |
int read(char[] c, int off, int len) | 将c.length长度字符读入数组中 |
String readLine() | 读一行文字 |
void close() | 关闭流并释放与之相关联的任何系统资源 |
3.4BufferWriter
方法 | 描述 |
---|---|
BufferedWriter(Writer out) | 创建使用默认大小的输出缓冲区的缓冲字符输出流 |
void write(int c) | 写一个字符 |
void write(char[] c) | 写入c.length长度的字符 |
void write(char[] c, int off, int len) | 写入字符数组的一部分 |
void write(String s, int off, int len) | 写一个字符串的一部分 |
Write append(char c) | 文件末尾追加字符 |
void newLine() | 写一行行分隔符 |
void flush() | 刷新流 |
void close() | 关闭流,先刷新 |
4.RandomAccessFile
该类的实例支持读取和写入随机访问文件。 随机访问文件的行为类似于存储在文件系统中的大量字节。 有一种游标,或索引到隐含的数组,称为文件指针 ; 输入操作读取从文件指针开始的字节,并使文件指针超过读取的字节。 如果在读/写模式下创建随机访问文件,则输出操作也可用; 输出操作从文件指针开始写入字节,并将文件指针提前到写入的字节。
方法 | 描述 |
---|---|
RandomAccessFile(File file, String mode) | 创建一个随机访问文件流从File参数指定的文件中读取,并可选地写入文件 |
RandomAccessFile(String name, String mode) | 创建随机访问文件流,以从中指定名称的文件读取,并可选择写入文件 |
int read() | 从该文件读取一个字节的数据 |
int read(byte[] b) | 从该文件读取最多b.length字节的数据到字节数 |
void write(int b) | 将指定的字节写入此文件 |
void write(byte[] b) | 从指定的字节数组写入b.length个字节到该文件,从当前文件指针开始 |
long length() | 返回此文件的长度。 |
void seek(long pos) | 设置文件指针偏移,从该文件的开头测量,发生下一次读取或写入 |
int skipBytes(int n) | 尝试跳过 n字节的输入丢弃跳过的字节 |
void close() | 关闭此随机访问文件流并释放与流相关联的任何系统资源 |
这两个构造方法均涉及到一个String类型的参数mode,它决定随机存储文件流的操作模式,其中mode值及对应的含义如下:
1.“r”:以只读的方式打开,调用该对象的任何write(写)方法都会导致IOException异常
2.“rw”:以读、写方式打开,支持文件的读取或写入。若文件不存在,则创建之。
3.“rws”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。这里的“s”表示synchronous(同步)的意思
4.“rwd”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。使用“rwd”模式仅要求将文件的内容更新到存储设备中,而使用“rws”模式除了更新文件的内容,还要更新文件的元数据(metadata),因此至少要求1次低级别的I/O操作
代码示例
package com.it.day2;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) {
try {
RandomAccessFile raf = new RandomAccessFile("D:/1/4.txt", "rw");
byte[] b = new byte[2];
int i;
raf.seek(raf.length());
int skipBytes = raf.skipBytes(4);
System.out.println(skipBytes);
while ((i = raf.read(b)) > -1) {
System.out.println(new String(b));
raf.write(100);
}
// String a = "天苍苍,野茫茫";
// raf.write(a.getBytes());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
5.对象序列化
-
序列化就是将对象的状态(对象的属性)存储到特定的存储介质中的过程, 也就是将对象状态转换为可保持或可传输格式的过程.
-
序列化的核心:1.保存对象的状态
2.对象状态可储存
-
-
反序列化则是从特定的存储介质中读取数据并重新构建成对象的过程
注意:Java中只有实现了java.io.Serializable接口的类的对象才能被序列化
5.1ObjectInputStream
方法 | 描述 |
---|---|
Object readObject(Object o) | 读取对象 |
5.2 ObjectOutputStream
方法 | 描述 |
---|---|
Object writeObject(Object o) | 序列化对象 |
5.3示例
/**
* 序列化
* @author MR.W
*
*/
public class Test {
public static void main(String[] args) throws IOException {
Student s1= new Student("方一凡", 18);
FileOutputStream fos = new FileOutputStream("D://s1.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//将内存中的对象保存到硬盘
oos.writeObject(s1);
}
}
/**
* 反序列化
* @author MR.W
*
*/
public class Test2 {
public static void main(String[] args) throws ClassNotFoundException, IOException {
FileInputStream fis = new FileInputStream("D://s1.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Student s = (Student) ois.readObject();
System.out.println(s.getName()+s.getAge());
}
}
代码示例:
package com.it.day2;
import java.io.Serializable;
/**
* 测试序列化与反序列化(注意:一个类要想序列化,必须实现Serializable接口)
* @author zl
* @parameter
* @return
* @version
*/
public class Student implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
private int age;
public Student(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
----------------------------------------------------------------------------------------
package com.it.day2;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* 测试序列化
* @author zl
* @parameter
* @return
* @version
*/
public class StudentTest1 {
public static void main(String[] args) {
Student s1 = new Student(1001, "张三", 20);
Student s2 = new Student(1002, "李四", 23);
Student s3 = new Student(1003, "赵武", 41);
Student s4 = new Student(1004, "小明", 22);
Student s5 = new Student(1005, "周八", 34);
List<Student> list = new ArrayList<Student>();
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
list.add(s5);
ObjectOutputStream oos = null;
FileOutputStream fos = null;
try {
fos = new FileOutputStream("D://1//s1.txt");
oos = new ObjectOutputStream(fos);
// 序列化集合对象
oos.writeObject(list);
// 序列化单个对象
// oos.writeObject(s1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
-----------------------------------------------------------------------------------------
package com.it.day2;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;
/**
* 测试反序列化
* @author zl
* @parameter
* @return
* @version
*/
public class StudentTest2 {
public static void main(String[] args) {
ObjectInputStream ois = null;
FileInputStream fis = null;
try {
fis = new FileInputStream("D://1//s1.txt");
ois = new ObjectInputStream(fis);
// 反序列化 集合 对象,并遍历输出
List<Student> list = (ArrayList<Student>) ois.readObject();
for (Student student : list) {
System.out.println(student.getId() + student.getName() + student.getAge());
}
// 反序列化单个对象,并输出
// Student student=(Student)ois.readObject();
// System.out.println(student.getId()+student.getName()+student.getAge());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6.DataInputStrean和DataOutputStream
-
DataInputStream(InputStream为父类)
数据输入流允许应用程序以独立于机器的方式从底层输入流读取原始Java数据类型。 应用程序使用数据输出流来写入稍后可以被数据输入流读取的数据。
方法 描述 DataInputStream(InputStream in) 创建使用指定的底层InputStream的DataInputStream。 int read(byte[] b) 从包含的输入流中读取一些字节数,并将它们存储到缓冲区数组 b int skipBytes(int n) 尝试跳过 n字节的输入丢弃跳过的字节 -
DataOutputStream(OutputStream为父类)
数据输出流使应用程序以便携式方式将原始Java数据类型写入输出流。 然后应用程序可以使用数据输入流来读取数据。
方法 描述 DataOutputStream(OutputStream out 创建一个新的数据输出流,以将数据写入指定的底层输出流 void write(int b) 将指定的字节(参数 b的低8位)写入底层输出流 int size() 返回计数器的当前值 written,
到目前为止写入此数据输出流的字节数
7.克隆(clone)
7.1浅复制(浅克隆)
(要实现浅克隆被克隆的类必须实现Cloneable接口)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
继承自java.lang.Object类的clone()方法是浅复制
7.2深复制(深克隆)
(要实现深克隆被克隆类以及被克隆类的引用必须实现Serializable接口)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。深克隆的实现实际上是对对象的序列化和反序列化.