File
常见文件操作
File file = new File("."+File.separator+"demo.txt"); //获取文件
String name=file.getName(); //获取文件名称
long size = file.length(); //单位时字节
long lasttime = file.lastModified(); //最后修改时间
boolean isFile= file.isFile();
boolean isDir = file.isDirectory();//是否目录
boolean isFile = file.isFile();//是否文件
boolean isHidden =file.isHidden(); //是否隐藏文件
boolean cr = file.canRead();
boolean cw = file.canWrite();
boolean ce = file.canExecute(); //是否可运行
file.delete(); //删除文件
f.exists(); //判断文件是否存在
f.mkdirs() //创建多级文件
为了解决系统差异导致的"/"问题,在Java中File.separator代替“/”
使用delete();删除一个目录前提是目录为空。
- 遍历目录
File f = new File(".");
if(f.isDirectory()) {
File[] subs= f.listFiles(); //返回数组
for(File sub:subs) {
System.out.println(sub);
}
}
- 递归删除
public static void main(String[] args) {
File dir = new File("a");
delete(dir);
}
public static void delete(File file) {
if(file.isDirectory()) {
file.delete();
File[] subs = file.listFiles();
for(File sub:subs) {
delete(sub);
}
}
file.delete();
}
使用重载的listFiles方法,需要传入一个额外的文件过滤器。文件过滤器是一个接口:FileFilter
public static void main(String[] args) {
File dir = new File(".");
File[] subs = dir.listFiles(
new FileFilter() {
public boolean accept(File f) {
// TODO 自动生成的方法存根
return f.getName().startsWith(".");
}
});
for(File sub:subs) {
System.out.println(sub.getName());
}
}
RandomAccessFile类
java.io.RandomAccessFile用来读写文件数据
RAF是基于指针进行读写的,即RAF总在指针指向的位置进行读写字节,并且读写后指针会自动向后移动.
RAF即可读取文件数据也可以向文件写入数据
RandomAccessFile f = new RandomAccessFile("test.txt", "rw");
- 两种模式
rw:读写
r:只读
字节数组复制文件算法
public static void main(String[] args) {
try {
RandomAccessFile desc =new RandomAccessFile("英雄1.mp3","rw");
RandomAccessFile m =new RandomAccessFile("周杰伦 - 英雄.mp3","r");
long start = System.currentTimeMillis();
byte[] buf = new byte[10*1024];
int len =-1;
while( (len=m.read(buf))!=-1) {
desc.write(buf,0,len);
}
long end = System.currentTimeMillis();
System.out.println("复制完成 ,耗时:"+(end-start)+"ms");
m.close();
desc.close();
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
seek(); 操作指针
IS与IO
概念
-
输入:用来读数据
-
输出:用来写数据
-
节点流:可以从或向一个特定的地方(节点)读写数据
-
处理流:对一个已存在的流连接和封装,通过封装的流的功能调用实现数据读写。
-
处理流的对象总要带一个其他流对象做参数。一个流对象经过其他流的多次包装,称为流的连接。
-
通常节点流程为低级流。
-
通常处理流也称为高级流或过滤流。
-
读写一定要有低级流,可以没有高级流
-
引入其他流的目的是简化读写数据中的操作
IS和OS常用方法
- InputStrema是所有字节输入流的父类,其定义了基础的读写方法,如下:
--int read()
以intd的形式返回,该int值的“第八位”有效,若返回值为-1则表示EOF
--int read(byte[] d)
尝试最多读取给顶数组的lenght个字节并存入数组,返回值为实际读取到的字节量。
- OutputStream是所有字节输出流的父类,其定义了基础的写出方法,如下:
--void write(int d)
写出一个字节,写的是给定的int的“第八位”
--void write(byte[] d)
将给定的字节数组中的所有字节全部写出。
文件流
创建FOS对象(重写模式)
-
FileOutStream是文件的字节输出流,我们使用该流可以以字节为单位将数据写入文件。
-
构造方法:
--FileOutStream(File file):
创建一个指向File对象表示的文件写出数据的文件输出流。
--FileOutStream(String filename):
创建一个指向具有指定名称的文件中写出数据的文件输出流。
如果指定文件已经存在,那么当使用FOS对其写入数据时,会清空原文件
在创建FOS时,若指定第二个参数,并且该值为true时,则时追加操作,追加到末尾。
文件流写入
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("fos.txt",true);//没有第二个参数则是直接覆盖
String str = ",加油,冲冲冲";
byte[] date = str.getBytes("utf-8");
fos.write(date);
System.out.println("写出完毕!!");
fos.close();
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
文件流读取
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("fos.txt");
byte[] date = new byte[100];
int len = fis.read(date);
String str = new String(date,0,len,"utf-8");
System.out.println(str);
fis.close();
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
缓冲流
public static void main(String[] args) {
try {
FileInputStream src = new FileInputStream("E:\\电影\\毒液-致命守护.mp4");
FileOutputStream desc = new FileOutputStream("毒液.mp4");
BufferedInputStream chu = new BufferedInputStream(src);//文件流
BufferedOutputStream ru = new BufferedOutputStream(desc);//文件流
long start = System.currentTimeMillis();
System.out.println("开始复制···");
int d = -1;
while((d=chu.read())!=-1){
ru.write(d);
}
chu.close();
ru.close();
long end = System.currentTimeMillis();
System.out.println("复制完毕,耗时:"+(end-start)+"ms");
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
- 缓冲流内部有一个缓冲区,即一个字节数组,缓冲流依靠提高每一次读写的数据量来减少读写次数来达到提高读写效率的目的
对象流
输入流
-
对象流是一种高级流,作用是方便读写Java中的对象。
-
java.io.ObjectOutputStream
-
对象输出流,可以将给定的对象转换为一组字节后写出。
public static void main(String[] args) {
Person p = new Person();
p.setName("田建华");
p.setAge(22);
p.setGender("男");
List<String> otherInfo = new ArrayList<String>();
otherInfo.add("一位java初学者");
otherInfo.add("痴迷于技术");
p.setOtherinfo(otherInfo); ![image](https://note.youdao.com/favicon.ico)![二个大概](https://note.youdao.com/favicon.ico)
try {
FileOutputStream fos = new FileOutputStream("JL.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(p); //对象流写入操作
oos.close();
System.out.println("已完成");
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
将对象转换为一组字节的过程称为:对象序列化
将对象转换的字节写入到硬盘的过程称为:对象持久化
输出流
-
对象输出流,左右时可以进行反序列化,读取一组字节并还原为对象
-
OIS读取的字节必须是由OOS将对象序列化得到的字节,否侧会抛出异常
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("JL.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
Person p = (Person)ois.readObject();
System.out.println(p);
ois.close();
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
- 不需要持久化的对象可以用关键字 transient (短暂的,路过的)进行描述如下:
private String name;
private int age;
private String gender;
private transient List<String> otherinfo; //transient 修饰的属性创建对象流时跳过
- 版本号
private static final long serialVersionUID = 1L;
版本号影响反序列化的结果,只有版本号一只反序列化操作才能成功,若版本号一致,内容不一样则会以兼容模式还原类
Reder和Writer
字符流原理
-
Reder是字符输入流的父类
-
Writer是字符输出流的父类
-
字符流是以字符为单位读写数据。一次处理一个Unicode。
-
字符流的底层仍然是基本的字节流。
常用方法:
- Reaer的常用方法:
--int read():读取一个字符,返回的int值“底16位”有效
字符转换流原理
-
字符流的读写单位为字符
-
字符流都是高级流,虽然以字符为单位。但底层还是读写字节,只是从字符转换成字节的工作交给了字符流来完成。
写
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("osw.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
osw.write("世界这么大,");
osw.write("我要去看看!");
osw.close();
System.out.println("写入完毕");
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
读
public static void main(String[] args) {
try {
FileInputStream du = new FileInputStream("osw.txt");
InputStreamReader dl = new InputStreamReader(du,"utf-8");
int d = -1;
while((d=dl.read())!=-1) {
System.out.print ((char)d);
}
dl.close();
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
- 大多数的字符流都只处理其他字符流,而低级流又是字节流,因此需要用上述两种流先进行转换,再用其他高级流处理
缓冲字符流
-
其特点是可以按行读写字符串
-
创建一个PrintWriter时,它一定会在内部创建BufferedWriter作为缓冲功能的叠加
-
提供多种构造方法,其中有两个可以直接对文件进行读写的方法:
PrinterWriter(File file);
PrinterWriter(String path);
PrintWriter也提供了可以处理其他流的构造方法,提供的方法可以提供字节流,亦可以处理字符流,并且,当前使用这类构造方法时,可以在传入第二个参数,该参数位boolean值,该值为true时,则具有了自动刷新功能。
- 记事本案例
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入文件名");
String fileName = scanner.nextLine();
try {
FileOutputStream fos = new FileOutputStream(fileName);
OutputStreamWriter osw = new OutputStreamWriter(fos);
PrintWriter pw = new PrintWriter(osw,true);
System.out.print("请您开始输入内容:");
String line = null;
while(true) {
line =scanner.nextLine();
if("exit".equals(line)) {
System.out.println("再见");
break;
}
pw.println(line);
}
pw.close();
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
- BuferedReader提供了按行读取的方法:String readLine()
连续读取若干个字符,直到读取到换行符为止,包括换行符;返回值为字符串,如返回值为UNLL则表示读到末尾
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("note.txt");//低级流
InputStreamReader isr = new InputStreamReader(fis);//字符流
BufferedReader br = new BufferedReader(isr); //字符缓冲流
String line = null;
while((line=br.readLine())!=null) {
System.out.println(line);
}
br.close();
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}