Java之I/O

Java I/O

核心掌握五个类(File、OutputStream、InputStream、Reader、Writer)一个接口(Serializable)

1.File文件操作类

File类既可以描述具体文件也可以描述文件夹,是唯一一个与文件本身操作(创建、删除、取得信息)有关的程序类。
产生File对象的构造方法:

public File(String pathName){}//根据文件绝对路径产生File对象
public File(URI uri){}//根据网络产生File对象

1.1常用操作方法

public boolean createNewFile(){}//创建新文件
public boolean exists(){}//判断文件是否存在
public boolean delete(){}//删除文件
//文件分隔符:File.separator

//使用范例
public class test {
    public static void main(String[] args) throws IOException {
        File file = new File("C:"+File.separator+"Users"+File.separator+
                "vsus"+File.separator+"Desktop"+File.separator+"TestIO.java");
        if(file.exists()){
            file.delete();
        }else
            file.createNewFile();
    }
}

1.2目录操作

public String getParent()//取得父路径
public File getParentFile()//取得父路径的File对象
public boolean mkdirs()//创建多级父目录(一次性创建多级不存在的父目录)


//使用范例
public class test {
    public static void main(String[] args) throws IOException {
        File file = new File("C:"+File.separator+"Users"+File.separator+
                "vsus"+File.separator+"Desktop"+File.separator+"www"+File.separator+"bit"+File.separator+"TestIO.java");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        if(file.exists()){
            file.delete();
        }else
            file.createNewFile();
    }
}

1.3取得文件信息

public boolean isFile()//判断File对象是否为文件
public boolean isDirectory()//判断File对象是否为文件夹
public long length()//取得文件大小-字节为单位
public long lastModified()//取得上次修改时间


//使用范例
public class test {
    public static void main(String[] args) throws IOException {
        File file = new File("C:"+File.separator+"Users"+File.separator+
                "vsus"+File.separator+"Desktop"+File.separator+"www"+File.separator+"bit"+File.separator+"TestIO.java");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        if(file.exists()&&file.isFile()){
            System.out.println("文件大小为:"+file.length()/1024+"kb");
            System.out.println("上次修改时间:"+file.lastModified());
        }
    }
}

1.4列出目录中全部组成

pubic File[] listFiles()
//这个方法只能列出本目录中的第一级信息,
//如果要求列出目录中所有级信息,必须自己处理

public class IO {
    public static void main(String[] args) {

        File file = new File("C:"+File.separator+"Users"+File.separator+
                "vsus"+File.separator+"Desktop");
        listAllFiles(file);
    }
    // 一个目录下的全部文件
    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);
                }
            }
        }
    }
}

2.字节流与字符流

java.io包中流分为两类:输入流和输出流
字节流:InputStream、OutputStream(byte)
——原生操作,无需转换,可以处理文本、文件、图像、音乐、视频等资源

字符流:Reader、Writer(char)
——经过处理后的操作,只能处理中文文本。

流模型的操作流程:
1.取得终端对象
2.根据终端对象取得输入输出流
3.根据输入输出流进行数据读取与写入
4.关闭流(IO操作属于资源操作,所有资源操作(IO操作、数据库操作、网络)最后必须要进行关闭)

2.1字节输出流(OutPutStream)

public abstract class OutputStream implements Closeable,Flushable
OutputStream类实现了两个接口,这两个接口中的方法:

public void close() throws IOException
public void flush() throws IOException

核心方法:

  1. 将给定的字节数组内容全部输出:public void write(byte b[]) throws IOException
  2. 将部分字节数组内容输出:public void write(byte b[], int off, int len) throws IOException
  3. 输出单个字节:public abstract void write(int b) throws IOException;

使用OutputStream输出数据时,若指定文件不存在,FileOutputStream会自动创建文件(不包括创建目录),使用FileOutputStream输出内容时,默认为文件内容的覆盖,若要进行文件内容追加,使用如下构造:public FileOutputStream(File file,boolean append)
JDK1.7提供了AutoCloseable自动关闭接口,要使用此接口必须使用try-catch块(不推荐使用)

