Java基础——IO流--转换流、标准输入输出流
转换流: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(); } } } } }