转换流(处理流的一种)
1.转换流:(属于字符流)
InputStreamReader:将一个字节的输入流转换为字符的输入流
OutputStreamWriter:将一个字符的输出流转换为字节的输出流
2.作用:提供字节流和字符流之间的转换
3.解码:字节,字节数组---->字符,字符数组
编码:字符,字符数组---->字节,字节数组
4.字符集
测试InputStreamReader的使用
//测试InputStreamReader的使用,实现字节的输入流到字符的输入流之间的转换
public void test() throws IOException {
FileInputStream fis = new FileInputStream("hello.txt");
InputStreamReader isr = new InputStreamReader(fis);//使用系统默认的字符集
//参数2指明了字符集,具体使用哪种,取决于文件hello.txt保存时使用的字符集
InputStreamReader isr1 = 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.println(str);
}
isr.close();
综合使用InputStreamReader和OutputStreamWriter
@Test
public void test1() throws IOException {
//1.造文件,造流
File file = new File("hello.txt");
File file1 = new File("hello-gbk.txt");
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(file1);
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();
其他流的使用
1.标准的输入,输出流
2.打印流
3.数据流
1.标准的输入,输出流
System.in:标准的输入流,默认从键盘输入 System.out:标准的输入流,默认从控制台输出
1.2
System类的setIn(InputStream is)/setOut(PrintStream ps)方式重新指定输入和输出的流
1.3练习:
从键盘读取字符串,要求将读取到的整行字符串转化为大写输出,然后继续进行输入操作。 直到输入"e"或"exit",退出程序
public static void main(String[] args) throws IOException {
//使用System.in(输入流)实现。System.in--->转换流--->BufferedReader的readLine()
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader 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 s = data.toUpperCase();
System.out.println(s);
}
br.close();
2.打印流
2.打印流:PrintStream和PrintWriter
2.1 提供了一系列重载的print()和println
2.2作用:可以将控制台呈现的东西打印在文件上
3.数据流
3.1 DataInputStream和DataOutputStream
3.2作用:用于读取或写出基本数据类型的变量或字符串
练习:将内存中的字符串,基本数据类型的变量写出到文件中
//注意:应该使用try-catch-finally(这里偷懒直接抛掉了)
@Test
public void test2() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeUTF("黄某");
dos.flush();//刷新操作,将内存中的数据写入文件
dos.writeInt(19);
dos.flush();
dos.writeBoolean(true);
dos.flush();
dos.close();
}
@Test
//将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中
//注意:读取不同类型的数据的顺序要与当初写入文件时,保存数据的顺序一致
public void test3() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
String s = dis.readUTF();
int i = dis.readInt();
boolean b = dis.readBoolean();
System.out.println(s+" "+i+" "+b);
dis.close();
}
对象流
对象流的使用
1.ObjectInputStream和ObjectOutputStream
2.作用:用于存储和读取基本数据类型或对象的处理流。 它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来
public void test4() throws IOException {
/*
序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
使用ObjectOutputStream来实现
*/
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));//生成的文件要通过反序列化才能查看
oos.writeObject(new String("我爱北京天安门"));
oos.flush();//刷新操作
oos.close();
}
@Test
public void test5() throws IOException, ClassNotFoundException {
//反序列化过程,将磁盘文件中的对象还原为内存中的一个java对象
//使用ObjectInputStream来实现
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"));
Object o = ois.readObject();
System.out.println(o);
ois.close();
}
public class Person implements Serializable {
/*Person类需要满足如下的要求,方可序列化
1.需要实现接口SerializableSerializable
2.需要类提供一个全局常量:serialVersionUID
3.除了当前类Person类需要实现SerializableSerializable
接口之外,还必须保证其内部所有属性也必须是可序列化的。(默认情况下,基本数据类型是可序列化的),即Person内部的自定义类的属性所属的类也要实现序列化。
补充:序列化和反序列化不能修饰static和transient修饰的成员变量
*/
public static final long serialVersionUID = 6433858223774886977L;
serialVersionUID的理解
对于序列化后而还没反序列化时,此时serialVersionUID可以作为电脑对Person类的识别码,若你在中途将Person内部进行了修改,那么电脑还可以通过serialVersionUID对你做出的修改做出反应。若没有serialVersionUID,则无法识别
随机存取文件流
/*RandomAccessFile的使用
1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput
2.RandomAccessFile既可以作为一个输入流,也可以作为一个输出流,但是要造2个对象
3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则自动创建。若存在,则会对原有文件进行覆盖(默认情况下,从头开始覆盖)
4.可以通过相关的操作,使用RandomAccessFile实现插入效果
*/
public class RandomAccessFileTest {
@Test
public void test() throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("小哀.jpg"),"r");
RandomAccessFile raf1 = new RandomAccessFile(new File("小哀3.jpg"),"rw");
byte[]buffer = new byte[1024];
int len;
while((len=raf.read(buffer))!=-1){
raf1.write(buffer,0,len);
}
raf.close();
raf1.close();
}
@Test
public void test2() throws IOException {//使用RandomAccessFile实现覆盖效果
RandomAccessFile raf = new RandomAccessFile("hello.txt","rw");
raf.seek(3);//默认为0。将指针调到角标为3的位置,abcdefghijklmn-->abcxyzghijklmn
raf.write("xyz".getBytes());//hello.txt中的abcdefghijklmn-->xyzdefghijklmn
raf.close();
}
//使用RandomAccessFile实现插入效果
@Test
public void test3() throws IOException {
RandomAccessFile raf = new RandomAccessFile("hello.txt","rw");
raf.seek(3);//将指针调到角标为3的位置
//保存指针3后面的所有数据到StringBuilder中
StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
byte[]buffer=new byte[20];
int len;
while((len=raf.read(buffer))!=-1){
builder.append(new String(buffer,0,len));
}
//调回指针,写入"xyz"
raf.seek(3);
raf.write("xyz".getBytes());
//将StringBuilder中的数据写入到文件中
raf.write(builder.toString().getBytes());
raf.close();
}