public class test {
    public static void main(String[] args) throws IOException {
        File file = new File("C:"+File.separator+"Users"+File.separator+
                "vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }

            OutputStream outputStream = new FileOutputStream(file,true);
            String msg = "ghw";
            outputStream.write(msg.getBytes());
            outputStream.close();
    }
}

2.2字节输入流(InputStream)

public abstract class InputStream implements Closeable

核心方法

1.public int read(byte b[]) throws IOException
2.pubic int read(byte b[],int off,int len) throws IOException
3.public abstract int read() throws IOException
方法1返回值的三种情况:

读取数据到字节数组中,返回数据的读取个数。如果此时开辟的字节数组大小大于读取的数据大小,则返 回的就是读取个数;如果要读取的数据大于数组的内容,那么这个时候返回的就是数组长度;如果没有数据了还在读,则返回-1

public class test {
    public static void main(String[] args) throws IOException {
        File file = new File("C:"+File.separator+"Users"+File.separator+
                "vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt");
        if (file.exists()){
            InputStream in = new FileInputStream(file);
            byte [] bytes = new byte[1024];
            int len = in.read(bytes);
            //将字节数组转为String
            String str = new String (bytes,0,len);
            System.out.println("读取内容为:"+str);
            in.close();
        }
    }
}

2.3 字符输出流Writer

public abstract class Writer implements Appendable,Closeable,Flushable
在Writer类中也提供了write()方法,而且该方法接收的类型都是char型,要注意的是,Writer类提供了一个直接输出字符串的方法:
public void write(String str)throws IOException
如果要操作文件使用FileWriter子类。

public class test {
    public static void main(String[] args) throws IOException {
        File file = new File("C:"+File.separator+"Users"+File.separator+
                "vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt");
        if (!file.getParentFile().exists()){
            file.mkdirs();
        }
        String msg = "hello bit";
        Writer writer = new FileWriter(file);
        writer.write(msg);
        writer.close();
    }
}

Writer类的结构与方法的使用与OutputStream非常相似,只是Writer类对于中文的支持很好并且提供了直接写入 String的方法而已。
未关闭流时,数据在缓存区存放,不会输出到目标终端,要想输出,要么关闭流,要么使用flush()强制刷新。

2.4 字符输入流(Reader)

!!!Reader类中没有方法可以直接读取字符串类型,这个时候只能通过字符数组进行读取操作。

public class test {
    public static void main(String[] args) throws IOException {
        File file = new File("C:"+File.separator+"Users"+File.separator+
                "vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt");
        if(file.exists()){
            Reader in = new FileReader(file);
            char [] data = new char[1024];
            //将数据读取到字符数组中
            int len = in.read(data);
            String str = new String (data,0,len);
            System.out.println("读取内容为:"+str);
            in.close();
        }
    }
}

3.转换流(字节流——>字符流)

3.1基本使用

OutputStreamWriter:将字节输出流变为字符输出流
InputStreamReader:将字节输入流变为字符输入流

这两类流的继承关系以及构造方法:

public class OutputStreamWriter extends Writer
public OutputStreamWriter(OutputStream out)

public class InputStreamReader extends Reader
public InputStreamReader(InputStream in)

字符流的具体子类大都是通过转换流将字节流转为字符流的。

3.2文件拷贝

public class FileCopy {
    public static void main(String[] args) throws Exception {
        //源路径&目标路径
        String sourcePath = "C:"+File.separator+"Users"+File.separator +
                "vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt";
        String destPath = "C:"+File.separator+"Users"+File.separator +
                "vsus"+File.separator+"Desktop"+File.separator+"Testcopy.txt";
        copyFile(sourcePath,destPath);
    }
    public static void copyFile(String sourcePath,String destPath) throws Exception {
        //1.获取file对象
        File sourcefile = new File(sourcePath);
        File destfile = new File(destPath);
        //2.取得输入输出流
        InputStream in = new FileInputStream(sourcefile);
        OutputStream out = new FileOutputStream(destfile);
        //根据输入输出流操作数据
        int len = 0;
        byte [] data = new byte[1024];
        len = in.read(data);
        out.write(data);
        //4.关闭流
        in.close();
        out.close();
    }
}

4.字符编码

4.1常用字符编码

1.GBK,GB2312:GBK包含简体与繁体中文,而GB2312只包含简体中文(这两种编码都是描述中文的编码)
2.UNICODE:java提供的16进制编码,可以描述世界上任意的文字信息,但编码进制数太高,编码体积较大,故会造成网络传输的负担。
3.ISO-8859-1:国际通用编码,不支持中文,浏览器默认编码
4.UTF编码:结合UNICODE与ISO-8859-1,最常用的就是UTF-8编码。

4.2乱码产生原因

大部分都是由于编解码不一致造成的,极少个别是由于数据丢失造成。

5.内存操作流程

需要进行IO处理,但是又不希望产生文件,这种情况下就可以使用内存作为操作终端。内存流分为两类:
字节内存流:ByteArrayInputStream/ByteArrayOutputStream
字符内存流:CharArrayReader/CharArrayWruter

构造方法:

//将指定的字节数组内容存放到内存中
public ByteArrayInputStream(byte buf[])
 
public ByteArrayOutputStream()
//内存流实现小写转大写
import java.io.*;

public class IOTouppercase {
    //利用内存流实现转大写操作
    public static void main(String[] args) throws Exception {
        String msg = "hellobit";
        ByteArrayInputStream in = new ByteArrayInputStream(msg.getBytes());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int len = 0;
        while ((len=in.read())!=-1){
            out.write(Character.toUpperCase(len));
        }
        System.out.println(out);
        in.close();
        out.close();
    }
}

6.打印流(输出流的强化版本)

字节打印流:PrintStream
字符打印流:PrintWriter

//范例:自己设计一个简单打印流

public class PrintUtil {
    private OutputStream outputStream;

