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类的操作
感觉差不多了,似乎还有点没完善,等我下次回看时,再想想有什么遗漏吧。
也看过了一些写得好的文章,在此一一列出: