JavaIO—File输入输出流、打印流、Java.util.Scanner类、装饰设计模式及序列化
IO基于抽象类。
File文件操作类(字节输入输出流、字符输入输出流)
字符编码
转换流
内存流
打印流
System对IO类的支持
两种输入流
Java.util.Scanner类
序列化
File文件操作类
在Java.io包中,File类是唯一一个与文件本身操作(创建、删除、获取信息等)有关的程序类。
File类不包括文件内容,它是文件本身,文件的读取与写入需要使用输入输出流。
1.1File类的使用–文件/文件夹
文件:
//File类源码
public class File implements Serializable, Comparable<File>{
}
由源码可得File类是Java.io包中的一个普通类,我们可以直接对其实例化对象。实例化对象可用到以下构造方法:
1.public File(String pathname){
};//根据文件的绝对路径产生File对象
创建一个新文件:
public boolean createNewFile() throws IOException {
}//根据绝对路径创建新文件
删除已有文件:
public boolean delete() {
}//删除已存在文件
判断一个文件是否存在:
public boolean exists() {
}//判断指定路径文件是否存在
判断是否为文件:
public boolean isFile() {
}
路径分隔符:出现原因是在Windows下路径分隔符通常为“//”,linux操作系统下通常为"/".故使用路径分隔符可更好的达到跨平台性。
public static final String separator = "" + separatorChar;
//使用时为File.separator(因separator在File类中为静态属性可通过类名直接调用)
若为文件即可获得文件大小:
public long length() {
}//获得当前路径下的文件大小(字节)通常使用时/1024(KB)
获取文件最新修改时间:
public long lastModified() {
}//获得当前路径文件最新修改时间,但要结合Date类使用,否则直接调用得到的是从1970年1月1日至文件最新修改时间的差值(无意义)
对以上方法的简单实用:
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test{
public static void main(String[] args) throws Exception {
//在桌面查找名称为lala.jpg的文件
File file=new File("C:"+File.separator+"Users"
+File.separator+"14665"+File.separator+"Desktop"+File.separator+"lala.jpg");
//判断当前路径下文件是否存在,不存在就创建
if(!file.exists()){
file.createNewFile();
}
//获取文件大小
System.out.println(file.length()/1024);
//获得文件最新修改时间(三种方法)
//1
System.out.println(file.lastModified());
//2
System.out.println(new Date(file.lastModified()));
//3
Date date=new Date(file.lastModified());
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(simpleDateFormat.format(date));
}
}
文件夹(目录):
创建目录(一次性创建多级不存在的父路径):
public boolean mkdirs() {
}
取得父路径/父路径File对象:
public String getParent(){
};//获取父路径
public File getParentFile(){
};//获得父路径File对象
判断是否为文件夹:
public boolean isDirectory() {
}
获得当前目录下所有文件:
public File[] listFiles() {
}//但直接调用该方法只能得到当前路径下的文件及目录,若想进一步得到该路径下所有目录的文件就需采用递归方法
创建目录方法简单使用:
import java.io.*;
public class Test{
public static void main(String[] args) throws Exception {
//在桌面创建新目录
File file=new File("C:"+File.separator+"Users"
+File.separator+"14665"+File.separator+"Desktop"+File.separator
+ "www"+File.separator+"ss"+File.separator+"hello.txt");
//判断该文件夹是否存在
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
//若该处为file.mkdirs()那么hello.txt也会被创建为文件夹
}
if(file.exists()){
file.delete();
}else {
file.createNewFile();
}
}
}
查找桌面路径下所有文件:
import java.io.*;
public class Test{
public static void main(String[] args) throws Exception {
File file=new File("C:"+File.separator+"Users"
+File.separator+"14665"+File.separator+"Desktop");
//测试所需时间
long start=System.currentTimeMillis();
listAllFiles(file);
long end=System.currentTimeMillis();
System.out.println("共耗时:"+(end-start)+"毫秒");
}
public static void listAllFiles(File file){
if(file.isFile()){
//递归出口(若为文件直接输出)
System.out.println(file);
}else{
if(file.exists()&&file.isDirectory()){
//判断文件是否存在且是否为文件夹
File[] files=file.listFiles();
for(File file1:files){
//对文件夹递归
listAllFiles(file1);
}
}
}
}
}
//924毫秒
对此我们可以看到只是查找桌面就耗时较多,那么查找C盘呢?时间会更久。出现这种情况的原因是主线程堵塞,因所有程序运行都在主线程中,如果listAllFiles()方法没有完成,那么main后续的执行将无法完成。这种情况造成了主线程堵塞,故对此我们可以新建立一个线程对其优化。
import java.io.*;
public class Test{
public static void main(String[] args) throws Exception {
File file=new File("C:"+File.separator+"Users"
+File.separator+"14665"+File.separator+"Desktop");
//将IO操作放在子线程中进行
new Thread(()->{
long start=System.currentTimeMillis();
listAllFiles(file);
long end=System.currentTimeMillis();
System.out.println("共耗时:"+(end-start)+"毫秒");
}).start();
System.out.println("主线程结束");
}
public static void listAllFiles(File file){
if(file.isFile()){
System.out.println(file);
}else{
if(file.exists()&&file.isDirectory()){
File[] files=file.listFiles();
for(File file1:files){
listAllFiles(file1);
}
}
}
}
}
一般来说,将IO操作放置子线程中进行。原因是这样IO操作就不影响主线程,且安卓开发中IO操作必须放在子线程中运行否则错误,虽然java中IO操作放置主线程中也可正常运行,但为了更好的跨平台性我们将IO操作放置子线程中运行。
1.2字节流与字符流
我们知道File类只与文件本身有关,若想进行文件读取或写入必须使用输入输出流。在Java.io包中,流分为字节流与字符流:
1.字节流:输入流:InputStream,输出流:OutputStream(均为抽象类)
public abstract class InputStream implements Closeable {
}//实现资源关闭流接口
Closeable(资源关闭流接口):public interface Closeable extends AutoCloseable {
}//资源关闭流接口继承自动关闭流接口
AutoCloseable(自动关闭流):public interface AutoCloseable {
}
//实现资源关闭流接口与强制刷新缓冲区接口
public abstract class OutputStream implements Closeable, Flushable {
}
Flushable(强制刷新缓冲区):public interface Flushable {
}
2.字符流:输入流:Reader,输出流:Writer
public abstract class Reader implements Readable, Closeable {
}
public interface Readable {
}
//Attempts to read characters into the specified character buffer.
public abstract class Writer implements Appendable, Closeable, Flushable {
}
public interface Appendable {
}
//Appends the specified character sequence to this <tt>Appendable</tt>.
字节输出流(从程序中向文件中写入数据)OutputStream:
OutputStream类中其他常用方法:
1.public void write(byte b[]) throws IOException {
}//将给定字节数组内容全部输出(直接输出到终端(文件、网络、内存中,不存在缓冲区))
2.public void write(byte b[], int off, int len) throws IOException {
}//将部分字节数组内容输出(将给定字节数组从off位置开始输出len长度后停止)
3.public abstract void write(int b) throws IOException;//输出单个字节
我们知道OutputStream类为抽象类不可直接实例化对象,故要想实例化必须使用子类。如果要进行文件操作,可以使用FileOutputStream类来处理:
1.public FileOutputStream(String name) throws FileNotFoundException {
}//覆写
2.public FileOutputStream(String name, boolean append)throws FileNotFoundException{
}//叠加
方法简单操作:
import java.io.*;
public class Test{
public static void main(String[] args) throws Exception {