【JavaSE】之IO

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关键字。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gx1500291

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值