第十一章 Java IO编程

第十一章 Java IO编程

11.1 文件操作类:File

java.io包中,如果要进行文件自身操作(创建,删除),只能依靠java.io.File类完成。

NO.方法类型描述
1public File(String pathname)构造传递完整文件操作路径
2public File(File parent,String child)构造设置父路径与子文件路径
3public boolean createNewFile() thorws IOException普通创建新文件
4public boolean exists()普通判断给定路径是否存在
5public boolean delete()普通删除指定路径的文件
6public File getParentFile()普通取得当前路径的父路径
7public boolean mkdirs()普通创建多级目录
8public long length()普通取得文件大小,以字节为单位返回
9public boolean isFile()普通判断给定路径是否是文件
10public boolean isDirectory()普通判断给定路径是否是目录
11public long lastModified()普通取得文件的最后一次修改日期时间
12public String[] list()普通列出指定目录中的全部内容
13public File[] listFiles()普通列出所有的路径以File类对象包装

文件基本操作

public class TestDemo {
    public static void main(String[] args) throws Exception {
        File file=new File("d:\\test.txt");
        if (file.exists()){
            file.delete();
        }else {
            System.out.println(file.createNewFile());
        }
    }
}

在Windows系统下,使用\\做分隔符,如果程序运行在Linux系统中,则路径的分隔符为/。

为此java中提供了一个路径分隔符常量:public static final String separator

​ File file=new File(“d:+File.separator+test.txt”);

创建带路径的文件

public class TestDemo {
    public static void main(String[] args) throws Exception {
        File file =new File("d:"+File.separator+"demo"+File.separator+"test.txt");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        System.out.println(file.createNewFile());
    }
}

取得文件或目录的信息

package com.company;
import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
public class TestDemo {
    public static void main(String[] args) throws Exception {
        File file=new File("d:"+File.separator+"DG5421239_x86.zip");
        if (file.exists()){
            System.out.println("是否是文件:"+(file.isFile()));
            System.out.println("是否是目录:"+(file.isDirectory()));
            //文件大小是按照字节单位返回的数字,所以需要字节单元转换为兆的单元
            System.out.println("文件大小:"+(new BigDecimal
                    ((double)file.length()/1024/1024).
                    divide(new BigDecimal(1),2,BigDecimal.ROUND_CEILING))+"M");
            //返回的日期是以long的形式返回,可以利用SimpleDateFoemat进行格式化操作
            System.out.println("上次修改时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(file.lastModified())));
        }
    }
}

列出目录信息

public class TestDemo {
    public static void main(String[] args) throws Exception {
        File file =new File("d:"+File.separator);
        if (file.isDirectory()) {
            File result[]=file.listFiles();
            for (int x = 0; x <result.length;x++){
                System.out.println(result[x]);
            }
        }
    }
}

列出指定目录下的所有文件以及子目录信息

public class TestDemo {
    public static void main(String[] args) throws Exception {
        File file =new File("d:"+File.separator);
        print(file);

    }
    public static void print(File file){
        if (file.isDirectory()) {
            File result[]=file.listFiles();
            if (result!=null) {
                for (int x = 0; x < result.length; x++) {
                    print(result[x]);
                }
            }
        }
        System.out.println(file);
    }
}

11.2 字节流与字符流

输入与输出两种方式:

  • 字节流:InputStream(输入字节流)、OutputStream(输出字节流)
  • 字符流:Reader(输入字符流)、Writer(输出字符流)

基本操作形式:

  • 第一步:通过File类定义一个要操作文件的路径;
  • 第二步:通过字节流或字符流的子类对象为父类对象实例化;
  • 第三步:进行数据的读,写操作;
  • 第四步:数据流属于资源操作,资源操作必须关闭。

对于四个操作类都属于抽象类。

11.2.1 字节输出流:OutputStream

常用方法

public void close() thorws IOException:关闭字节输出流

public void flush() throws IOException:强制刷新

public abstract void write(int b) throws IOException:输出单个字节

public void write(byte[] b)throws IOException:输出全部字节数组数据

public void write(byte[] b,int off,int len)throws IOException:输出部分字节数组数据

文件内容的输出

public class TestDemo {
    public static void main(String[] args) throws Exception {
        //1.定义要输出文件的路径
        File file=new File("d:"+File.separator+"demo"+File.separator+"mldn.txt");
        //此时由于目录不存在,所以文件不能输出,应该首先创建目录
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        //2.应该使用OutputStream和其子类进行对象的实例化,此时目录存在,文件还不存在。
        OutputStream output=new FileOutputStream(file);
        //字节输出流需要使用byte类型,需要将String类对象变为字节数组
        String str="更多课程资源请访问:www.baidu.com";
        byte data[]=str.getBytes();
        //进行写操作
        output.write(data);
        //进行清除操作
        output.close();
    }
}

输出部分数组内容

output.write(data,6,6);

对于已有文件进行追加操作

OutputStream output=new FileOutputStream(file,true);

11.2 字节输入流:InputStream

常用方法

