转换流
作用:
- 实现字节流到字符流的转换
- 解决中文乱码的问题
中文编码:
- gb2312 (采用两个字节保存字符汉字,英文数字一个字节)
- GBK (采用两个字节保存字符汉字,英文数字一个字节)
- GB18030 (英文数字都是一个字节,中文是两个或四个字节)
- Unicode字符集(包含每个国家的所有字符)国际通用
- unicode编码 使用两个字节—65536个字符,浪费空间
- 为了节省空间使用转码形式
- utf-8 使用 1 、2、3个字节
- (EF BB BF 记事本添加的BOM(Byte Order Mark)头,编码的标记)
- utf-16 使用两个字节—65536个字符 (FF FE 小端(尾) FE FF 大端(尾))
- utf-32 使用4个字节
- 台湾 big5
- ANSI:在简体中文Windows操作系统中, ANSI 编码代表 GBK 编码
- 只有转换流才能指定读取和写入的字符集
InputStreamReader类
- InputStreamReader:字节字符转换输入流,将字节输入流转换为字符输入流
- 注意:当一个流的存在的意义是为了实例化另外一个流,则这个流不需要手动进行关闭
//使用默认的字符集【GBK】进行实例化转换流 InputStreamReader reader1 = new InputStreamReader(new FileInputStream(new File("file/input1.txt"))); //使用指定字符集进行实例化转换流 //字符集一般使用字符串直接传参,不区分大小写,但是,如果字符集书写有误的话,则会跑出java.io.UnsupportedEncodingException InputStreamReader reader2 = new InputStreamReader(new FileInputStream(new File("file/input1.txt")),"UTF-8"); //3.读取 char[] arr = new char[16]; int len = 0; while((len = reader.read(arr)) != -1) { String string = new String(arr, 0, len); System.out.println(string); } reader.close();
OutputStreamWriter类
- OutputStreamWriter:字符转换输出流,将内存中的字符转成字节保存到硬盘中。
//注意:对于所有的输出流而言,文件可以不存在,在进行写入的过程中可以自动进行创建 //但是,对于所有的输入流而言,文件必须先存在,然后才能操作,否则,会抛出FileNotFounedException //如果不想覆盖源文件中的内容时,则在传参的时候,设置一个参数为true OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file,true), "utf-8"); //3.写入 writer.write("变秃了,也变强了"); //4.刷新 writer.flush(); //5.关闭 writer.close();
缓冲流
作用
- 主要是为了增强基础流的功能而存在的,提高了流的工作效率【读写效率】
- 该流自己创建一个缓存区域保存数据。读数据时先读到缓存区,再读到硬盘中。写数据也是如此
- 注意:如果使用记事本创建的文件,文件是utf-8或者unicode编码,文件的前面有一个BOM(Byte Order Mark)头
- BOM作用指定文件使用的编码类型。GBK编码没有添加bom头。
- utf-8:EF BB BF
- unicode 小端: FF FE 66 00
- unicode 大端:FE FF 00 66
BufferedInputStream类
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("tt.txt")); byte[] arr = new byte[8]; int len = 0; while ((len=bis.read(arr))!=-1){ String str = new String(arr,0,len); System.out.println(str); } bis.close();
BufferedOutputStream类
//如果不想覆盖源文件中的内容时,则在传参的时候,设置一个参数为true BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("tt.txt",true)); bos.write("努力".getBytes()); bos.flush(); bos.close();
BufferedReader类
BufferedReader br = new BufferedReader(new >FileReader("tt.txt")); //读取一行 String str = br.readLine(); System.out.println(str);
BufferedWriter类
BufferedWriter bw = new BufferedWriter(new FileWriter("tt.txt",true)); bw.write("\r\n努力"); // 作用:主要就是为了换行 bw.newLine(); bw.flush(); bw.close();
内存流
作用
- 输入和输出都是从文件中来的,当然,也可将输出输入的位置设置在内存上,这就需要
ByteArrayInputStream
和ByteArrayOutputStream
- ByteArrayInputStream:将内容写入到内存中,是Inputstream的子类
- ByteArrayOutputStream:将内存中数据输出,是OutputStream的子类
- 此时的操作应该以内存为操作点
- 注意:内存操作流的操作对象,一定是以内存为主准,不要以硬盘为准。
- 完成一个字母大小写转换的程序:
//定义一个字符串,全部由大写字母组成 String string = "HELLOWORLD"; //内存输入流 //向内存中输出内容,注意:跟文件读取不一样,不设置文件路径 ByteArrayInputStream bis = new ByteArrayInputStream(string.getBytes()); //内存输出流 //准备从内存中读取内容,注意:跟文件读取不一样,不设置文件路径 ByteArrayOutputStream bos = new ByteArrayOutputStream(); int temp = 0; //read()方法每次只读取一个字符 while((temp = bis.read()) != -1) { //将读取的数字转为字符 char c = (char)temp; //将字符变为大写 bos.write(Character.toLowerCase(c)); } //循环结束之后,所有的数据都在ByteArrayOutputStream中 //取出内容,将缓冲区内容转换为字符串 String newString = bos.toString(); //关闭流 bis.close(); bos.close(); System.out.println(newString);
标准输入输出流
- Java的标准输入/输出分别通过System.in和System.out实现,默认情况下分别代表是键盘和显示器
- PrintStream类:PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
- PrintWriter类:向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream中的所有 print方法。它不包含用于写入原始字节的方法。
//PrintStream ps = new PrintStream("tt.txt"); PrintWriter pw = new PrintWriter("tt.txt"); pw.println(true); pw.println(3.14); pw.println(100); pw.println("奋斗123"); pw.flush(); pw.close();
//注意:默认打印到控制台,但是,如果采用setOut方法进行重定向之后,将输出到指定的文件中 PrintStream print = new PrintStream(new FileOutputStream(new File("test33.txt"))); /*static void setErr(PrintStream err) 重新分配“标准”错误输出流。 static void setIn(InputStream in) 重新分配“标准”输入流。 static void setOut(PrintStream out) 重新分配“标准”输出流。 */ //将标准输出重定向到print的输出流 System.setOut(print); System.out.println("hello world");
FileInputStream inputStream = new FileInputStream(new File("test33.txt")); //setIn System.setIn(inputStream); //System.out.println("请输入内容:"); //默认情况下是从控制台进行获取内容 //但是如果使用setIn方法设置了重定向之后,将从指定文件中获取内容 Scanner sc = new Scanner(System.in); String string = sc.next(); System.out.println(string);
对象流
流中流动的数据是对象
- 将一个对象写入到本地文件中,被称为对象的序列化
- 将一个本地文件中的对象读取出来,被称为对象的反序列化
使用对象流
- ObjectInputStream: 对象输出流
- ObjectOutputStream:对象输入流
注意:
- 序列化对象的类型必须实现
Serializable
接口。否则不能序列化。- 如果向将多个对象序列化到本地,可以借助于集合,【思路:将多个对象添加到集合中,将集合的对象写入到本地文件中,再次读出来,获取到的仍然是集合对象,遍历集合】。
- 对象中那些字段可以不序列化:
transient
修饰属性,被修饰的属性无法序列化静态的字段
- 在要序列化类中添加字段,保证序列化和反序列化是
同一个类
- private static final long serialVersionUID = 100L;
注意:在使用对象流的时候,用于初始化对象流的参数只能是字节流(将对象转换为二进制的形式,然后再把二进制写入文件)
//user对象必须实现序列化,否则报错 User user = new User(1,"sdh"); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("tt.txt"))); oos.writeObject(user); oos.flush(); oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("tt.txt"))); User user = (User) ois.readObject(); System.out.println(user);
RandomAccessFile类
RandomAccessFile
是用来访问那些保存数据记录的文件的,你就可以用seek()方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。但是该类仅限于操作文件。
RandomAccessFile file = new RandomAccessFile("file.txt", "rw"); // 以下向file文件中写数据 file.writeInt(20);// 占4个字节 file.writeDouble(8.236598);// 占8个字节 //这个长度写在当前文件指针的前两个字节处,可用readShort()读取 file.writeUTF("这是一个UTF字符串"); //把文件指针位置设置到文件起始处,从0开始 file.seek(0); //将文件指针跳过3个字节,从当前位置 //file.skipBytes(3); System.out.println(file.readInt()); System.out.println(file.readDouble()); System.out.println(file.readUTF()); //注意readDouble()方法会移动文件指针,所以不用写2。 //file.skipBytes(file.readDouble()); /* 文件复制案例 */ RandomAccessFile fileCopy = new RandomAccessFile("fileCopy.txt", "rw"); int len = (int) file.length();// 取得文件长度(字节数) byte[] b = new byte[len]; //全部读取 file.readFully(b); fileCopy.write(b); System.out.println("复制完成!");
Properties类
- 这个其实是一个集合,放着这里是为了通过io流来学习它的使用
- 是
Map接口
的一个实现类,并且是Hashtable的子类Properties集合
中元素也是以键值对的形式存在的- Properties特点:
- 存储属性名和属性值
- 属性名和属性值都是字符串
- 和流有关系
- 没有泛型
Properties properties = new Properties(); //设置键、值 properties.setProperty("name","xxx"); Set<String> strings = properties.stringPropertyNames(); for (String key : strings) { System.out.println(key+" "+properties.getProperty(key)); } //把上面信息填充到该文件中 properties.list(new PrintStream("prop.properties")); //list也可以打印,输出到控制台,不保存到文件中 properties.list(System.out); //去该文件中加载内容,打印出来 properties.load(new FileReader("prop.properties")); properties.list(System.out); //保存到该文件中 properties.store(new FileWriter("prop.properties"),"xxx"); //读取系统信息 Properties properties1 = System.getProperties(); properties1.list(System.out);