1. File类:
不管是文件还是目录,在Java中都是以File的实例来表示,如下示例是指定查询某个目录下的所有文件与目录名称。File类是文件的抽象代表,若要作文件输出/输入,必须配合其他相关类来使用。
package ysu.hxy;
import java.io.*;
import java.util.*;
public class FileDemo
{
public static void main(String[] args)
{
try
{
File file = new File(args[0]);
if(file.isFile()) //是否为文件
{
System.out.println(args[0] + "文件");
System.out.print(file.canRead()?"可读":"不可读");
System.out.print(file.canWrite()?"可写":"不可写");
System.out.println(file.length()+"字节");
}
else
{
//列出所有文件及目录
File[] files = file.listFiles();
ArrayList<File> fileList = new ArrayList<File>();
for(int i=0;i<files.length;i++)
{
//先列出目录
if(files[i].isDirectory())
{
//是否为目录
System.out.println("["+files[i].getPath()+"]");
}
else
{
//文件先存入fileList,待会再列出
fileList.add(files[i]);
}
}
//列出文件
for(File f : files)
{
System.out.println(f.toString());
}
System.out.println();
}
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("using: java FileDemo pathname");
}
}
};
2. RandomAccessFile类:
使用此类可以在文件中随意地移动读取位置,使用它的seek()方法来指定文件存取的位置,指定的单位是字节。但是每次文件读取的长度需要自己来设定。下面两段代码示例了如何利用RandomAccessFile类来读取和写入文件,以学生的单条数据信息的长度为读写单位。
package ysu.hxy;
public class Student
{
private String name;
private int score;
public Student()
{
setName("noname");
}
public Student(String name,int score)
{
setName(name);
this.score = score;
}
public void setName(String name)
{
//利用StringBuilder来固定字符长度
StringBuilder builder = null;
if(name != null)
builder = new StringBuilder(name);
else
builder = new StringBuilder(15);
builder.setLength(15); //最长15字符
this.name = builder.toString();
}
public void setScore(int score)
{
this.score = score;
}
public String getName()
{
return name;
}
public int getScore()
{
return score;
}
//每个数据固定写入34字节
//对于每个学生数据的实例在写入文件时,会固定以34字节的长度写入,
//也就是15个字符(30字节)加上一个int整数的长度(4字节)。
public static int size()
{
return 34;
}
};
下面的代码示范了如何使用RandomAccessFile来写入文件,并可随机指定一个所想读出的数据。
package ysu.hxy;
import java.io.*;
import java.util.*;
public class RandomAccessFileDemo
{
public static void main(String[] args)
{
Student[] students = {
new Student("Justin",90),
new Student("momore",95),
new Student("Bush",88),
new Student("caterpillar",84)};
try
{
File file = new File(args[0]);
//建立以RandomAccessFile实例并以读写模式打开文件
RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
for(int i=0;i < students.length;i++)
{
//使用对应的write方法写入数据
randomAccessFile.writeChars(students[i].getName());
randomAccessFile.writeInt(students[i].getScore());
}
Scanner scanner = new Scanner(System.in);
System.out.println("读取第几个数据?");
int num = scanner.nextInt();
//使用seek()方法操作存取位置
randomAccessFile.seek((num-1)*Student.size());
Student student = new Student();
//使用对应的read方法读出数据
student.setName(readName(randomAccessFile));
student.setScore(randomAccessFile.readInt());
System.out.println("姓名:" + student.getName());
System.out.println("分数:" + student.getScore());
//设定关闭文件
randomAccessFile.close();
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("请指定文件名称:");
}
catch(IOException e)
{
e.printStackTrace();
}
}
private static String readName(RandomAccessFile randomAccessFile) throws IOException
{
char[] name = new char[15];
for(int i=0;i<name.length;i++)
name[i]=randomAccessFile.readChar();
//将空字符取代为空格并返回
return new String(name).replace('\0',' ');
}
};
D:\hxy>java ysu.hxy.RandomAccessFileDemo Student.txt
读取第几个数据?
2
姓名:momore
分数:95
读写文件时的几个必要的流程:
(1) 打开文件并指定读写方式:在Java中,当实例化一个与文件相关的输入/输出类时,就会进行打开文件的动作。在实例化的时候要指定文件是以读出(r)、写入(w)、可读写(rw)的方式打开;
(2) 使用对应的写入方法:如writeInt()、writeChar()等;
(3) 使用对应的读出方法:如readInt()、readChar()等;
(4) 关闭文件:对于某些文件存取对象来说,关闭文件的动作意味着将缓冲区(Buffer)的数据全部写入文件,如果不作关闭文件的动作,某些数据可能没有写入文件而丢失。
3. 位流:Java将数据于目的地及来源之间的流动抽象化为一个流(Stream),而流当中流动的则是位数据。
(1) java.io.InputStream和java.io.OutputStream:
InputStream是所有表示位输入流的类之父类,是一个抽象类。InputStream是从装置来源地读取数据的抽象表示。如System中的标准输入流in对象就是一个InputStream类型的实例。在Java程序开始之后,in流对象就会开启,目的是从标准输入装置中读取数据。
OutputStream是所有表示位输出流的类之父类,也是一个抽象类。用于将数据写入目的地的抽象表示。在Java程序开始之后,out流对象就会开启,目的是将数据写到目的地装置。
4. FileInputStream和FileOutputStream
当建立一个FileInputStream和FileOutputStream的实例时,必须指定文件位置及文件名称,实例被建立时文件的流就会开启;而不使用流时,必须关闭文件流,以释放与相依的系统资源,完成文件读/写的动作。
FileInputStream可以使用read()方法一次读入一个字节,并以int类型返回,或者是使用read()方法时读入至一个byte数组,byte数组的元素有上,就读入多少个字节。这样的一个byte数组在文件读出与写入完成的过程中,经常充当缓冲区在中间承接数据的角色。
package onlyfun.caterpillar;
import java.io.*;
public class FileStreamDemo {
public static void main(String[] args) {
try {
byte[] buffer = new byte[1024];
// 来源文件
FileInputStream fileInputStream =
new FileInputStream(new File(args[0])/*直接用args[0]建立也可以 */);
// 目的文件
FileOutputStream fileOutputStream =
new FileOutputStream(new File(args[1])/*直接用args[0]建立也可以*/);
// available()可取得未读取的数据长度
System.out.println("复制文件:" +
fileInputStream.available() + "字节");
while(true) {
if(fileInputStream.available() < 1024) {
// 剩余的数据比1024字节少
// 一位一位读出再写入目的文件
int remain = -1;
while((remain = fileInputStream.read())
!= -1) {
fileOutputStream.write(remain);
}
break;
}
else {
// 从来源文件读取数据至缓冲区
fileInputStream.read(buffer);
// 将数组数据写入目的文件
fileOutputStream.write(buffer);
}
}
// 关闭流
fileInputStream.close();
fileOutputStream.close();
System.out.println("复制完成");
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println(
"using: java FileStreamDemo src des");
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
程序中示范了两个read()方法,一个方法可以读入指定长度的数据至数组,另一个方法一次可以读入一个字节。每次读取之后,读取的光标都会往前进,如果读不到数据则返回-1,使用available()方法获得还有多少字节可以读取。
FileOutputStream默认会以新建文件的方式来开户流。如果指定的文件名称已经存在,则原文件会被覆盖;如果想以附加模式来写入文件,则可以在构建FileOutputStream实例时指定为附加模式。如:
FileOutputStream fileOutputStream = new FileOutputStream(args[1],true);