  • public void close() throws IOException:关闭字节输入流
  • public abstract int read() throws IOException:读取单个字节
  • public int read(byte[] b)throws IOException :将数据读取到字节数组中,同时返回读取长度。
  • public int read(byte[] b,int off,int len)throws IOException :将数据读取到部分字节数组中,同时返回读取的数据长度。

关于InputStream类中最为重要的3个read()方法

  • 读取单个字节:public abstract int read() throws IOException(返回读取的字节内容,如果已经没有内容,则读取后返回“-1”)
  • 将读取的数据保存在字节数组里(一次性读取多个数据):public int read(byte[] b)throws IOException (返回读取的数据长度,如果已经读取到结尾,则返回-1)
  • 将读取的数据保存在部分字节数组里:public int read(byte[] b,int off,int len) throws IOException(读书数据部分长度

FilelnputStream类的构造方法

public FileIputStream(File file)throws FileNotFoundException:设置要读取的文件数据路径

数据读取操作

public class TestDemo {
    public static void main(String[] args) throws Exception {
        //1.定义要输出文件的路径
        File file=new File("d:"+File.separator+"demo"+File.separator+"mldn.txt");
        if (file.exists()){
            //2.使用InputStream进行读取
            InputStream input=new FileInputStream(file);
            byte data[]=new byte[1024];
            int foot=0;
            int temp=0;
            while( (temp=input.read())!=-1){
                data[foot++]=(byte) temp;
            }
            input.close();
            System.out.println("["+new String(data,0,foot)+"]");
        }
    }
}

11.2.3 字符输出流 Writer

Writer类的常用操作方法

  • public void close() throws IOException:关闭字节输出流
  • public void flush() throws IOException:强制刷新
  • public Writer append(CharSequence csq)throws IOException:追加数据
  • public void writer(String str ) throws IOException:输出字符串数据
  • public void write(char[] cbuf)throws IOException:输出字符数组数据

FileWriter类的常用方法

  • public FileWriter(File file )throws IOException :设置输出文件
  • public FileWriter(File file ,boolean append)throws IOException:设置输出文件以及是否进行数据追加。
public class TestDemo {
    public static void main(String[] args) throws Exception {
        //1.定义要输出文件的路径
        File file=new File("d:"+File.separator+"demo"+File.separator+"mldn.txt");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        Writer out=new FileWriter(file);
        String str="更多课程访问:www.baidu.com";
        out.write(str);
        out.close();
    }
}

11.2.4 字符输入流:Reader

Reader类的常用方法

  • public void close() throws IOException:关闭字节输入流
  • public int read() throws IOException :读取单个数据
  • public int read() throws IOException:读取单个字符
  • public int read(char[] cbuf)throws IOException:读取数据到字符串组中,返回读取长度
  • public long skip(long n )throws IOException:跳过字节长度

使用Reader读取数据

public class TestDemo {
    public static void main(String[] args) throws Exception {
        //1.定义要输出文件的路径
        File file=new File("d:"+File.separator+"demo"+File.separator+"mldn.txt");
        if (file.exists()){
            Reader in=new FileReader(file);
            char data[]=new char[1024];
            int len=in.read(data);
            in.close();
            System.out.println(new String(data,0,len));
        }
    }
}

11.2.5 字节流和字符流的区别

字节流直接与终端文件进行数据交互,字符流需要将数据经过缓冲区处理才与终端文件数据交互。

如果有特殊情况不能关闭字符输出流,可以使用flush()方法强制清空缓冲区。

11.3 转换流

字节流通过向上转型可以转换为字符流

实现输出流转换

public class TestDemo {
    public static void main(String[] args) throws Exception {
        //1.定义要输出文件的路径
        File file=new File("d:"+File.separator+"demo"+File.separator+"mldn.txt");
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        OutputStream output=new FileOutputStream(file);
        Writer out=new OutputStreamWriter(output);
        out.write("更多课程请访问:www.baidu.com");
        out.flush();
        out.close();
    }
}

11.4 案例:文件复制

两种方法

  • 法一:将所有的文件内容先一次性读取到程序中,再一次性输出。缺点:如果要读取的文件量过大,就会造成程序的崩溃。
  • 法二:采用边读边输出的操作方式,每次从源文件输入流中读取数据,而后将这部分数据交给输出流输出,这样的做法不会占用较大的内存空间,但是会适当损耗一些时间。

使用的类与方法

  • InputStream类:public int read(byte[] b)throws IOException;(将内容读取到字节数组中,如果没有数据则返回-1,否则读取长度)

  • OutputStream类:public void write(byte[] b)throws IOException. (要设置的字节数组实际上就是在read()方法里面使用的数组;数据输出一定是从字节数组的第0个元素开始,输出读取的数据长度。)

    实现文件复制操作

    public class TestDemo {
        public static void main(String[] args) throws Exception {
            //取得复制开始的时间
            long start=System.currentTimeMillis();
            if (args.length!=2){
                System.out.println("命令执行错误!");
                System.exit(1);
            }
            //如果输入参数正确,应该进行源文件有效性的验证
            File inFile=new File(args[0]);
            if (!inFile.exists()){
                System.out.println("源文件不存在,请输入有效入径。");
                System.exit(1);
            }
            //如果此时源文件正确,就需要定义输出文件,同时要考虑到输出文件有目录
            File outFile=new File(args[1]);
            if (!outFile.getParentFile().exists()){
                outFile.getParentFile().mkdirs();
                //创建目录
            }
            //实现文件内容的复制,分别定义输出流和输入流对象
            InputStream intput=new FileInputStream(inFile);
            OutputStream output=new FileOutputStream(outFile);
            int temp=0;
            byte data[]=new byte[1024];
            //将每次读取进来的数据保存在字节数组里面,并且返回读取的个数
            while ((temp=intput.read(data))!=-1){
                output.write(data,0,temp);
            }
            intput.close();
            output.close();
            long end=System.currentTimeMillis();
            System.out.println("复制所花费的时间:"+(end-start));
        }
    }
    

11.5 字符编码

GBK、GB2312:中文的国际编码,其中GBK包含简体中文与繁体中文两种,而GB2312只包含简体中文;

ISO8859-1:是国际编码,可以描述任何文字信息;

UNICODE:是十六进制编制,但是在传递字符信息时会造成传输的数据较大。

UTF编码:是一种UNICODE的可变长度编码,常见的编码为UTF-8编码。

public class TestDemo {
    public static void main(String[] args) throws Exception {
        File file=new File("d:"+File.separator+"demo"+File.separator+"mldn.txt");
        OutputStream output=new FileOutputStream(file);
        //强制改变文件的编码,此操作可以通过String类的getBytes()方法实现
        output.write("更多课程访问:www.baidu.com".getBytes("GBK"));
        output.close();
    }
}

11.6 内存流

内存流的两种方式

  • 字节内存流:ByteArrayInputStream(内存字节输入流)、ByteArrayOutputStream(内存字节输出流)
  • 字符内存流:CharArrayReader(内存字符输入流)、CharArrayWriter(内存字符输出流)

字母转大小写

  • 转小写字母:public static char toLowerCase(char ch);
  • 转小写字母(利用字母编码转换):public static int toLowerCase(int codePoint);
  • 转大写字母:public static char toUpperCase(char ch)
  • 转大写字母(利用字母编码转换):public static int toUpperCase(int codePoint)

实现文件的合并读取

public class TestDemo {
    public static void main(String[] args) throws Exception {
        File fileA=new File("d:"+File.separator+"into.txt");
        File fileB=new File("d:"+File.separator+"outto.txt");
        InputStream inputA=new FileInputStream(fileA);
        InputStream inputB=new FileInputStream(fileB);
        ByteArrayOutputStream output=new ByteArrayOutputStream();
        int temp=0;
        while ((temp=inputA.read())!=-1){
            output.write(temp);
        }
        while ((temp=inputB.read())!=-1){
            output.write(temp);
        }
        //现在所有的内容都保存在了内存输出流里面,所有的内容为字节数组取出
        byte data[]=output.toByteArray();
        output.close();
        inputA.close();
        inputB.close();
        System.out.println(new String(data));
    }
}

11.7 打印流

在java中主要利用OutputStream类主要是进行数据输出。

定义打印流工具类

package com.company;

import java.io.IOException;
import java.io.OutputStream;

public class PrintUtil {
    private OutputStream output;
    public PrintUtil(OutputStream output){
        this.output=output;
    }
    public void print(int x){
        this.print(String.valueOf(x));
    }
    public void print(String x){
        try{
            this.output.write(x.getBytes());
        }catch (IOException e){
            e.printStackTrace();
        }
    }
    public void print(double x){
        this.print(String.valueOf(x));
    }
    public void println(int x){
        this.print(String.valueOf(x));
    }
    public void println(String x){
        this.print(x.concat("\n"));
    }
    public void println(double x){
        this.println(String.valueOf(x));
    }
    public void close(){
        try{
            this.output.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}
public class TestDemo {
    public static void main(String[] args) throws Exception {
        PrintUtil pu=new PrintUtil(new FileOutputStream(new File("d:"+File.separator+"yootk.txt")));
        pu.print("优秀教育:");
        pu.println("www.dadaf");
        pu.println(1+1);
        pu.println(1.1+1.1);
        pu.close();
    }
}

PrintStream类的常用操作方法

public PrintStream(OutputStream out):通过已有OutputStream out确定输出目标

public void print(数据类型 参数名称):输出各种常见数据类型

public void println(数据类型 参数名称):输出各种常见数据类型,并追加一个换行

格式化输出

public class TestDemo {
    public static void main(String[] args) throws Exception {
        String name="朱小东";
        int age=19;
        double score=59.24452;
        PrintStream pu=new PrintStream(new FileOutputStream(new File("d:"+File.separator+"yootk.txt")));
        pu.printf("姓名:%s,年龄:%d,成绩:%5.2f",name,age,score);
        pu.close();
    }
}

11.8 System类的IO的支持

System.err:显示器上错误输出

System.out:显示器上信息输出

System.in:键盘数据输入

错误输出

public class TestDemo {
    public static void main(String[] args) throws Exception {
        try{
            Integer.parseInt("abc");
        }catch (Exception e){
            System.err.println(e);
        }
    }
}

System.err是输出不希望用户看见的异常、System.out是输出希望用户看到的信息。

利用OutputStream实现屏幕输出

public class TestDemo {
    public static void main(String[] args) throws Exception {
        OutputStream out=System.out;
        out.write("www.baidu.com".getBytes());
    }
}

系统输入:System.in

public class TestDemo {
    public static void main(String[] args) throws Exception {
        InputStream input=System.in;
        StringBuffer buf=new StringBuffer();
        System.out.print("请输入数据:");
        int temp=0;
        while ((temp=input.read())!=-1){
            if (temp=='\n'){
                break;
            }
            buf.append((char) temp);
        }
        System.out.println("输出数据为:"+buf);
    }
}

11.9 字符缓冲流:BufferedReader

为了可以进行完整数据的输入操作,最好的做法是采用缓冲区的方式对输入的数据进行暂存,而后程序可以利用输入流一次性读取内容。

  • 字符缓冲区流:BufferedReader、BufferedWriter;
  • 字节缓冲区流:BufferedInputStream、BufferedOutputStream。

public BufferedReader(Reader in):设置字符输入流

public String readLine() throws IOException:读取一行数据,默认以“\n"为分隔符。

判断输入内容

public class TestDemo {
    public static void main(String[] args) throws Exception {
        BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
        boolean flag=true;
        while (flag){
            System.out.print("请输入年龄:");
            String str=buf.readLine();
            if (str.matches("\\d{1,3}")){
                System.out.println("年龄是:"+Integer.parseInt(str));
                flag=false;
            }else {
                System.out.println("年龄输入错误,应该由数字所组成。");
                //该程序利用正则去判断
            }
        }
    }
}

读取文件

public class TestDemo {
    public static void main(String[] args) throws Exception {
        File file=new File("D:"+File.separator+"yootk.txt");
        //使用文件输入流实例化BufferedReader类对象
        BufferedReader buf=new BufferedReader(new FileReader(file));
        String str=null;
        while ((str=buf.readLine())!=null){
            System.out.println(str);
        }
        buf.close();
    }
}

11.10 扫描流:Scanner

  • public Scanner(InputStream source):接收InputStream输入流对象,此为输入源
  • public boolean hasNext():判断是否有数据输入
  • public String next():取出输入数据,以String形式返回
  • public boolean hasNextXxx():判断是否有指定类型数据存在
  • public 数据类型 nextXxx():取出指定数据类型的数据
  • public Scanner useDelimiter(String pattern):设置读取的分隔符

利用Sanner实现键盘数据输入

public class TestDemo {
    public static void main(String[] args) throws Exception {
        Scanner scan=new Scanner(System.in);
        System.out.println("请输入内容:");
        if (scan.hasNext()){
            System.out.println("输出内容:"+scan.next());
        }
        scan.close();
    }
}

输入一个数字–double

public class TestDemo {
    public static void main(String[] args) throws Exception {
        Scanner scan=new Scanner(System.in);
        System.out.println("请输入成绩:");
        if (scan.hasNextDouble()){
            double score=scan.nextDouble();
            System.out.println("输出内容:"+score);
        }else {
            System.out.println("输入的不是数字,错误!");
        }
        scan.close();
    }
}

正则验证

public class TestDemo {
    public static void main(String[] args) throws Exception {
        Scanner scan=new Scanner(System.in);
        System.out.println("请输入生日:");
        if (scan.hasNext("\\d{4}-\\d{2}-\\d{2}")){
            String bir=scan.next("\\d{4}-\\d{2}-\\d{2}");
            System.out.println("输出内容:"+bir);
        }else {
            System.out.println("输入生日格式错误!");
        }
        scan.close();
    }
}

读取文件

public class TestDemo {
    public static void main(String[] args) throws Exception {
        Scanner scan = new Scanner(new FileInputStream("d:" + File.separator + "demo" + File.separator + "mldn.txt"));
        scan.useDelimiter("\n");
        while (scan.hasNext()) {
            System.out.println(scan.next());
            //中文读取不出来,会乱码。
        }
        scan.close();
    }
}

11.11 对象序列化

但是在很多时候可能需要在JVM进程结束后对象依然可以被保存下来,或者在不同的JVM进程中要进行对象传输,这个时候就要采用对象序列化的方式进行处理。

序列化:将对象序列化为格式指定的二进制数据

反序列化:将系列化的二进制对象信息转换回对象内容。

  • public ObjectOutStream(OutputStream out)throws IOException:指定对象序列化的输出流
  • public final void writeObject(Object obj)throws IOException:序列化对象
  • public ObjectInputStream(InputStream in)throws IOException:指定对象反序列化的输入流
  • public final Object readObject()throws IOException,ClassNotFoundException:从输入流中读取对象

定义一个可以被序列化对象的类

import java.io.Serializable;
@SuppressWarnings("serial")
public class Book implements Serializable {
    private String title;
    private double price;
    public Book(String title,double price){
        this.title=title;
        this.price=price;
    }
    @Override
    public String toString(){
        return "书名:"+this.title+"价格:"+this.price;
    }
}

实现序列化对象操作

public class TestDemo {
    public static void main(String[] args) throws Exception {
        ser();
    }
    public static void ser()throws Exception{
        ObjectOutputStream oos=new ObjectOutputStream(new ObjectOutputStream
                (new FileOutputStream(new File("d:"+File.separator+"demo"+File.separator+"mldn.txt"))));
        oos.writeObject(new Book("java开发",19.2));
        oos.close();
    }
}

反序列化操作

public class TestDemo {
    public static void main(String[] args) throws Exception {
        ser();
    }
    public static void ser()throws Exception{
        ObjectInputStream oos=new ObjectInputStream(new FileInputStream(new  File("d:"+File.separator+"demo"+File.separator+"mldn.txt")));
        Object obj=oos.readObject();
        Book book=(Book) obj;
        System.out.println(book);
        oos.close();
    }
}

transient关键字用此关键字定义的属性无法被序列化。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值