Java IO编程之文件处理归纳

前言

进日来跟随老师学习java编程,但仅仅是以偏概全式地讲解和c++中不同之处,以及注意事项。所以最近看书真的是看的头大,在此也记录一下看书的心得,以免日后忘记。

如何处理IO

这里主要讲的是文件数据处理
首先,要明确的是输入输出的过程无非就是:

  • 创建流对象(将数据源转化为流对象,或者向流中写入数据)
  • 处理流内数据(从流中读取,或写入数据源)
  • 关闭流对象

Java提供5大基本类用以处理文件和流

File类

直接对文件进行操作,但不涉及文件内容的操作

  • 创建文件对象
    File file = new File(path)
  • 一般文件操作
        /* 截取main函数中部分代码
         * 文件信息:
         * 是否是目录
         * 是否是文件
         * 文件大小、最后修改时间
         * 当前路径、父目录路径
         * 重命名
         */
        File file3 = new File("otherFile\\test.txt");

        System.out.println("当前文件:"+file3);

        if (!file3.exists()) {
            System.out.println("file2是否存在:"+file3.exists());
            file3.createNewFile();
        }else {
            //  is File?
            System.out.println("是否是文件:"+file3.isFile());
            //  is Directory?
            System.out.println("是否是目录:"+file3.isDirectory());
            //  get the absolute path
            System.out.println("绝对路径:"+file3.getAbsolutePath());
            // 默认get the relative Path,实际上是构造file3时的路径 
            System.out.println("相对路径:"+file3.getPath());
            //  the name of the file
            System.out.println("文件名:"+file3.getName());
            // the size of the file
            System.out.println("文件大小:"+file3.length());
            // the last times of revising file
            long lasttime = file3.lastModified();
            Date date = new Date(lasttime);
            System.out.println("文件最后修改时间:"+date);

            //  get the parentFile
            File pFile = file3.getParentFile();

            // rename the file
            File file4 = new File("123.txt");
            file3.renameTo(file4);//对文件对象处理,返回布尔值

这里在区分几个函数

  • mkdir(),mkdirs():区别在于前者如果父目录不存在则不创建,后者则连同父目录一起创建(推荐使用后者)
  • getAbsolutePath(),getCanonicalPath():获取绝对路径,区别是后者会处理“.”“..”

4大基本抽象Stream数据流类

注意:全是抽象类

字节流和字符流的区别:

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

字节流
  • InputStream字节输入流
  • OutputStream字节输出流
  • 由FileInputStream、FileOutputStream来实现

上文提到了这些类全是抽象类,所以要借助子类来实现功能。(下文也是)


  • 实例化流对象
    FileInputStream fis = new FileInputStream(file);file是File对象,输出流也类似,但可以多一个参数【boolean append】选择是末尾追加数据,还是覆盖数据(true 是追加)
  • 函数(无非就是读、写、关闭流)

read():有三个重载
write():有三个重载
close()
输出流多一个强制刷新 flush()

字符流
  • Reader
  • Writer
  • 通过FileReader、FileWriter实现

同上文解释

  • 实例化流对象
    FileReader fr = new FileReader(file);FileWriter的情况类似上文的FileOutputStream
  • Reader常用方法
    • close()
    • read():三个重载,了解一下
    • skip(long n):跳过n个字节长度
  • Writer常用方法
    • close()
    • writer():两个重载,直接写入String或char[ ]
    • append(CharSequence):追加数据,CharSequence可保存String、StringBuffer、StringBuilder类对象
    • flush()

看到这里你自然会想得到这些类每次只对一个字节(字符)进行IO操作,效率自然就低了,下文是解决办法。

转换流—-字节字符流间的转换

  • InputStreamReader
    • 继承自Reader,接受InputStream对象
  • OutputStreamWriter
    • 继承自Writer,接受OutputStream对象

举个栗子:

File file = new File("123.txt");
//字节流
InputStream input = FileInputStream(file);
//向上转型,转为字符流
Reader in = new InputStreamReader(in);
in.read();

读写优化—处理流

先明确两点

  • 节点流 (类似FileInputStream直接处理流)
  • 处理流 (把其他流对象再做处理封装)

缓冲流

同理会有四种两对不同类,
但是用的多的还是BufferedReader,它可以按行读取。

BufferedReader
  • 实例化(可以指定缓冲区大小,默认8KB,一般够用了)
    BufferedReader bfr = BufferedReader(Reader in); in 可以是各种Reader的子类(如FileReader、InputStreamReader)
    FileReader in = new FileReader(file);InputStreanReader isr = new InputStreamReader(new FileInputStream(file));
  • 按行读取 readLine()
    • 返回的是字符串对象,读取结束的标志是 bfr.readLine()==null
  • 自然也有 read() 读取一个或一组字符,但那样的话干嘛不用FileReader
  • close()不用说
BufferedWriter(相比用得少,下文会有个打印流)
  • 实例化同上BufferedWriter bfw = new BufferedWriter(Writer out);
  • write(),写入单个字符、一组字符、字符串。和FileWriter的功能是不是类似,所以感觉没必要用这个
  • newLine(),写入一个行分隔符,默认“\n”
  • close()、flush()
顺便提下解决平台编码问题

就是再用字符流解决中文等编码时,jvm对字符是unicode码,但平台默认以GBK码读取,这时你在输出就是乱码。
解决方法就是通过字节流来处理,不存在编码的问题,在文件操作是指定编码格式就好了。
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(saveFilename),"utf-8"));

