1 简述RandomAccessFile和FileInputStream及FileOutputStream在使用中的区别
参考答案
RandomAccessFile使用随机访问的方式,而FileInputStream及FileOutputStream使用的是流式访问的方式。
2 用自定义缓存区的方式实现文件的移动
使用FileInputStream类的read(byte[])方法和FileOutputStream类的write(byte[])方法实现文件移动。
参考答案
实现此案例需要按照如下步骤进行。
步骤一:新建TestMoveFile类,添加测试方法testMove方法
首先新建类TestMoveFile,然后在该类中添加测试方法testMove,代码如下所示:
import org.junit.Test;
public class TestMoveFile {
/**
* 测试使用字节数组形式移动文件
*/
@Test
public void testMove()throws Exception{
}
}
步骤二:实现文件移动
首先,创建文件字节输入流FileInputStream类的对象和文件字节输出流
FileOutputStream类的对象;然后,使用循环。在循环中,使用FileInputStream类的read(byte[])方法从文件fos.dat中读取数据;使用FileOutputStream类的write(byte[])方法将读取到的数据写入src下的fos_move.dat文件中,直到read(byte[])方法返回-1,则退出循环;最后,将流关闭,以释放资源,代码如下所示:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.junit.Test;
public class TestMoveFile {
/**
* 测试使用字节数组形式移动文件
*/
@Test
public void testMove()throws Exception{
FileInputStream fis
= new FileInputStream("fos.dat");
FileOutputStream fos
= new FileOutputStream("src/fos_move.dat");
int len = -1;
byte[] buf = new byte[32];
while((len = fis.read(buf)) != -1){
fos.write(buf,0,len);
}
System.out.println("移动完毕");
fis.close();
fos.close();
}
}
运行testMove方法,在当前工程的src目录下生成了文件fos_move.dat,该文件的内容与文件fos.dat的内容相同。
本案例的完整代码如下所示:
代码
3 用缓冲流的方式实现文件的移动
使用BufferedInputStream类的read方法和BufferedOutputStream类的write方法实现文件移动。
参考答案
实现此案例需要按照如下步骤进行。
步骤一:添加测试方法testCopy方法
在类TestMoveFile中添加测试方法testMove2,代码如下所示:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.junit.Test;
public class TestMoveFile {
/**
* 测试基于缓冲流的复制文件
*/
@Test
public void testMove2()throws Exception{
}
}
步骤二:实现文件复制
使用BufferedInputStream和BufferedOutputStream实现文件复制的详细过程如下:
1)首先,创建文件字节输入流FileInputStream类的对象,接着使用该文件字节输入流对象作为参数构造缓冲字节输入流BufferedInputStream类的对象;
2)首先,创建文件字节输出流FileOutputStream类的对象,接着使用该文件字节输出流对象作为参数构造缓冲字节输出流BufferedOutputStream类的对象;
3)构建循环。在循环中,使用BufferedInputStream类的read方法从文件fos.dat中读取数据;使用BufferedOutputStream类的write方法将读取到的数据写入src目录下的bfos_move.dat文件中,直到read方法返回-1,则退出循环。
4)将流关闭,以释放资源。
代码如下所示:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.junit.Test;
public class TestMoveFile {
/**
* 测试基于缓冲流的复制文件
*/
@Test
public void testMove2()throws Exception{
FileInputStream fis
= newFileInputStream("fos.dat");
//创建缓冲字节输入流
BufferedInputStream bis
= newBufferedInputStream(fis);
FileOutputStream fos
= newFileOutputStream("src/bfos_move.dat");
BufferedOutputStream bos
= newBufferedOutputStream(fos);
int d = -1;
while((d = bis.read()) != -1){
bos.write(d);
}
System.out.println("移动完毕");
bis.close();
bos.close();
}
}
运行testMove2方法,在当前工程的src目录下生成了文件bfos_move.dat,该文件的内容与文件fos.dat的内容相同。
本案例的完整代码如下所示:
代码
4 实现empList的序列化和反序列化
实现empList的序列化和反序列化,详细要求如下:
1)在List集合中存放Emp类型的对象;
2)将List集合序列化到文件emplist.obj中;
3) 从文件emplist.obj中将List集合反序列化取出并打印到控制台。
参考答案
实现此案例需要按照如下步骤进行。
步骤一:创建Emp类
创建Emp类,代码如下所示:
import java.io.Serializable;
/**
* 实现序列化接口后该类可以被序列化
*/
public class Emp implements Serializable{
/**
* 版本号
*/
private static finallongserialVersionUID = 1L;
private String name;
private int age;
private String gender;
private double salary;
public Emp(String name, int age, String gender, double salary) {
this.name = name;
this.age = age;
this.gender = gender;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Emp [name=" + name + ", age=" + age + ", gender=" + gender
+ ", salary=" + salary + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
特别需要注意的是该类实现了Serializable接口。实现该接口不需要重写任何方法,其只是作为可序列化的标志。
步骤二:新建测试方法
首先,新建类TestSerialEmps类中新建测试方法testWiter,代码如下所示:
import org.junit.Test;
/**
* 实现对象的序列化与反序列化
*/
public class TestSerialEmps {
/**
* 使用OOS实现对象的序列化
*/
@Test
public void testWiter()throws Exception{
}
}
步骤三:序列化List对象到文件中
将List对象序列化到文件emplist.obj中的详细过程如下:
1)构造List对象;
2)创建文件字节输出流FileOutputStream类的对象,接着使用该文件字节输出流对象作为参数构造对象字节输出流ObjectOutputStream类的对象;
3)使用ObjectOutputStream类的writeObject方法将List对象写入到文件emplist.obj中;
4)关闭oos对象流,以释放资源。
代码如下所示:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
/**
* 实现对象的序列化与反序列化
*/
public class TestSerialEmps {
/**
* 使用OOS实现对象的序列化
*/
@Test
public void testWiter()throws Exception{
FileOutputStream fos
= new FileOutputStream("emplist.obj");
ObjectOutputStream oos
= new ObjectOutputStream(fos);
List<Emp> emps = new ArrayList<Emp>();
emps.add(new Emp("张三", 33, "男", 9000));
emps.add(new Emp("李四", 26, "男", 5000));
emps.add(new Emp("王五", 48, "男", 34000));
oos.writeObject(emps);
System.out.println("序列化完毕");
oos.close();
}
}
运行testWiter方法,在当前工程下生成了文件emplist.obj,该文件的内容是二进制文本,无法读懂其中的内容。
List对象可以直接进行序列化,说明List接口继承了Serializable接口。
步骤四:新建测试方法testRead
在TestSerialEmps类中,新建测试方法testRead,代码如下所示:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
/**
* 实现对象的序列化与反序列化
*/
public class TestSerialEmps {
/**
* 使用OOS实现对象的序列化
*/
@Test
public void testWiter()throws Exception{
... ...
}
/**
* 使用OIS实现对象的反序列化
*/
@Test
public void testRead()throws Exception{
}
}
步骤五:实现对Emp对象的反序列化
将List对象从文件emplist.obj反序列化读取出来的详细过程如下:
1)创建文件字节输入流FileInputStream类的对象,接着使用该文件字节输入流对象作为参数构造对象字节输入流ObjectInputStream类的对象;
2)使用ObjectInputStream类的readObject方法将List对象从emplist.obj文件中读取出来;
3)关闭ois对象流,以释放资源。
代码如下所示:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
/**
* 实现对象的序列化与反序列化
*/
public class TestSerialEmps {
/**
* 使用OOS实现对象的序列化
*/
@Test
public void testWiter()throws Exception{
... ...
}
/**
* 使用OIS实现对象的反序列化
*/
@Test
public void testRead()throws Exception{
FileInputStream fis
= new FileInputStream("emplist.obj");
ObjectInputStream ois
= new ObjectInputStream(fis);
List emps = (List)ois.readObject();
System.out.println("反序列化完毕");
System.out.println(emps);
ois.close();
}
}
运行testRead方法,控制台输出结果如下所示:
反序列化完毕
[Emp [name=张三, age=33, gender=男, salary=9000.0], Emp [name=李四, age=26, gender=男, salary=5000.0], Emp [name=王五, age=48, gender=男, salary=34000.0]]
从输出结果可以看出,已经将Emp对象反序列化出来了。
本案例中,类TestSerialEmps的完整代码如下所示:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
/**
* 实现对象的序列化与反序列化
*/
public class TestSerialEmps {
/**
* 使用OOS实现对象的序列化
*/
@Test
public void testWiter()throws Exception{
FileOutputStream fos
= new FileOutputStream("emplist.obj");
ObjectOutputStream oos
= new ObjectOutputStream(fos);
List<Emp> emps = new ArrayList<Emp>();
emps.add(new Emp("张三", 33, "男", 9000));
emps.add(new Emp("李四", 26, "男", 5000));
emps.add(new Emp("王五", 48, "男", 34000));
oos.writeObject(emps);
System.out.println("序列化完毕");
oos.close();
}
/**
* 使用OIS实现对象的反序列化
*/
@Test
public void testRead()throws Exception{
FileInputStream fis
= new FileInputStream("emplist.obj");
ObjectInputStream ois
= new ObjectInputStream(fis);
List emps = (List)ois.readObject();
System.out.println("反序列化完毕");
System.out.println(emps);
ois.close();
}
}
隐藏
类Emp的完整代码如下所示:
代码
5 简述Serializable接口和transient关键字的意义
参考答案
1)ObjectOutputStream在对对象进行序列化时有一个要求,就是需要序列化的对象所属的类必须实现Serializable接口。实现该接口不需要重写任何方法。其只是作为可序列化的标志。
2)对象在序列化后得到的字节序列往往比较大,有时我们在对一个对象进行序列化时可以忽略某些不必要的属性,从而对序列化后得到的字节序列”瘦身”。关键字 transient表示被该关键字修饰的属性在序列化时其值将被忽略。
6 名称解释:ISO8859-1,GBK,UTF-8
参考答案
1) ISO8859-1: 西文编码就是ASCII,一个英文字母一个字节。
2)GBK:中文编码是GB2312的超集, 1-2变长编码, 英文与ASCII一致, 中文2个字节,可以对20000多个汉字进行编码。
3)UTF-8: 1到4字节的变长编码, 英文与ascII一致,中文3个字节。
7 分别简述ISR和OSW的工作原理
参考答案
InputStreamReader字符输入流。使用该流可以设置字符集,并按照指定的字符集从字节流中按照指定编码将字节数据转换为字符数据并读取。
OutputStreamReader字符输出流。使用该流可以设置字符集,并按照指定的字符集将字符转换为对应的字节后通过该流写出。
8 读取文本文件中的每一行数据信息,求其和再存入最后一行
文本文件pw.txt的内容如下所示:
大家好!
hello!
bye!
操作完毕之后的文本文件pw.txt的内容如下所示:
大家好!
hello!
bye!
大家好!hello!bye!
参考答案
实现此案例需要按照如下步骤进行。
步骤一:新建TestBrAndPw类,添加测试方法testBrAndPw方法
首先,新建名为TestBrAndPw的类,并在类中添加单元测试方法testBrAndPw,代码如下所示:
import org.junit.Test;
public class TestBrAndPw {
/**
* 使用BufferedReader和PrintWriter
*/
@Test
public void testBrAndPw() throws Exception {
}
}
步骤二:读取文本文件的所有行
首先,创建BufferedReader类的对象,并调用该对象的 readLine 方法逐一读取文件中的每行文本连接为一个字符串,代码如下所示:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import org.junit.Test;
public class TestBrAndPw {
/**
* 使用BufferedReader和PrintWriter
*/
@Test
public void testBrAndPw() throws Exception {
FileInputStream fis = new FileInputStream("pw.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String line = "";
String all = "";
while ((line = br.readLine()) != null) {
all += line;
System.out.println(line);
}
}
}
步骤三:使用PrintWriter对象写出数据
PrintWriter是带有行刷新的缓冲字符输出流,它提供了丰富的重载print与println方法。其中,println方法在于输出目标数据后自动输出一个系统支持的换行符。
为向文本文件中追加信息,首先创建OutputStream类的对象,构造该对象时要使该对象具备追加功能;然后,使用OutputStream类的对象构造 PrintWriter类的对象,最后调用 println 方法写入文本,并关闭BufferedReader 对象和PrintWriter对象。代码如下所示:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import org.junit.Test;
public class TestBrAndPw {
/**
* 使用BufferedReader和PrintWriter
*/
@Test
public void testBrAndPw() throws Exception {
FileInputStream fis = new FileInputStream("pw.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String line = "";
String all = "";
while ((line = br.readLine()) != null) {
all += line;
System.out.println(line);
}
OutputStream os=new FileOutputStream("pw.txt",true);
PrintWriter pw = new PrintWriter(os,true);
System.out.println(all);
pw.println();
pw.println(all);
br.close();
pw.close();
}
}
运行上述代码,文本文件pw.txt文件末尾多了一行数据,这一行的内容为pw.txt文本文件中的每一行数据信息累加的和。