I/O流详细介绍:https://www.cnblogs.com/wugongzi/p/12092326.html
https://blog.csdn.net/weixin_61619114/article/details/142153736
File相关:
@Test public void testFile() throws IOException { //File:即使文件不存在也不会异常,只是在内存中构建了一个路径对象,可以直接输出路径。 //相对路径,此项目或者此module的根目录:ProjectA/1.txt 或者 ProjectA/moduleA/1.txt //File file = new File("1.txt"); //绝对路径,带盘符 //不同系统路径分割符不同,windows支持 \\ 和 /,unix 支持 / 或者使用 File.separator //File file = new File("E:/a.txt"); //拼接目录E:/a.txt //File file = new File("E:/","a.txt"); //拼接目录E:/a.txt // File file = new File(new File("E:/"), "a.txt"); // System.out.println(file.getAbsolutePath());//物理路径 E:\JavaProject\wmstest\1.txt // System.out.println(file.getPath());//new File时构造参数中的路径 // System.out.println(file.getName());//文件名称 // System.out.println(file.getParent());//new File时构造参数中的路径的上一级路径 // System.out.println(file.length());//文件字节长度 // System.out.println(file.lastModified());//文件最后修改时间戳 //指定目录下文件和目录的名称数组 // Arrays.stream(new File("E:/").list()).forEach(x-> System.out.println(x)); //file.listFiles();//指定目录下文件和目录的File数组 //把E:/a.txt移动到E:/CFPQ/b.txt,原文件剪切并重命名到新目录,要求目标不能存在 // File file1 = new File("E:/a.txt"); // File file2 = new File("E:/CFPQ/b.txt"); // System.out.println(file1.renameTo(file2)); // System.out.println(file1.isDirectory()); // System.out.println(file1.isHidden()); // System.out.println(file1.isFile()); // System.out.println(file1.canRead()); // System.out.println(file1.canWrite()); // System.out.println(file1.exists()); // System.out.println(file1.createNewFile());//创建文件,若已存在 false // File fileDir = new File("E:/test/abc"); // fileDir.mkdir();//创建目录,文件存在或者上层目录不存在,则不创建。 // fileDir.mkdirs();//创建目录,文件存在则不创建,上层目录不存在,则一并创建。 // fileDir.delete();//删除文件或目录,不走回收站,直接删除。 }
缓冲流:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
加速读写,原理:缓冲流把数据从原始流成块读入或把数据积累到一个大数据块后再成批写出,通过减少资源的读写次数来加快程序的执行。
关闭缓冲流会自动关闭其中的输入输出流,不需要再重复关闭。
ObjectInputStream(反序列化)和ObjectOutputStream(序列化)说明:
1、主要用于基本数据类型和对象的处理流。
2、不能序列化static和transient修饰的成员变量。
3、要序列化的类需要继承Serializable接口或者Externalizable接口。
4、要序列化的类需要添加 序列版本号,不加默认会生成一个,但修改类后这个值就会改变,导致之前的对象不能被反序列化回来。
序列版本号:private static final long serialVersionUID = 123456789L;
5、要序列化的类中的所有属性也都需要是可序列化的。
/* * 继承 Serializable 才可序列化 */ class Student implements Serializable { @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", address=" + address + "]"; } // 序列版本号 private static final long serialVersionUID = 123456789L; public String name; public int age; public transient String address; public Student(String name, int age, String address) { super(); this.name = name; this.age = age; this.address = address; } }
序列化
@Test public void objStreamTest() { try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("stu.txt"))){ Student s1 = new Student("张三", 23, "上海虹北公寓58号楼101室"); Student s2 = new Student("jay", 30, "上海虹北公寓58号楼201室"); oos.writeObject(s1); oos.writeObject(s2); oos.flush(); } catch (Exception e) { e.printStackTrace(); } }
反序列化
@Test public void objStreamTest2() { try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("stu.txt"))) { // 要按照写的顺序读 Student sr1 = (Student) ois.readObject(); Student sr2 = (Student) ois.readObject(); System.out.println(sr1.toString()); System.out.println(sr2.toString()); } catch (Exception e) { e.printStackTrace(); } }
RandomAccessFile简介与使用:https://blog.csdn.net/qq_31615049/article/details/88562892
1、seek:指定文件的光标位置,从0开始,读写文件时从该位置读取。
2、getFilePointer:返回当前的文件光标位置。
3、length:文件的长度。
4、read()、read(byte[] b)、read(byte[] b,int off,int len)这些方法跟FileInputStream中的方法一样。
5、常用:readDouble() readFloat() readBoolean() readInt() readLong() readShort() readByte() readChar()
writeDouble() writeFloat() writeBoolean() writeInt() writeLong() writeShort() writeByte() writeChar()
6、readFully(byte[] b):这个方法的作用就是将文本中的内容填满这个缓冲区b。如果缓冲b不能被填满,那么读取流的过程将被阻塞,如果发现是流的结尾,那么会抛出异常。这个过程就比较像“凑齐一车人在发车,不然不走”。
7、getChannel:它返回的就是nio通信中的file的唯一channel。
8、skipBytes(int n):跳过n字节的位置,相对于当前的point。
9、读写方式:RandomAccessFile raf = new RandomAccessFile(new File("hello.txt"), "rw");
r 以只读的方式打开文本,也就意味着不能用write来操作文件
rw 读操作和写操作都是允许的
rws 每当进行写操作,同步的刷新到磁盘,刷新内容和元数据
rwd 每当进行写操作,同步的刷新到磁盘,刷新内容
10、RandomAccessFile写文件时会覆盖原来的内容,要实现插入内容时,需要定位光标,读取光标后面的所有内容,拼接到要插入的内容后,然后写入。
RandomAccessFile raf1 = new RandomAccessFile("1.txt", "rw"); raf1.seek(3);// 把指针定位到第4个字符 // 避免乱码 ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[20]; int len; while ((len = raf1.read(buffer)) != -1) { baos.write(buffer, 0, len); } raf1.seek(3); raf1.write("xxx".getBytes()); raf1.write(baos.toString().getBytes()); baos.close(); raf1.close();
11、RandomAccessFile既可以做输入流,也可以做输出流。作为输出流时,如果文件不存在,则创建文件,如果文件存在则覆盖文件。
示例代码:
@Test public void randomAccessFileTest() { try (RandomAccessFile raf1 = new RandomAccessFile("1.txt", "rw"); // 避免乱码 ByteArrayOutputStream baos = new ByteArrayOutputStream() ) { raf1.seek(3);// 把指针定位到第4个位置 byte[] buffer = new byte[20]; int len; while ((len = raf1.read(buffer)) != -1) { baos.write(buffer, 0, len); } raf1.seek(3); raf1.write("xxx".getBytes()); raf1.write(baos.toString().getBytes()); } catch (Exception e) { e.printStackTrace(); } }
字节流读写文件,缓冲流 加速读取
@Test public void fileStreamTest() { File file1 = new File("1.txt"); File file2 = new File("2.txt"); try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file1)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file2))) { byte[] buffer = new byte[1024]; int len; while ((len = bis.read(buffer)) != -1) { bos.write(buffer, 0, len); } } catch (Exception e) { e.printStackTrace(); } }
字符流读取文件,文件不存在会报错
//字符流fileReader.read读取数据到chars中返回读取的字符个数,返回-1读取结束 File file = new File("1.txt"); int len; char[] chars = new char[5]; try (FileReader fileReader = new FileReader(file)) { while ((len = fileReader.read(chars)) != -1) { // for (int i = 0; i < len; i++) { // System.out.print(chars[i]); // } String str = new String(chars, 0, len); System.out.print(str); } } catch (RuntimeException e) { e.printStackTrace(); }
字符流写入文件,文件不存在会创建
//字符流写文件 File file = new File("1.txt"); try (FileWriter fw = new FileWriter(file)) { fw.write("你好,这是测试数据1。\n"); fw.write("你好,这是测试数据2。\n"); fw.append("你好,这是测试数据3。\n"); } catch (RuntimeException e) { e.printStackTrace(); }
读写txt文件
/** * 把字符串(UTF-8)写进txt,追加到末尾。 */ public static void writeStrToTxt(String fileName, String content, boolean append) throws Exception { byte[] bytes = content.getBytes(StandardCharsets.UTF_8); //相对路径,此项目或者此module的根目录:ProjectA/1.txt 或者 ProjectA/moduleA/1.txt //创建文件对象 File file = new File(fileName); //创建文件输出流 try (FileOutputStream fos = new FileOutputStream(file, append);) { fos.write(bytes); } catch (Exception e) { throw e;//关闭输出流异常 } } /** * 读取txt文件字符串。 */ public static String readStrFromTxt(String fileName) throws Exception { File file = new File(fileName); StringBuilder jsonStr = new StringBuilder(); try ( FileReader fileReader = new FileReader(file); BufferedReader bufferedReader = new BufferedReader(fileReader); ) { boolean firstRow = true; String line; while ((line = bufferedReader.readLine()) != null) { if (!firstRow){ jsonStr.append("\r\n"); } jsonStr.append(line); firstRow = false; } return jsonStr.toString().trim(); } catch (Exception e) { throw e; } }