1.文件本身的操作用File类来操作;
例1:创建与删除文件:
例2.列出所给文件目录下的全部内容,包括子文件夹中的内容:
2.对于文件内容的IO操作,则方法居多;主要有字节流与字符流两大类,操作方法等价,可相互替换,因此只讲一种;
A. RandomAccessFile类提供对文件内容的随机访问存取,以字节为单位去文件内定为指针,可以通过文档查询自行完成。
B. 字节流操作,较为常用,由OutputStream与InputStream两个抽象类以及其子类完成操作:
例3. 在文件中写入内容:
注:此处文件若不在,则会自动创建;文件分隔符一般用File.separator来表示,因为它为类变量,但由于同样可以用对象调用类变量,所以此处file.separator也可以,只是不常用。
例4.从文件中读取内容:
方法一:
该方法是通过定义与文件内容大小一致的字节数组,然后一次性的把文件内容装到数组中;但如果无法取得文件大小的时候,可以一次次读取文件字节,直到文件末尾,来完成把文件中的内容装到数组中;
方法二:
在这个方法中,数组的长度是固定的,并且肯定要大于文件内容的长度,因此输出的时候后面会有大量空格,为解决这个问题,可以,必须用判断读进了多少内容,可以用FileInputStream类中的intread(byte[] b)方法,该方法返回的是读取了多少长度字节到数组,因此可以记录下该返回的总长度,然后字节数组转换成字符串时候,选用String(byte[] bytes,int offset,int length)该构造方法,生成有效长度的字符串。
注:区分InputStream与FileInputStream类中的read()方法。InputStream类中的read()方法返回的是读取总数据的长度,而且有参数,接收一个字节数组;而FileInputStream类中的read()无参数,每次读取一个字节,返回读取当前的字节,一般配合循环使用,用于判断是否读取到了末尾。
C. 除了字节流与字符流,还有一种转换流;由于程序在缓冲区内存中处理是以字符形式,而在文件读写过程中是以字节形式,所以运用转换流效率较高。
InputStreamReader类将文件内容以字节形式读入,然后转换为字符形式;OutputStreamWriter类将程序将要输出的内容以字符接收,并转换为字节写入文件中。
例5. 运用转换流完成文件的复制工作。
File file1=null;
File file2=null;
InputStreamReader in = null;
OutputStreamWriter out = null;
try{
//定义文件对象,用路径定义文件
file1 = new File("D:"+File.separator+"test.txt");
file2 = new File("D:"+File.separator+"copy.txt");
//对文件的读取都用字节流进行实例化,然后把字节流的对象转换为字符流,供程序进行字符操作
in = new InputStreamReader(new FileInputStream(file1));
out = new OutputStreamWriter(new FileOutputStream(file2,true));
int temp=0;
while((temp=in.read())!=-1){//此处的read()读进的是一个字符对应int值
out.write(temp);//把字符对应的int值写入文件
}
//最后关闭输出
in.close();
out.close();
}catch(Exception e){
e.printStackTrace();
}
注:此处的ready()与write()操作都是字符流操作。
D.在以上的转换输出流中,可以方便的输出字符串到文件中,但是无法方便的定义格式;因此诞生了一个装饰输出类,可以简化字符输出流以及字节输出流,这里仅介绍字节输出流的装饰类-PrintStream
例6.格式化输出:
File file=null;
OutputStream out = null;
PrintStream ps = null;
try{
//定义文件对象,用路径定义文件
file = new File("D:"+File.separator+"test.txt");
//定义文件字节输出流对象
out = new FileOutputStream(file,true);
String name = "wangjxy";
int age = 25;
float weight = 55.5f;
char gender = 'M';
//定义打印输出流
ps = new PrintStream(out);
//格式化输出
ps.printf("Name: %s; Age: %d; Weight: %f; Gengder: %c;",name,age,weight,gender);
//最后关闭输出
out.close();
ps.close();
}catch(Exception e){
e.printStackTrace();
}
更多格式化输出可以参考文档;
3.标准输入输出(键盘输入与显示器输出)
以上部分讲的是用文件输入输出流来实例化字节流的实例,因此所有输入输出都是通过文件形式;
在System类中,已经预先定义了三个标准IO实例-err,in,out.
err错误输出;out标准输出;in标准输入;
这里重点讲解从键盘的输入.如果单单用System.in来输入的话,就可能会出现以下情况:
a.以字节形式读入,必须预先开辟字节数组用来接收,这是,固定大小的数组会出现超界或者非偶数字节的话,中文会出现乱码;
b.若不固定数组长度,就要一个字节一个字节的读,这时中文全会出现乱码,因为无法一次读取一个中文单位(2字节);
因此,比较合理的键盘输入方法是用BufferedReader类中提供的readLine()方法进行整行读取;而由文档中的构造函数
BufferedReader(Reader in)可以发现,接收的是字符流,而System.in提供的是字节流,因此要进行转换,如:
BufferedReader br = null;
br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
至此不用担心数据大小以及中文乱码问题。
4.工具输入类-Scanner
在util包中的Scanner类是专门为输入操作开发的工具输入类,提供了输入与输入的各种验证操作。
从文档中可以看到,构造方法主要有Scanner(File source),Scanner(InputStream source);
即接受字节输入流的对象以及直接接受文件输入。
在方法中,useDelimiter(String pattern)方法可以用来设置分隔符,一旦完成分隔符的设置,就可以根据设置的分隔符,进行
String next()方法读取一个被分隔符分开的数据单元;
Scanner类最大的好处在于,有hasXXX()方法可以对输入的数据提前进行验证判断,如:
boolean hasNext(Pattern pattern)方法,参数为正则表达式,根据提供的正则表达式,判断是否有下一个满足要求的数据单元,
如若参数为空,则判断是否有下一个数据单元,有则全盘按照字符串接收(boolean hasNext());
当然,该类提供一些基本数据判断的函数,如boolean hasNextInt(),对应读取操作为intnextInt(),等。