    public PrintUtil(OutputStream outputStream) {
        this.outputStream = outputStream;
    }
    public void print(String str)  {
        try {
            this.outputStream.write(str.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void println(String str){
        this.print(str+"\n");
    }
    public void print(int data){
        this.print(String.valueOf(data));
    }
    public void println(int data){
        this.print(data+"\n");
    }
    public void close(){
        try {
            this.outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  }

打印流的设计属于装饰设计模型——基于抽象类
特点: 核心依然是某个类(OutputStream提供的write方法)的功能。但是为了得到更好的操作效果,让其支持的功能更多一些,使用装饰类(PrintStream)。
优点: 很容易更换装饰类来达到不同的操作效果。
缺点: 造成类结构复杂

7.System类对IO的支持

标准输出(显示器):System.out
标准输入(键盘):System in
错误输出:System.err

7.1系统输出

系统输出一共有两个常量:out、err,且这两个常量表示的都是PrintStream类的对象。

由于System.out是PrintStream的实例化对象,而PrintStream又是OutputStream的子类,所以可以直接使用 System.out直接为OutputStream实例化,这个时候的OutputStream输出的位置将变为屏幕。


public class test {
    public static void main(String[] args) throws IOException {
        OutputStream out = System.out;
        out.write("hello".getBytes()); 
    }
}

7.2系统输入

System.in是InputStream的直接对象

//范例:使用System.in实现数据读入
public class test {
    public static void main(String[] args) throws IOException {
        InputStream in = System.in;
        byte []data = new byte[1024];
        System.out.println("请输入内容....");
        int len = in.read(data);
        System.out.println("输出内容为"+new String(data,0,len));
        in.close();
    }
}

8.两种输入流

8.1BufferedReader类

核心方法:String readLine () throws IOException
这个方法可以直接读取一行数据(以回车为换行)

//使用BufferedReader实现键盘输入
public class TestPrint {   
	public static void main(String[] args) throws Exception {   
		BufferedReader buf = new BufferedReader(
							new InputStreamReader(System.in)) ;      
		System.out.println("请输入信息 :") ;   
		// 默认的换行模式是BufferedReader的大缺点  
		String str = buf.readLine() ;
		 // 默认使用回车换行    
		System.out.println("输入信息为:" + str );   		 			
		} 
}

8.2java.util.Scanner类

在这个类中主要关注以下方法:

  1. 判断是否有指定类型数据:public boolean hasNextXxx()
  2. 取得指定类型的数据:public 数据类型 nextXxx()
  3. 定义分隔符:public Scanner useDelimiter(Pattern pattern)
  4. 构造方法:public Scanner(InputStream source)
//使用Scanner实现数据输入
public class test {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入内容....");
        if (scanner.hasNext()){
            System.out.println("输入内容为"+scanner.next());
        }
        scanner.close();
    }
}


//接收各种数据类型
public class test {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入内容....");
        if (scanner.hasNextInt()){
            System.out.println("输入内容为"+scanner.nextInt());
        }else
            System.out.println("输入的不是数字");
        scanner.close();
    }
}

9.序列化

9.1概念

定义: 将内存中保存的对象变为二进制流进行输出或保存在文本中。
要想让类支持序列化,必须实现Serializable接口,Serializable接口为标识接口。只有实现了Serializable接口的类才具备对象序列化的功能。

9.2序列化与反序列化

要想实现序列化与反序列化的对象操作,在java.io包中提供有两个处理类:ObjectOutputStream、ObjectInputStream

序列化:ObjectOutputStream
核心方法:writeObject(Object obj),将obj变为二进制流输出到目标终端

反序列化:ObjectInputStream
核心方法:readObject():Object,将二进制流反序列化为对象

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 test {
    public static   File file = new File("C:"+File.separator+"Users"
            +File.separator+"vsus"+File.separator+"Desktop"+File.separator+"test.txt");
    public static void main(String[] args) throws Exception {
       Person person = new Person("zhangsan",27);
       Ser(person);
    }
    public static void Ser(Object obj) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new  FileOutputStream(file));
        oos.writeObject(obj);
        oos.close();
    }
        public static void dSer(Object obj)throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        System.out.println(ois.readObject());
        ois.close();
    }
}

9.3transient关键字

若希望类中若干属性不被序列化,可以在属性前添加transient关键字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值