打印流

这个类就是为了有效率地处理写入问题,对应上文的BufferedReader。它包含PrintStream、PrintWriter字节字符两种,方法功能都是一样的,用的多的是PrintWriter。

PrintWriter
  • 实例化
    • PrintWriter(File file)
    • PrintWriter(OutputStream out,[Boolean autoflush]),是否自动刷新
    • PrintWriter(Writer out,[Boolean autoflush])
  • print()、println():写入各种数据形式,后者追加一个换行
  • printf():格式化输入,类似C语言的printf用法,看下文代码
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class WriteData {
     public static void main(String[] args) throws FileNotFoundException{
         File file=new File("test.txt");//文件对象
         if(file.exists()){
             System.out.print("文件已经存在!");
             System.exit(0);
         }
         PrintWriter out=new PrintWriter(file);//由文件对象构造一个写出器
         //或者
         //FileWriter fw = new FileWriter(file,true);//追加
         //PrintWriter out = new PrintWriter(fw);
         out.print(1+1.1);
         out.println("Josonlee,Where are you?");
         out.println(15);
         pWriter.printf("姓名:%s,年龄:%d", "josonlee",20);
         out.flush();
         out.close();
     }
}
  • 指定文件编码方式
    PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),"utf-8")));
PrintStream

同上用法类似

扫描流 Scanner

这个不同于其他定义在java.io中,它在java.util包中,是一个方便数据输入操作的工具类。

这东西看着挺有用的,但我没有过多关注

  • 实例化(包括字符串、输入流、文件)
    • Scanner scan = new Scanner(File file/InputStream in);
    • 也可以new Scanner(Readable source),如Systerm.in类似的可读资源
  • 常用方法
    • hasNext():判断是否有数据输入
    • next():以字符串形式返回输入数据
    • hasNextLine():是否有下一行
    • nextLine():同理输出下一行
    • hasNextXXX():XXX代表 Int、Double、Boolean等,是否有指定该类型数据在
    • nextXXX():同上,就是取出该类型数据
    • useDelimiter(String pattern):这个挺重要的,设置读取的分隔符,默认空格

Properties对配置文件操作

这里我就不归纳了,有篇挺好的文章 Java中Properties类的操作


感觉差不多了,似乎还有点没完善,等我下次回看时,再想想有什么遗漏吧。


也看过了一些写得好的文章,在此一一列出:

【java文件读写操作指定编码格式】
【java中文乱码处理】
【Java 编程要点之 I/O 流详解】

posted @ 2018-07-10 19:47  不知道的痛  阅读(142)  评论(0编辑  收藏  举报