IO流
分类:
- 按照读写数据的基本单位不同,分为 字节流 和 字符流。
- 其中字节流主要指以字节为单位进行数据读写的流,可以读写任意类型的文件。
- 其中字符流主要指以字符(2个字节)为单位进行数据读写的流,只能读写文本文件。
整体结构:
FileWriter类:
用于将字符内容写入文本文件.
测试代码:
package com.lagou.task17; import java.io.FileWriter; import java.io.IOException; public class FileWriterTest { public static void main(String[] args) { // 选中代码后可以使用 ctrl+alt+t 来生成异常的捕获代码等 FileWriter fw = null; try { // 1.构造FileWrite类型的对象与d:/a.txt文件关联 // 若文件不存在,该流会自动创建新的空文件 // 若文件存在,该流会清空文件中的原有内容 fw = new FileWriter("d:/a.txt"); // 以追加的方式创建对象去关联文件 // 若文件不存在则自动创建新的空文件,若文件存在则保留原有数据内容 //fw = new FileWriter("d:/a.txt", true); // 2.通过流对象写入数据内容 每当写入一个字符后则文件中的读写位置向后移动一位 fw.write('a'); // 准备一个字符数组 char[] cArr = new char[]{'h', 'e', 'l', 'l', 'o'}; // 将字符数组中的一部分内容写入进去 fw.write(cArr, 1, 3); // ell // 将整个字符数组写进去 fw.write(cArr); // hello // 刷新流 fw.flush(); System.out.println("写入数据成功!"); } catch (IOException e) { e.printStackTrace(); } finally { // 3.关闭流对象并释放有关的资源 if (null != fw) { try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
FileReader类:
用于从文本文件读取文本数据内容。
测试代码:
package com.lagou.task17; import java.io.FileReader; import java.io.IOException; public class FileReaderTest { public static void main(String[] args) { FileReader fr = null; try { // 1.构造FileReader类型的对象与d:/a.txt文件关联 //fr = new FileReader("d:/a.txt"); fr = new FileReader("d:/b.txt"); // 2.读取数据内容并打印 /* int res = fr.read(); System.out.println("读取到的单个字符是:" + (char)res); // 'a' */ int res = 0; while ((res = fr.read()) != -1) { System.out.println("读取到的单个字符是:" + (char)res + ",对应的编号是:" + res); } // 准备一个字符数组来保存读取到的数据内容 // char[] cArr = new char[5]; // 期望读满字符数组中的一部分空间,也就是读取3个字符放入数组cArr中下标从1开始的位置上 /*int res = fr.read(cArr, 1, 3); System.out.println("实际读取到的字符个数是:" + res); // 3 for (char cv : cArr) { System.out.println("读取到的单个字符是:" + (char)cv); // 啥也没有 a e l 啥也没有 }*/ // 期望读满整个字符数组 /*int res = fr.read(cArr); System.out.println("实际读取到的字符个数是:" + res); // 5 for (char cv : cArr) { System.out.println("读取到的单个字符是:" + (char)cv); // a e l l h }*/ } catch (IOException e) { e.printStackTrace(); } finally { // 3.关闭流对象并释放有关的资源 if (null != fr) { try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
FileOutputStream类:
要用于将图像数据之类的原始字节流写入到输出流.
FileInputStream类:
用于从输入流中以字节流的方式读取图像数据等。
BufferedOutputStream类:
BufferedInputStream类:
BufferedWriter类:
BufferedReader类:
OutputStreamWriter类:
输出字节流转字符流
InputStreamReader类:
输入字节流转字符流。
ObjectOutputStream类:
写对象。
- java.io.ObjectOutputStream类主要用于将一个对象的所有内容整体写入到输出流中。
- 只能将支持 java.io.Serializable 接口的对象写入流中。
- 类通过实现 java.io.Serializable 接口以启用其序列化功能。
- 所谓序列化主要指将一个对象需要存储的相关信息有效组织成字节序列的转化过程。
ObjectInputStream类:
读对象。
- java.io.ObjectInputStream类主要用于从输入流中一次性将对象整体读取出来。
- 所谓反序列化主要指将有效组织的字节序列恢复为一个对象及相关信息的转化过程。
- 序列化版本号
序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时, JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如 果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常 (InvalidCastException)。
- transient关键字
transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行 化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进 去的。
- 经验的分享
当希望将多个对象写入文件时,通常建议将多个对象放入一个集合中,然后将集合这个整体看做一 个对象写入输出流中,此时只需要调用一次readObject方法就可以将整个集合的数据读取出来, 从而避免了通过返回值进行是否达到文件末尾的判断。
相关测试代码:
写入Person对象:
@Test//写入Person对象 public void test8() { FileOutputStream fileOutputStream = null; BufferedOutputStream bufferedOutputStream = null; ObjectOutputStream objectOutputStream = null; try { fileOutputStream = new FileOutputStream("src/com/atguigu/day19/person.bin"); bufferedOutputStream = new BufferedOutputStream(fileOutputStream); objectOutputStream = new ObjectOutputStream(bufferedOutputStream); objectOutputStream.writeObject(new Person("小明", 12, 14)); objectOutputStream.writeObject(new Person("大花", 13, 15)); objectOutputStream.writeObject(new Person("曼曼", 14, 16)); } catch (Exception e) { e.printStackTrace(); } finally { if (objectOutputStream != null) { try { objectOutputStream.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } }
//读取Person对象:
public void test9() { FileInputStream fileInputStream = null; BufferedInputStream bufferedInputStream = null; ObjectInputStream objectInputStream = null; try { fileInputStream = new FileInputStream("src/com/atguigu/day19/person.bin"); bufferedInputStream = new BufferedInputStream(fileInputStream); objectInputStream = new ObjectInputStream(bufferedInputStream); for (int i = 0; i < 3; i++) { Object o = objectInputStream.readObject(); System.out.println(o); } } catch (Exception e) { e.printStackTrace(); } finally { if (objectInputStream != null) { try { objectInputStream.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } }
读取GBK文件:
public void test10() { FileInputStream fis = null; InputStreamReader isr = null; BufferedReader bufferedReader = null; try { fis = new FileInputStream("HashMap_gbk.java"); isr = new InputStreamReader(fis, "gbk"); bufferedReader = new BufferedReader(isr); String line; while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } } catch (Exception e) { e.printStackTrace(); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } }
键盘输入以GBK编码写入文件:
public static void main(String[] args) { InputStream in = System.in; InputStreamReader isr = null; BufferedReader bufferedReader = null; FileOutputStream fos = null; OutputStreamWriter osw = null; BufferedWriter bufferedWriter = null; try { isr = new InputStreamReader(in); bufferedReader = new BufferedReader(isr); fos = new FileOutputStream("keyboard_gbk.txt"); osw = new OutputStreamWriter(fos, "gbk"); bufferedWriter = new BufferedWriter(osw); String line; while ((line = bufferedReader.readLine()) != null) { if (line.equalsIgnoreCase("exit")) { break; } bufferedWriter.write(line); bufferedWriter.newLine(); } } catch (Exception e) { e.printStackTrace(); } finally { if (null != bufferedReader) { try { bufferedReader.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } if (null != bufferedWriter) { try { bufferedWriter.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } }
2种文件拷贝方式测试:
@Test//缓冲流:BufferedInputStream、BufferedOutputStream copy file,,复制700M文件 1.2s public void test() { Long l1=System.currentTimeMillis(); FileInputStream fis = null; BufferedInputStream bis = null; FileOutputStream fos = null; BufferedOutputStream bos = null; byte[] buf = new byte[8192]; try { fis = new FileInputStream("视频.zip"); bis = new BufferedInputStream(fis); fos = new FileOutputStream("视频1.zip"); bos = new BufferedOutputStream(fos); int count; while ((count = bis.read(buf)) != -1) { bos.write(buf, 0, count); } } catch (Exception e) { e.printStackTrace(); } finally { if (null != bis) { try { bis.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } if (null != bos) { try { bos.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } Long l2=System.currentTimeMillis(); System.out.println(l2-l1); } @Test //fileInputStream fileOutputStream 更快 ,复制700M文件 700ms public void test0() { Long l1=System.currentTimeMillis(); FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream("视频.zip"); fileOutputStream = new FileOutputStream("视频2.zip"); byte[] buf = new byte[8192]; int count; while ((count = fileInputStream.read(buf)) != -1) { fileOutputStream.write(buf, 0, count); } } catch (Exception e) { e.printStackTrace(); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } Long l2=System.currentTimeMillis(); System.out.println(l2-l1); }
RandomAccessFile类:
package com.lagou.task17; import java.io.IOException; import java.io.RandomAccessFile; public class RandomAccessFileTest { public static void main(String[] args) { RandomAccessFile raf = null; try { // 1.创建RandomAccessFile类型的对象与d:/a.txt文件关联 raf = new RandomAccessFile("d:/a.txt", "rw"); // 2.对文件内容进行随机读写操作 // 设置距离文件开头位置的偏移量,从文件开头位置向后偏移3个字节 aellhello raf.seek(3); int res = raf.read(); System.out.println("读取到的单个字符是:" + (char)res); // a l res = raf.read(); System.out.println("读取到的单个字符是:" + (char)res); // h 指向了e raf.write('2'); // 执行该行代码后覆盖了字符'e' System.out.println("写入数据成功!"); } catch (IOException e) { e.printStackTrace(); } finally { // 3.关闭流对象并释放有关的资源 if (null != raf) { try { raf.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
补充Hadoop操作流:
读文件:
FileSystem fs = FileSystem.get(context.getConfiguration()); FSDataInputStream pdIn = fs.open(new Path(pdFile)); // 2. 声明高级流对象 BufferedReader reader = new BufferedReader(new InputStreamReader(pdIn, "utf-8")); String line; while ((line=reader.readLine()) != null){ // 获取当前行 01 小米 String[] pdDatas = line.split("\t"); pdMap.put(pdDatas[0],pdDatas[1]); } // while (StringUtils.isNotEmpty(line=reader.readLine())){ // // } // 关流 IOUtils.closeStream(reader);
写文件:
package com.atguigu.mr.outputformat; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.io.NullWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.RecordWriter; import org.apache.hadoop.mapreduce.TaskAttemptContext; import java.io.IOException; /** * 自定义RecordWriter对象 */ public class LogRecordWriter extends RecordWriter<Text, NullWritable> { private String atguiguPath = "F:\\logs\\atguigu.txt"; private String otherPath = "F:\\logs\\other.txt"; private FileSystem fs; private FSDataOutputStream atguiguOut; private FSDataOutputStream otherOut; /** * 进行一些初始化操作 * @param job */ public LogRecordWriter(TaskAttemptContext job) throws IOException { fs = FileSystem.get(job.getConfiguration()); // 创建输出流 atguiguOut = fs.create(new Path(atguiguPath)); otherOut = fs.create(new Path(otherPath)); } /** * 编写自定义输出的逻辑 * @param key * @param value * @throws IOException * @throws InterruptedException */ @Override public void write(Text key, NullWritable value) throws IOException, InterruptedException { // 获取当前key String data = key.toString(); // 判断是否包含atguigu if (data.contains("atguigu")) { atguiguOut.writeBytes(data + "\n"); }else { otherOut.writeBytes(data + "\n"); } } /** * 关闭资源 * @param context * @throws IOException * @throws InterruptedException */ @Override public void close(TaskAttemptContext context) throws IOException, InterruptedException { IOUtils.closeStream(atguiguOut); IOUtils.closeStream(otherOut); } }