转换流:InputStreamReader, OutputStreamWriter;实现字节流与字符流之间的转换
解码:字节数组->字符串 InputStreamReader 输入时实现字节流到字符流的转换,提高操作的效率(前提是:数据是文本文件)
编码:字符串->字节数组 OutputStreamWriter 输出时实现字符流到字节流的转换
未处理异常版:
@Test
public void test() {
//解码
File file1 = new File("hello.txt");
FileInputStream fis = new FileInputStream(file1);
InputStreamReader isr = new InputStreamReader(fis, "GBK");
BufferedReader br = new BufferedReader(isr);
//编码
File file2 = new File("hello2.txt");
FileOutputStream fos = new FileOutputStream(file2);
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
BufferedWriter bw = new BufferedWriter(osw);
String str = null;
while((str = br.readLine()) != null) {
bw.write(str);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
}
标准输入输出流:
标准输入流:System.in 从键盘读入数据
标准输出流:System.out 从显示器输出数据
打印流(了解): 字节流:PrintStream 字符流:PrintWriter
FileOutputStream fos = new FileOutputStream("hello.txt");
PrintStream ps = new PrintStream(fos, true);//创建打印输出流,true为设置成自动刷新模式(写入换行符或字节‘\n’时,都会刷新缓冲区)
if(ps != null){
System.setOut(ps);//重新设置输出的位置。把标准输出流(控制台输出)改成文件
}
//往ps指向的文件内写入(省略)
ps.close();
数据流(了解):用来处理基本数据类型、String、字节数组的数据:DataInputStream DataOutputStream
FileOutputStream file = new FileOutputStream("hello.txt");
DataOutputStream dos = new DataOutputStream(file);
dos.writeUTF("我爱你 ");
dos.writeBoolean(true);
dos.writeLong(123456789);
dos.close();
//上面的写出来直接打开看是乱码,要用相同的数据流读取才能看到
DataInputStream dis = new DataInputStream(new FileInputStream("hello.txt"));
//byte[] b = new byte[20];
//int len;
//while((len = dis.read(b))!= -1){
// System.out.println(new String(b, 0, len));//这样写出来的也是乱码
//}
//正确做法
String str = dis.readUTF();
boolean b = dis.readBoolean();
long l = dis.readLong();
dis.close();
对象流:ObjectInputStream, ObjectOutputSteam
1.对象序列化机制:
允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
2.对象序列化过程(Serialize):将内存中的对象通过ObjectOutputStream转换为二进制流,存储在硬盘中
3.对象反序列化过程(Deserialize):将硬盘中的文件通过ObjectInputStream转换为相应的对象
4.要实现序列化的类:
1.要求此类是可序列化的:该类必须实现如下两个接口之一:Serializable、Externalizable
2.要求类的属性同样要实现上述接口
3.提供一个版本号 private static final long serialVersionUID = 515841561684L;
4.不能序列化static和transient修饰的属性
//序列化:将对象写入到磁盘或者进行网络传输。要求对象必须实现序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test3.txt"));
Person p = new Person("韩梅梅",18,"中华大街",new Pet());
oos.writeObject(p);
oos.flush();
oos.close();
//反序列化:将磁盘中的对象数据源读出。
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test3.txt"));
Person p1 = (Person)ois.readObject();
System.out.println(p1.toString());
ois.close();
随机存取文件流:RandomAccessFile 类:支持随机访问
1.既可以充当一个输入流,也可以充当一个输出流
2.支持从文件的开头读取、写入。若输出的文件不存在,直接创建,若存在,则是对原有文件内容的覆盖
3.支持从文件的任意位置读取、写入(插入)
构造器
public RandomAccessFile(File file, String mode);
public RandomAccessFile(String name, String mode);
创建 RandomAccessFile 类实例需要指定一个 mode 参数,该参数指定 RandomAccessFile 的访问模式:
r: 以只读方式打开
rw:打开以便读取和写入
rwd:打开以便读取和写入;同步文件内容的更新
rws:打开以便读取和写入;同步文件内容和元数据的更新
//全文读取,写入
RandomAccessFile raf1 = new RandomAccessFile(new File("hello.txt"), "r");
RandomAccessFile raf2 = new RandomAccessFile(new File("hello1.txt"), "rw");
long getFilePointer():获取文件记录指针的当前位置
void seek(long pos):将文件记录指针定位到 pos 位置
package test;
import java.io.*;
import org.junit.Test;
public class TestRandomAccessFile {
@Test
public void testRandomAccessFile() {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(new File("hello.txt"), "rw");
raf.seek(4);
StringBuffer sb = new StringBuffer();//使用一个String的缓冲流,效率比都写到String中更高
int len;
byte[] b = new byte[5];
while((len = raf.read(b)) != -1) {
sb.append(new String(b, 0, len));
}
raf.seek(4);//这里返回指向该点的指针
raf.write("xsd".getBytes());//注意这里不能只写写入int或String型的
raf.write(sb.toString().getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(raf != null) {
try {
raf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}