【RandomAccessFile】
--------------------------------------
该类不算是IO体系中的子类,而是直接继承了Object。
但它是IO包中的成员,因为他具备读取和写入功能。
它内部封装了一个数组,而且通过指针对数组的元素进行操作。
并且可以通过getFilePointer获取指针位置,通过seek改变指针位置。
【提示】:可以使用seek让多个线程分别读取不同段,达到同时读取的效果,效率高。
该类能完成读取和写入的原因是内部封装了输入流和输出流。
通过构造函数可以看出,该类只能操作文件(File)。
并且,该类操作文件时有特定模式。
--------------------------------------
public RandomAccessFile(File file,String mode)
throwsFileNotFoundException
创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
--------------------------------------
mode 参数指定用以打开文件的访问模式。允许的值及其含意为:
"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出IOException。
"rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
"rws" 打开以便读取和写入,对于"rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
"rwd" 打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备。
--------------------------------------
如果模式为r,则不会自动创建文件,若读取的文件不存在,则会抛出异常。
如果模式为rw,该对象的构造函数要操作的文件不存在,会自动创建。如果存在则不会覆盖。
* // *
import java.io.*;
class RandomAccessFileDemo
{
public static voidmain(String[] args) throws IOException
{
writeFile();
//readFile();
writeFile_2();
}
public static voidreadFile() throws IOException{
RandomAccessFileraf = new RandomAccessFile("random.txt","r");//只读
//调整对象中的指针。
//raf.seek(8*1);
//跳过指定的字节数,只能按索引往前跳,不能回跳
raf.skipBytes(8*1);
byte[] buf = newbyte[4];
raf.read(buf);
String name =new String(buf);
int age =raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);
raf.close();
}
public static voidwriteFile_2 () throws IOException{
RandomAccessFileraf = new RandomAccessFile("random.txt","rw");//读写
raf.seek(8*3);
raf.write("Kate".getBytes());
raf.writeInt(98);
raf.close();
}
public static voidwriteFile() throws IOException{
RandomAccessFileraf = new RandomAccessFile("random.txt","rw");//读写
raf.write("Mike".getBytes());
raf.writeInt(97);
raf.write("Lily".getBytes());
raf.writeInt(99);
raf.close();
}
}
* // *
---------------------------------------------------------------------------------------------------------------------
**************操作基本数据类型*****************
【DataInputStream】和【DataOutputStream】
InputStream和OutputStream的子类
* // *
import java.io.*;
class DataStreamDemo
{
public static voidmain(String[] args) throws IOException{
//writeData();
//readData();
//writeUTFData();
readUTFData();
}
public static voidreadUTFData() throws IOException{
DataInputStreamdis = new DataInputStream(new FileInputStream("dataUTF.txt"));
//public finalString readUTF()throws IOException
//用UTF-8编码写,就一定对应UTF-8读
System.out.println(dis.readUTF());
dis.close();
}
public static voidwriteUTFData()throws IOException{
DataOutputStreamdos =
new DataOutputStream(new FileOutputStream("dataUTF.txt"));
//public finalvoid writeUTF(String str) throws IOException
//以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流。
dos.writeUTF("学生");
dos.close();
}
public static voidreadData() throws IOException{
DataInputStreamdis = new DataInputStream(new FileInputStream("data.txt"));
int num =dis.readInt();
boolean b =dis.readBoolean();
double d =dis.readDouble();
dis.close();
System.out.println("num="+num);
System.out.println("b="+b);
System.out.println("d="+d);
}
public static voidwriteData()throws IOException{
DataOutputStreamdos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(1666);
dos.writeBoolean(true);
dos.writeDouble(6789.234);
dos.close();
}
}
* // *
---------------------------------------------------------------------------------------------------------------------
**************操作字节数组,字符数组,字符串*****************
【ByteArrayInputStream】:
在构造的时候,需要接收数据源,而且该数据源是一个字节数组
【ByteArrayOutputStream】:
在构造的时候,不需要定义数据目的,因为该对象内部已封装了可变长度的字节数组。
这两个流对象操作的都是数组,并且没有使用系统资源。因此,不需要close关闭。
这是用流的思想思想来操作数组。
对于流操作规律的补充说明:
源设备:
键盘:System.in 硬盘:FileStream 内存:ArrayStream
目的设备:
控制台:System.out 硬盘:FileStream 内存:ArrayStream
【writeTo(OutputStream out)】:
涉及IO异常的操作,当一次性输入到字节数组后,可以将数组中数据写入到输出流中,
借以写入文件或其他目的设备。
import java.io.*;
class ByteArrayStreamDemo
{
public static void main(String[]args) throws IOException
{
//数据源
ByteArrayInputStream bis = newByteArrayInputStream("ABCDFE".getBytes());
//数据目的
ByteArrayOutputStream bos = newByteArrayOutputStream();
int by = 0;
while((by =bis.read())!=-1){
bos.write(by);
}
FileOutputStream fos = newFileOutputStream("ByteArrayDemo.txt");
try{bos.writeTo(fos);}
catch(IOException e){ throw new RuntimeException("写入文件失败");}
System.out.println(bos.size());
System.out.println(bos.toString());
}
}
* // *
【字符编码问题】:
“联通”:字符编码符合UTF-8的规定,当前面无字符时,被记事本默认用U8解码
import java.io.*;
class EncodeStreamDemo
{
public static voidmain(String[] args) throws IOException{
//writeText();
readText();
}
public static voidreadText()throws IOException{
InputStreamReaderisr =
newInputStreamReader(newFileInputStream("UTF-8code.txt"),"UTF-8");
//当指定的文件编码与读取编码不同时,打印的不是目标字符。
char[] ch = newchar[10];
isr.read(ch);
System.out.println(ch);
isr.close();
}
public static voidwriteText() throws IOException{
OutputStreamWriter osw =
newOutputStreamWriter(newFileOutputStream("UTF-8code.txt"),"UTF-8");
osw.write("你好");
osw.close();
}
}
-------------------------------------------------------------------
【练习】:
有五个学生,每个学生有3门课的成绩,从键盘输入以上数据(包括姓名,三门课成绩)。
输入的格式:如:Mike,30,40,60计算出总成绩。
并把学生的信息和计算出的总分数高低顺序存放在磁盘文件"STU.txt"中。
* /
import java.io.*;
import java.util.*;
class Student
{
private String name;
private int sum;
Student(String name,intmath,int eng,int chins){
this.name =name;
this.sum =math+eng+chins;
}
public StringtoString(){
return (name+" : "+sum);
}
public StringgetName(){
return name;
}
public int getSum(){
return sum;
}
}
class Comp implements Comparator<Student>
{
public intcompare(Student s1,Student s2){
int num =s2.getSum()-s1.getSum();
if(num == 0)
returns2.getName().compareTo(s1.getName());
return num;
}
}
class TestDemo
{
public static voidmain(String[] args) throws Exception{
BufferedWriterbw= new BufferedWriter(
//newOutputStreamWriter(new FileOutputStream("STU.txt")));
newFileWriter("STU.txt"));
BufferedReaderbr =new BufferedReader(
newInputStreamReader(System.in));
System.out.println("Please input the message in this format:Mike,30,40,50:");
//学生的集合容器,一定记得添加自定义比较器
TreeSet<Student> ts = new TreeSet<Student>(new Comp());
String line ;//按行输入的内容
while ((line =br.readLine())!=null){
if(line.equals("over"))//结束条件
break;
String[]str = line.split(",");//字符串分割,提取对应的成绩
Studentstu = new Student(
str[0],Integer.parseInt(str[1]),
Integer.parseInt(str[2]),Integer.parseInt(str[3]));
ts.add(stu); //将生成的Student对象加入集合中。
}
//设置迭代器,取出集合中元素的对应信息。
Iterator<Student> it = ts.iterator();
while(it.hasNext()){
Student s= it.next();
bw.write(s.toString());
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
}/ *
思路总结:
1.分析流:
键盘录入:(字节流)System.in ;
文件输出:(字节流)FileOutputStream 或者 (字符流)FileWriter
若是:字节-->字节,则操作的是缓冲字节数组,不方便,可以字符流处理,再转换成字节流暑输出。
InputStreamReader(System.in);
OutputStreamWriter(new FileOutputStream("STU.txt"));
若是:字节-->字符,需要转换流。InputStreamReader(System.in);
效率:提高效率可以使用BufferedReader/Writer