其他流
1、转换流
InputStreamReader:将InputStream转换为Reader
- 实现将字节的输入流按指定字符集转换为字符的输入流
- 需要和InputStream“套接
- 构造器
- public InputStreamReader(InputStreamin)
- public InputSreamReader(InputStreamin,StringcharsetName)
- 如:Reader isr= new InputStreamReader(System.in,”gbk”);
OutputStreamWriter:将Writer转换为OutputStream
- 实现将字符的输出流按指定字符集转换为字节的输出流。
- 需要和OutputStream“套接”。
- 构造器
- public OutputStreamWriter(OutputStreamout)
- public OutputSreamWriter(OutputStreamout,StringcharsetName)
字节流中的数据都是字符时,转成字符流操作更高效。
很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。
import org.junit.Test;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;/*** 处理流之二:转换流的使用* 1.转换流:属于字符流* InputStreamReader:将一个字节的输入流转换为字符的输入流* OutputStreamWriter:将一个字符的输出流转换为字节的输出流** 2.作用:提供字节流与字符流之间的转换** 3.解码:字节、字节数组 --->字符数组、字符串* 编码:字符数组、字符串 ---> 字节、字节数组** 4.字符集*/public class InputStreamReaderTest {/*** 此时处理异常的话,仍然应该使用try-catch-finally* InputStreamReader的使用,实现字节的输入流到字符的输入流的转换*/@Testpublic void test() throws IOException {FileInputStream fis = new FileInputStream("dbcp.txt");// InputStreamReader isr = new InputStreamReader(fis);//使用系统默认的字符集//参数2指明了字符集,具体使用哪个字符集,取决于文件dbcp.txt保存时使用的字符集InputStreamReader isr = new InputStreamReader(fis,"UTF-8");//使用系统默认的字符集char[] cbuf = new char[20];int len;while((len = isr.read(cbuf)) != -1){String str = new String(cbuf,0,len);System.out.print(str);}isr.close();}}
import org.junit.Test;import java.io.*;/*** 处理流之二:转换流的使用* 1.转换流:属于字符流* InputStreamReader:将一个字节的输入流转换为字符的输入流* OutputStreamWriter:将一个字符的输出流转换为字节的输出流** 2.作用:提供字节流与字符流之间的转换** 3.解码:字节、字节数组 --->字符数组、字符串* 编码:字符数组、字符串 ---> 字节、字节数组** 4.字符集*/public class InputStreamReaderTest {/*** 此时处理异常的话,仍然应该使用try-catch-finally* 综合使用InputStreamReader和OutputStreamWriter*/@Testpublic void test2() throws IOException {//1.造文件、造流File file1 = new File("dbcp.txt");File file2 = new File("dbcp_gbk.txt");FileInputStream fis = new FileInputStream(file1);FileOutputStream fos = new FileOutputStream(file2);InputStreamReader isr = new InputStreamReader(fis,"utf-8");OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");//2.读写过程char[] cbuf = new char[20];int len;while((len = isr.read(cbuf)) != -1){osw.write(cbuf,0,len);}//3.关闭资源isr.close();osw.close();}}
2、标准输入输出流
- System.in和System.out分别代表了系统标准的输入和输出设备
- 默认输入设备是:键盘,输出设备是:显示器
- System.in的类型是InputStream
- System.out的类型是PrintStream,其是OutputStream的子类FilterOutputStream的子类
- 重定向:通过System类的setIn,setOut方法对默认设备进行改变。
- public static void setIn(InputStreamin)
- public static void setOut(PrintStreamout) ```java import org.junit.Test;
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;
/**
- 其他流的使用
- 1.标准的输入、输出流
- 2.打印流
3.数据流 */ public class OtherStreamTest {
/**
- 1.标准的输入、输出流
- 1.1
- System.in:标准的输入流,默认从键盘输入
- System.out:标准的输出流,默认从控制台输出
- 1.2
- System类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流。 *
- 1.3练习:
- 从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,
- 直至当输入“e”或者“exit”时,退出程序。 *
- 方法一:使用Scanner实现,调用next()返回一个字符串
方法二:使用System.in实现。System.in —-> 转换流 —-> BufferedReader的readLine() */ @Test public void test(){ BufferedReader br = null; try { InputStreamReader isr = new InputStreamReader(System.in); br = new BufferedReader(isr);
while (true) {
System.out.println("请输入字符串:");String data = br.readLine();if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) {System.out.println("程序结束");break;}String upperCase = data.toUpperCase();System.out.println(upperCase);
} } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) {
try {br.close();} catch (IOException e) {e.printStackTrace();}
} } } }
[<br />](https://blog.csdn.net/PorkBird/article/details/113727505)<a name="SyczY"></a># 3、打印流- 实现将基本数据类型的数据格式转化为字符串输出- 打印流:PrintStream和PrintWriter- 提供了一系列重载的print()和println()方法,用于多种数据类型的输出- PrintStream和PrintWriter的输出不会抛出IOException异常- PrintStream和PrintWriter有自动flush功能- PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用PrintWriter 类。- System.out返回的是PrintStream的实例```javaimport org.junit.Test;import java.io.*;public class OtherStreamTest {/*** 2. 打印流:PrintStream 和PrintWriter* 2.1 提供了一系列重载的print() 和 println()* 2.2 练习:*/@Testpublic void test2(){PrintStream ps = null;try {FileOutputStream fos = new FileOutputStream(new File("D:\\IO\\text.txt"));// 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)ps = new PrintStream(fos, true);if (ps != null) {// 把标准输出流(控制台输出)改成文件System.setOut(ps);}for (int i = 0; i <= 255; i++) { // 输出ASCII字符System.out.print((char) i);if (i % 50 == 0) { // 每50个数据一行System.out.println(); // 换行}}} catch (FileNotFoundException e) {e.printStackTrace();} finally {if (ps != null) {ps.close();}}}}
4、数据流
- 为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流。
- 数据流有两个类:(用于读取和写出基本数据类型、String类的数据)
- DataInputStream和DataOutputStream
- 分别“套接”在InputStream和OutputStream子类的流上
DataInputStream中的方法
boolean readBoolean() byte readByte()char readChar() float readFloat()double readDouble() short readShort()long readLong() int readInt()String readUTF() void readFully(byte[s] b)
DataOutputStream中的方法
将上述的方法的read改为相应的write即可 ```java import org.junit.Test; import java.io.*;
public class OtherStreamTest {
/**
* 3.数据流* 3.1 DataInputStream 和 DataOutputStream* 3.2 作用:用于读取或写出基本数据类型的变量或字符串** 练习:将内存中的字符串、基本数据类型的变量写出到文件中。** 注意:处理异常的话,仍然应该使用try-catch-finally.*/@Testpublic void test3() throws IOException {//1.DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));//2.dos.writeUTF("刘刚");dos.flush();//刷新操作,将内存中的数据写入文件dos.writeInt(23);dos.flush();dos.writeBoolean(true);dos.flush();//3.dos.close();}/*** 将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。** 注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!*/@Testpublic void test4() throws IOException {//1.DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));//2.String name = dis.readUTF();int age = dis.readInt();boolean isMale = dis.readBoolean();System.out.println("name = " + name);System.out.println("age = " + age);System.out.println("isMale = " + isMale);//3.dis.close();}
}
<a name="nH1oB"></a># 5、对象流<a name="wBmwi"></a>## 5.1、对象序列化机制的理解- ObjectInputStream和OjbectOutputSteam- 用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。- 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制- 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制- ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量- 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原来的Java对象- 序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原- 序列化是RMI(Remote Method Invoke –远程方法调用)过程的参数和返回值都必须实现的机制,而RMI 是JavaEE的基础。因此序列化机制是JavaEE平台的基础- 如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一。否则,会抛出NotSerializableException异常- Serializable- Externalizable<a name="ktCu1"></a>## 5.2、对象流序列化与反序列化字符串操作```javaimport org.junit.Test;import java.io.*;/*** 对象流的使用* 1.ObjectInputStream 和 ObjectOutputStream* 2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。*/public class ObjectTest {/*** 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去* 使用ObjectOutputStream实现*/@Testpublic void test(){ObjectOutputStream oos = null;try {//创造流oos = new ObjectOutputStream(new FileOutputStream("object.dat"));//制造对象oos.writeObject(new String("秦始皇陵欢迎你"));//刷新操作oos.flush();} catch (IOException e) {e.printStackTrace();} finally {if(oos != null){//3.关闭流try {oos.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 反序列化:将磁盘文件中的对象还原为内存中的一个java对象* 使用ObjectInputStream来实现*/@Testpublic void test2(){ObjectInputStream ois = null;try {ois = new ObjectInputStream(new FileInputStream("object.dat"));Object obj = ois.readObject();String str = (String) obj;System.out.println(str);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {if(ois != null){try {ois.close();} catch (IOException e) {e.printStackTrace();}}}}}
5.3、自定义类实现序列化与反序列化操作
若某个类实现了Serializable接口,该类的对象就是可序列化的
- 创建一个ObjectOutputStream
- 调用ObjectOutputStream对象的writeObject(对象) 方法输出可序列化对象
- 注意写出一次,操作flush()一次
反序列化
- 创建一个ObjectInputStream对象调用readObject() 方法读取流中的对象
- 强调:如果某个类的属性不是基本数据类型或String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的Field 的类也不能序列化 ```java import java.io.Serializable;
/**
- Person需要满足如下的要求,方可序列化
1.需要实现接口:Serializable */ public class Person implements Serializable { public static final long serialVersionUID = 475463534532L;
private String name; private int age;
public Person() { }
public Person(String name, int age) {
this.name = name;this.age = age;
}
@Override public String toString() {
return "Person{" +"name='" + name + '\'' +", age=" + age +'}';
}
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;
} }
```javaimport org.junit.Test;import java.io.*;/*** 对象流的使用* 1.ObjectInputStream 和 ObjectOutputStream* 2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。** 3.要想一个java对象是可序列化的,需要满足相应的要求。见Person.java** 4.序列化机制:* 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种* 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。* 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。**/public class ObjectTest {/*** 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去* 使用ObjectOutputStream实现*/@Testpublic void test(){ObjectOutputStream oos = null;try {//创造流oos = new ObjectOutputStream(new FileOutputStream("object.dat"));//制造对象oos.writeObject(new String("秦始皇陵欢迎你"));//刷新操作oos.flush();oos.writeObject(new Person("李时珍",65));oos.flush();} catch (IOException e) {e.printStackTrace();} finally {if(oos != null){//3.关闭流try {oos.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 反序列化:将磁盘文件中的对象还原为内存中的一个java对象* 使用ObjectInputStream来实现*/@Testpublic void test2(){ObjectInputStream ois = null;try {ois = new ObjectInputStream(new FileInputStream("object.dat"));Object obj = ois.readObject();String str = (String) obj;Person p = (Person) ois.readObject();System.out.println(str);System.out.println(p);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {if(ois != null){try {ois.close();} catch (IOException e) {e.printStackTrace();}}}}}
5.4、serialVersionUID的理解
凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
- private static final long serialVersionUID;
- serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容
- 如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID可能发生变化。故建议,显式声明。
- 简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException) ```java import java.io.Serializable;
/**
- Person需要满足如下的要求,方可序列化
- 1.需要实现接口:Serializable
- 2.当前类提供一个全局常量:serialVersionUID
- 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性
- 也必须是可序列化的。(默认情况下,基本数据类型可序列化)
补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量 */ public class Person implements Serializable { public static final long serialVersionUID = 475463534532L;
private String name; private int age; private int id;
public Person() { }
public Person(String name, int age, int id) {
this.name = name;this.age = age;this.id = id;
}
@Override public String toString() {
return "Person{" +"name='" + name + '\'' +", age=" + age +", id=" + id +'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
} }
```javaimport org.junit.Test;import java.io.*;/*** 对象流的使用* 1.ObjectInputStream 和 ObjectOutputStream* 2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。** 3.要想一个java对象是可序列化的,需要满足相应的要求。见Person.java** 4.序列化机制:* 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种* 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。* 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。**/public class ObjectTest {/*** 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去* 使用ObjectOutputStream实现*/@Testpublic void test(){ObjectOutputStream oos = null;try {//创造流oos = new ObjectOutputStream(new FileOutputStream("object.dat"));//制造对象oos.writeObject(new String("秦始皇陵欢迎你"));//刷新操作oos.flush();oos.writeObject(new Person("李时珍",65,0));oos.flush();} catch (IOException e) {e.printStackTrace();} finally {if(oos != null){//3.关闭流try {oos.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 反序列化:将磁盘文件中的对象还原为内存中的一个java对象* 使用ObjectInputStream来实现*/@Testpublic void test2(){ObjectInputStream ois = null;try {ois = new ObjectInputStream(new FileInputStream("object.dat"));Object obj = ois.readObject();String str = (String) obj;Person p = (Person) ois.readObject();System.out.println(str);System.out.println(p);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {if(ois != null){try {ois.close();} catch (IOException e) {e.printStackTrace();}}}}}
5.5、自定义类可序列化的其它要求
import java.io.Serializable;/*** Person需要满足如下的要求,方可序列化* 1.需要实现接口:Serializable* 2.当前类提供一个全局常量:serialVersionUID* 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性* 也必须是可序列化的。(默认情况下,基本数据类型可序列化)*** 补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量**/public class Person implements Serializable{public static final long serialVersionUID = 475463534532L;private String name;private int age;private int id;private Account acct;public Person(String name, int age, int id) {this.name = name;this.age = age;this.id = id;}public Person(String name, int age, int id, Account acct) {this.name = name;this.age = age;this.id = id;this.acct = acct;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", id=" + id +", acct=" + acct +'}';}public int getId() {return id;}public void setId(int id) {this.id = id;}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 Person(String name, int age) {this.name = name;this.age = age;}public Person() {}}class Account implements Serializable{public static final long serialVersionUID = 4754534532L;private double balance;@Overridepublic String toString() {return "Account{" +"balance=" + balance +'}';}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}public Account(double balance) {this.balance = balance;}}
import org.junit.Test;import java.io.*;/*** 对象流的使用* 1.ObjectInputStream 和 ObjectOutputStream* 2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。** 3.要想一个java对象是可序列化的,需要满足相应的要求。见Person.java** 4.序列化机制:* 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种* 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。* 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。*/public class ObjectTest {/*** 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去* 使用ObjectOutputStream实现*/@Testpublic void test(){ObjectOutputStream oos = null;try {//创造流oos = new ObjectOutputStream(new FileOutputStream("object.dat"));//制造对象oos.writeObject(new String("秦始皇陵欢迎你"));//刷新操作oos.flush();oos.writeObject(new Person("李时珍",65));oos.flush();oos.writeObject(new Person("张学良",23,1001,new Account(5000)));oos.flush();} catch (IOException e) {e.printStackTrace();} finally {if(oos != null){//3.关闭流try {oos.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 反序列化:将磁盘文件中的对象还原为内存中的一个java对象* 使用ObjectInputStream来实现*/@Testpublic void test2(){ObjectInputStream ois = null;try {ois = new ObjectInputStream(new FileInputStream("object.dat"));Object obj = ois.readObject();String str = (String) obj;Person p = (Person) ois.readObject();System.out.println(str);System.out.println(p);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {if(ois != null){try {ois.close();} catch (IOException e) {e.printStackTrace();}}}}}
6、随机存储文件流
- RandomAccessFile 声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了DataInput、DataOutput这两个接口,也就意味着这个类既可以读也可以写。
- RandomAccessFile 类支持“随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件
- 支持只访问文件的部分内容
- 可以向已存在的文件后追加内容
- RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。RandomAccessFile类对象可以自由移动记录指针:
- long getFilePointer():获取文件记录指针的当前位置
- void seek(long pos):将文件记录指针定位到pos位置
- 构造器
- public RandomAccessFile(Filefile, Stringmode)
- public RandomAccessFile(Stringname, Stringmode)
- 创建RandomAccessFile类实例需要指定一个mode 参数,该参数指定RandomAccessFile的访问模式:
- r: 以只读方式打开
- rw:打开以便读取和写入
- rwd:打开以便读取和写入;同步文件内容的更新
- rws:打开以便读取和写入;同步文件内容和元数据的更新
- 如果模式为只读r。则不会创建文件,而是会去读取一个已经存在的文件,如果读取的文件不存在则会出现异常。如果模式为rw读写。如果文件不存在则会去创建文件,如果存在则不会创建。
6.1、RandomAccessFile实现数据的读写操作
```java import org.junit.Test;
import java.io.File; import java.io.IOException; import java.io.RandomAccessFile;
/**
- RandomAccessFile的使用
- 1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
- 2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
- 3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖) */ public class RandomAccessFileTest {
@Test public void test(){
RandomAccessFile raf1 = null; RandomAccessFile raf2 = null; try {
raf1 = new RandomAccessFile(new File("爱情与友情.jpg"),"r");raf2 = new RandomAccessFile(new File("爱情与友情1.jpg"),"rw");byte[] buffer = new byte[1024];int len;while((len = raf1.read(buffer)) != -1){raf2.write(buffer,0,len);}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(raf1 != null){try {raf1.close();} catch (IOException e) {e.printStackTrace();}}if(raf2 != null){try {raf2.close();} catch (IOException e) {e.printStackTrace();}}
} }
@Test public void test2() throws IOException {
RandomAccessFile raf1 = new RandomAccessFile(“hello.txt”,”rw”);
raf1.write(“xyz”.getBytes());
raf1.close();
6.2、RandomAccessFile实现数据的插入操作
```java import org.junit.Test;
import java.io.File; import java.io.IOException; import java.io.RandomAccessFile;
/**
- RandomAccessFile的使用
- 1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
- 2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
- 3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
- 如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖) *
4.可以通过相关的操作,实现RandomAccessFile“插入”数据的效果 */ public class RandomAccessFileTest {
/**
使用RandomAccessFile实现数据的插入效果 */ @Test public void test3() throws IOException { RandomAccessFile raf1 = new RandomAccessFile(“hello.txt”,”rw”);
raf1.seek(3);//将指针调到角标为3的位置 //保存指针3后面的所有数据到StringBuilder中 StringBuilder builder = new StringBuilder((int) new File(“hello.txt”).length()); byte[] buffer = new byte[20]; int len; while((len = raf1.read(buffer)) != -1){
builder.append(new String(buffer,0,len)) ;
} //调回指针,写入“xyz” raf1.seek(3); raf1.write(“xyz”.getBytes());
//将StringBuilder中的数据写入到文件中 raf1.write(builder.toString().getBytes());
raf1.close();
//思考:将StringBuilder替换为ByteArrayOutputStream } } ```
7、NIO.2中Path、Paths、Files类的使用
- Java NIO (New IO,Non-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。
Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。
|-----java.nio.channels.Channel|-----FileChannel:处理本地文件|-----SocketChannel:TCP网络编程的客户端的Channel|-----ServerSocketChannel:TCP网络编程的服务器端的Channel|-----DatagramChannel:UDP网络编程中发送端和接收端的Channel12345
随着JDK 7 的发布,Java对NIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为NIO.2。因为NIO 提供的一些功能,NIO已经成为文件处理中越来越重要的部分。
- 早期的Java只提供了一个File类来访问文件系统,但File类的功能比较有限,所提供的方法性能也不高。而且,大多数方法在出错时仅返回失败,并不会提供异常信息。
- NIO. 2为了弥补这种不足,引入了Path接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。Path可以看成是File类的升级版本,实际引用的资源也可以不存在。
在以前IO操作都是这样写的:
import java.io.File;File file = new File(“index.html”);
但在Java7 中,我们可以这样写:
import java.nio.file.Path;import java.nio.file.Paths;Path path = Paths.get(“index.html”);


