1.File
1、File类的基本概念
File类:表示文件和目录路径名的抽象表示形式。
File类可以实现文件的创建、删除、重命名、得到路径、创建时间等等,是唯一与文件本身有关的操作类
2、File类的操作方法
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/**
* File类的使用
* @description
*/
public class FileDemo {
public static void main(String[] args) {
//File类表示一个文件或目录
// "C:\\test\\vince.txt"
//"C:/test/vince.txt"
File f1 = new File("c:"+File.separator+"test"+File.separator+"vince.txt");
if(!f1.exists()){ //判断文件是否存在
try {
f1.createNewFile(); //创建文件
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
//f1.isFile() :是否为文件
System.out.println("是否为文件夹:"+f1.isDirectory());
File f2 = new File("c:\\test\\my");
boolean b = f2.delete();
System.out.println(b);
String[] names = f2.list(); //列出当前目录下的所有文件名
System.out.println(Arrays.toString(names));
File[] fs = f2.listFiles();//列出当前目录下的所有文件,以file对象返回
for(File f: fs){
System.out.println("length="+f.length());
System.out.println("name="+f.getName());
System.out.println("相对路径="+f.getPath());
System.out.println("绝对路径="+f.getAbsolutePath());
System.out.println("是否为隐藏文件="+f.isHidden());
System.out.println("是否可读文件="+f.canRead());
Date date = new Date(f.lastModified());
DateFormat df = new SimpleDateFormat("HH:mm:ss");
System.out.println("文件最后修改的时间="+df.format(date));
System.out.println("---------");
}
//相对路径与绝对路径的区别
File f3 = new File("temp.txt");
System.out.println(f3.getPath());
System.out.println(f3.getAbsolutePath());
//
File f4 = new File("c:\\test\\dabin1");
f4.mkdirs();
//重命名与移动文件
//f4.renameTo(new File("c:\\test\\dabin1"));;
f4.renameTo(new File("c:\\dabin1"));
File f5 = new File("c:\\test\\my");
// File[] files = f5.listFiles(new FileFilter() {
// @Override
// public boolean accept(File pathname) {
// return pathname.getName().endsWith(".txt");
// }
// });
File[] files = f5.listFiles((pathname)->pathname.getName().endsWith(".txt"));
System.out.println("---------");
for(File f:files){
System.out.println(f.getName());
}
}
}
/**
* 在指定的目录中查找文件
* @description
*/
public class FileDemo2 {
public static void main(String[] args) {
findFile(new File("C:\\Users\\vince\\Downloads"),".jpg");
}
//查找文件的方法
private static void findFile(File target,String ext){
if(target==null)return;
//如果文件是目录
if(target.isDirectory()){
File[] files = target.listFiles();
if(files!=null){
for(File f: files){
findFile(f,ext);//递归调用
}
}
}else{
//此处表示File是一个文件
String name = target.getName().toLowerCase();
//System.out.println(name);
if(name.endsWith(ext)){
System.out.println(target.getAbsolutePath());
}
}
}
}
2.字节流
流:流是一组有顺序,有起点和终点的字节集合,是对数据传输的总称或抽象,即数据在设备间的传输成为流。
流的本质是数据传输。
字节流,默认每次执行写入操作会直接将数据写入文件
1、字节输出流
OutputStream类定义
public abstract class OutputStream extends Object implements Closeable, Flushable
此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到InputStream 类某个接收器
要向文件中输出,使用FileOutputStream类
2、字节输入流
定义:
public abstract class InputStream extends Object implements Closeable
此抽象类是表示字节输入流的所有类的超类。
FileInputStream 从文件系统中的某个文件中获得输入字节。
/**
* 字节输出输入流
* 输出流:超类 OutputStream,对文件的输出流使用子类FileOutputStream
* 输入流:超类InputStream,对文件的输入流使用子类FileInputStream
*
* 输入输出字节流操作原理,每次只会操作一个字节,(从文件中读取或写入 )
* 字节操作流,默认每次执行写入操作会直接把数据写入文件
* @author vince
* @description
*/
public class ByteStreamDemo {
private static void in(){
//0、确定目标文件
File file = new File("c:\\test\\vince.txt");
//1、构建 一个文件输入流对象
try {
InputStream in = new FileInputStream(file);
byte[] bytes = new byte[10];
StringBuilder buf = new StringBuilder();
int len = -1;//表示每次读取的字节长度
//把数据读入到数组中,并返回读取的字节数,当不等-1时,表示读取到数据,等于-1表示文件已经读完
while((len = in.read(bytes))!=-1){
//根据读取到的字节数组,再转换为字符串内容,添加到StringBilder中
buf.append(new String(bytes,0,len));
}
//打印内容:
System.out.println(buf);
//关闭输入流
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void out(){
//0、确定目标文件
File file = new File("c:\\test\\vince.txt");
//1、构建一个文件输出流对象
try {
OutputStream out = new FileOutputStream(file,true); //append 为true表示追加内容
//2、输出的内容
String info = "小河流水哗啦啦\r\n";// \r\n表示换行
//String line = System.getProperty("line.separator");//获取换行符
//3、把内容写入到文件
out.write(info.getBytes());
//4、关闭流
out.close();
System.out.println("write success.");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
out();
// in();
}
}
3.字符流
Writer
写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。但是,多数子类将重写此
处定义的一些方法,以提供更高的效率和/或其他功能。
与OutputStream一样,对文件的操作使用:FileWriter类完成。
Reader
用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,多数子类将重写
此处定义的一些方法,以提供更高的效率和/或其他功能。
使用FileReader类进行实例化操作。
/**
* 字符流:
* 字符输出流:Writer,对文件的操作使用子类:FileWriter
* 字符输入流:Reader,对文件的操作使用子类:FileReader
* 每次操作的单位是一个字符
* 文件字符操作流会自带缓存,默认大小为1024字节,在缓存满后,或手动刷新缓存,或关闭流时会把数据写入文件
*
* 如何选择使用字节流还是字符流:
* 一般操作非文本文件时,使用字节流,操作文本文件时,建议使用字符流
*
* 字符流的内部实现还是字节流
* @author vince
* @description
*/
public class CharStreamDemo {
private static void in(){
File file = new File("c:\\test\\vince.txt");
try {
Reader in = new FileReader(file);
char[] cs = new char[3];
int len = -1;
StringBuilder buf = new StringBuilder();
while((len=in.read(cs))!=-1){
buf.append(new String(cs,0,len));
}
in.close();
System.out.println(buf);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void out(){
File file = new File("c:\\test\\vince.txt");
try {
Writer out = new FileWriter(file,true);
out.write(",村花到我家");
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
out();
// in();
}
}
4.转换流
转换流,可以将一个字节流转换为字符流,也可以将一个字符流转换为字节流。
OutputStreamWriter:可以将输出的字符流转换为字节流的输出形式
InputStreamReader:将输入的字节流转换为字符流输入形式
/**
* 转换流
* OutputStreamWriter:可以将输出的字符流转换为字节流的输出形式
InputStreamReader:将输入的字节流转换为字符流输入形式
* @author vince
* @description
*/
public class ChangeStreamDemo {
private static void write(OutputStream out){
Writer writer = new OutputStreamWriter(out,Charset.defaultCharset());
try {
writer.write("开开心心来玩耍\r\n");
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void read(InputStream in){
Reader reader = new InputStreamReader(in,Charset.defaultCharset());
char[] cs = new char[1024];
int len = -1;
try {
while((len=reader.read(cs))!=-1){
System.out.println(new String(cs,0,len));
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws FileNotFoundException {
// InputStream in = new FileInputStream("c:\\test\\vince.txt");
// read(in);
OutputStream out = new FileOutputStream("c:\\test\\vince.txt");
write(out);
}
}
5.缓冲流
首先要明确一个概念:
对文件或其它目标频繁的读写操作,效率低,性能差。
使用缓冲流的好处是,能够更高效的读写信息,原理是将数据先缓冲起来,然后一起写入或者读取出来。
BufferedInputStream: 为另一个输入流添加一些功能,在创建 BufferedInputStream 时,会创建一个内部缓冲
区数组,用于缓冲数据。
BufferedOutputStream:通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次
字节写入调用底层系统。
BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
/**
* 缓存的目的:
* 解决在写入文件操作时,频繁的操作文件所带来的性能降低的问题,
* BufferedOutputStream 内部默认的缓存大小是8KB,每次写入时存储到缓存中的byte数组中,当数组存满时,会把数组中的数据写入文件,
* 并且缓存下标归零
*
* 字符流
* 1、加入字符缓存流,增强读取功能(readLine)
* 2、更高效的读取数据
* FileReader: 内部使用InputStreamReader( sun.nio.cs.StreamDecoder),解码过程,byte->char,默认缓存大小是8K
* BufferedReader:默认缓存大小是8K,但可以手动指定缓存大小,把数据进接读取到缓存中,减少每次转换过程,效率更高
* BufferedWriter 同上
*
* @author vince
* @description
*/
public class BufferStreamDemo {
private static void charWriter(){
File file = new File("c://test//vince.txt");
try {
Writer writer = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(writer);
bw.write("村花到我家");
bw.flush();
bw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void charReader(){
File file = new File("c://test//vince.txt");
try {
Reader reader = new FileReader(file);
//为字符流提供缓存,以达到高效读取的目的
BufferedReader br = new BufferedReader(reader);
char[] cs = new char[1024];
int len = -1;
while((len=br.read(cs))!=-1){
System.out.println(new String(cs,0,len));
}
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void byteReader2(){
File file = new File("c://test//vince.txt");
try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
byte[] bytes = new byte[1024];
int len = -1;
while((len=bis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void byteReader(){
File file = new File("c://test//vince.txt");
try {
InputStream in = new FileInputStream(file);
//构造一个字节缓冲流
BufferedInputStream bis = new BufferedInputStream(in);
byte[] bytes = new byte[1024];
int len = -1;
while((len=bis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
bis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void byteWriter(){
File file = new File("c://test//vince.txt");
try {
OutputStream out = new FileOutputStream(file);
//构造一个字节缓冲流
BufferedOutputStream bos = new BufferedOutputStream(out);
//
String info = "小河还是流水哗啦啦";
bos.write(info.getBytes());
bos.close();
//out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// byteWriter();
byteReader();
}
}
6、打印流
打印流的主要功能是用于输出,在整个IO包中打印流分为两种类型:
字节打印流:PrintStream
字符打印流:PrintWriter
打印流可以很方便的进行输出
/**
* 打印流:很方便的进行输出
*
* 字节打印流
* 在字节输出时,可以增强输出功能
* 字符打印流
*
* @author vince
* @description
*/
public class PrintStreamDemo {
private static void charPrint(){
File file = new File("c:\\test\\vince.txt");
try {
Writer out = new FileWriter(file);
//加缓存
BufferedWriter bos = new BufferedWriter(out);
//增强打印功能
PrintWriter pw = new PrintWriter(bos);
pw.println("小河流水天天哗啦啦");
pw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void bytePrint(){
File file = new File("c:\\test\\vince.txt");
try {
OutputStream out = new FileOutputStream(file);
//加缓存
BufferedOutputStream bos = new BufferedOutputStream(out);
//增强打印功能
PrintStream ps = new PrintStream(bos);
ps.println("小河流水天天哗啦啦");
ps.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// bytePrint();
charPrint();
}
}
7、对象流
对象流的两个类:
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
序列化一组对象:
在序列化操作中,同时序列化多个对象时,反序列化也必须按顺序操作,如果想要序列化一组对象该如何操作呢?
序列化一组对象可采用:对象数组的形式,因为对象数组可以向Object进行转型操作。
transient关键字:
如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class ObjectStreamDemo {
/**
* 对象序列化
* 把对象写入文件:实际写入的是类名、属性名、属性类型、属性的值等
*/
private static void writeObjects(){
Dog dog = new Dog("wangwang",2,"母");
Dog dog2 = new Dog("2哈",3,"公");
Dog[] dogs = {dog,dog2};
File file = new File("c:\\test\\dog.obj");
try {
OutputStream out = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(dogs);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 反序列化的过程
* 从文件中把对象的内容读取出来,还原成对象
*/
private static void readObject(){
File file = new File("c:\\test\\dog.obj");
try {
InputStream in = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(in);
Dog dog = (Dog)ois.readObject();
ois.close();
System.out.println(dog);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 对象序列化
* 把对象写入文件:实际写入的是类名、属性名、属性类型、属性的值等
*/
private static void writeObject(){
Dog dog = new Dog("wangwang",2,"母");
File file = new File("c:\\test\\dog.obj");
try {
OutputStream out = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(dog);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// writeObject();
readObject();
}
}
8、字节数组流
ByteArrayInputStream
包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。 关闭
ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
ByteArrayOutputStream
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用
toByteArray() 和 toString() 获取数据。 关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可
被调用,而不会产生任何 IOException。
@Override
protected Object clone() {
ByteArrayOutputStream bos=null;
ObjectOutputStream oos=null;
ByteArrayInputStream bis=null;
ObjectInputStream ois=null;
try {
//将对象写出去
bos=new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
bis=new ByteArrayInputStream(bos.toByteArray());
ois=new ObjectInputStream(bis);
return (Sheep)ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}finally {
try {
ois.close();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
9、数据流
DataInputStream:
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出
流写入稍后由数据输入流读取的数据。 DataInputStream 对于多线程访问不一定是安全的。 线程安全是可选
的,它由此类方法的使用者负责。
DataOutputStream:
数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将
数据读入。
/**
* 数据流
* 与机器无关的操作JAVA的基本数据类型
* @author vince
* @description
*/
public class DataStreamDemo {
private static void read(){
File file = new File("c:\\test\\vince.dat");
try {
InputStream in = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(in);
DataInputStream dis = new DataInputStream(bis);
int num = dis.readInt();
byte b = dis.readByte();
String s = dis.readUTF();
System.out.println(num+","+b+","+s);
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void write(){
File file = new File("c:\\test\\vince.dat");
try {
OutputStream out = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(out);
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(10); //写入4个字节
dos.writeByte(1);//写入1个字节
dos.writeUTF("中");
dos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// write();
read();
}
}
10、合并流、字符串流、管道流
一、合并流:
SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,
直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
文件分割
/**
* 文件的分割 targetFile 要分割的目标文件 cutSize 每个文件大小
*/
private static void cut(File targetFile, long cutSize) {
if (targetFile == null) {
return;
}
if (targetFile.length() == 0) {
return;
}
//切割文件的数量
long num = 0L;
if (targetFile.length() % cutSize == 0) {
num = targetFile.length() / cutSize;
} else {
num = targetFile.length() / cutSize + 1;
}
byte[] bytes = null;
long readNum =0L;
BufferedInputStream fileInputStream = null;
BufferedOutputStream fileOutputStream = null;
try {
fileInputStream = new BufferedInputStream(new FileInputStream(targetFile));
for (int i = 0; i < num; i++) {
if (cutSize <= 1024) {
bytes = new byte[(int) cutSize];
readNum = 1;
} else {
bytes = new byte[1024];
readNum = (int) cutSize / 1024;
}
fileOutputStream = new BufferedOutputStream(new FileOutputStream(new File("d:\\" + (i + 1) + "-" + targetFile.getName())));
int len = -1;
long readTime = readNum;
while (readTime > 0 & fileInputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes, 0, len);
readTime--;
fileOutputStream.flush();
}
//这里要注意,最后一次读取的bytes大小不能是1024 ,不然就读多了
if (cutSize % bytes.length != 0L) {
bytes = new byte[(int) (cutSize % bytes.length)];
len = fileInputStream.read(bytes);
if (len != -1) {
fileOutputStream.write(bytes, 0, len);
fileOutputStream.flush();
}
}
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件合并
public class SequenceInputStreamDemo {
/**
* 用SequenceInputStream 合并
* @param e
* @param fileName
* @throws IOException
*/
public static void merge(Enumeration<? extends InputStream> e,String fileName) throws IOException {
SequenceInputStream sequenceInputStream = new SequenceInputStream(e);
FileOutputStream fileOutputStream = new FileOutputStream(new File(fileName));
byte[] bytes = new byte[1024];
int len=-1;
while((len=sequenceInputStream.read(bytes))!=-1){
fileOutputStream.write(bytes,0,len);
fileOutputStream.flush();
}
fileOutputStream.close();
sequenceInputStream.close();
}
public static void main(String[] args) throws IOException {
FileInputStream fos1 = new FileInputStream(new File("d:\\1-01Linux操作系统介绍.mp4"));
FileInputStream fos2 = new FileInputStream(new File("d:\\2-01Linux操作系统介绍.mp4"));
FileInputStream fos3 = new FileInputStream(new File("d:\\3-01Linux操作系统介绍.mp4"));
FileInputStream fos4 = new FileInputStream(new File("d:\\4-01Linux操作系统介绍.mp4"));
FileInputStream fos5 = new FileInputStream(new File("d:\\5-01Linux操作系统介绍.mp4"));
FileInputStream fos6 = new FileInputStream(new File("d:\\6-01Linux操作系统介绍.mp4"));
FileInputStream fos7 = new FileInputStream(new File("d:\\7-01Linux操作系统介绍.mp4"));
Vector vector = new Vector();
vector.add(fos1);
vector.add(fos2);
vector.add(fos3);
vector.add(fos4);
vector.add(fos5);
vector.add(fos6);
vector.add(fos7);
merge(vector.elements(),"d:\\test.mp4");
}
}
二、字符串流
1、StringReader
其源为一个字符串的字符流。
2、 StringWriter
一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。 关闭 StringWriter 无效。此类中的方法在关
闭该流后仍可被调用,而不会产生任何 IOException。
三、管道流
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程
从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对
象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读
操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。
11、RandomAccessFile
RandomAccessFile是IO包的类,从Object直接继承而来。 只可以对文件进行操作,可以对文件进行读取和写入。
当模式为r是,当文件不存在时会报异常,当模式为rw时,当文件不存在时,会自己动创建文件,当文件已经
存在时 不会对原有文件进行覆盖。
RandomAccessFile有强大的文件读写功能,其内部是大型 byte[],可以通过seek(),getFilePointer()等方法操
作的指针,方便对数据进行写入与读取。还可以对基本数据类型进行直接的读和写操作。
RandomAccessFile的绝大多数功能,已经被JDK 1.4的nio的“内存映射文件(memory-mapped files)”给取代了,你
该考虑一下是不是用“内存映射文件”来代替RandomAccessFile了。