java的文件操作【流】
本文主要讲述java的文件操作
一. 创建文件
public class fileTest { public static void main(String[] args) { } // 创建文件方式一: // String filePath = "F:\\韩顺平java基础笔记\\java图片\\new01.txt"; @Test public void create01(){ String filePath = "F:\\韩顺平java基础笔记\\java图片\\new01.txt"; File file = new File(filePath); try { file.createNewFile(); System.out.println("文件创建成功"); } catch (IOException e) { System.out.println(e.getMessage()); } } // 创建文件方式二: // File parentFile = new File("F:\\韩顺平java基础笔记\\java图片\\"); // String fileName = "new02.txt"; // File file = new File(parentFile, fileName); @Test public void create02(){ File parentFile = new File("F:\\韩顺平java基础笔记\\java图片\\"); String fileName = "new02.txt"; // 这里的file对象,在java程序中,只是一个对象 File file = new File(parentFile, fileName); try { // 真正创建文件的方法file.createNewFile(); file.createNewFile(); } catch (IOException e) { System.out.println(e.getMessage()); } } // 创建方式三: // String parentFile = "F:\\韩顺平java基础笔记\\java图片\\"; // String fileName = "new03.txt"; // File file = new File(parentFile, fileName); @Test public void create03(){ String parentFile = "F:\\韩顺平java基础笔记\\java图片\\"; String fileName = "new03.txt"; File file = new File(parentFile, fileName); try { file.createNewFile(); } catch (IOException e) { System.out.println(e.getMessage()); } } }
方式2和方式3的区别是:路径信息一个是由文件对象表示,另一个是字符串表示。
注意:file.createFile(),才是真正创建了文件对象。
二. 输入流和输出流
1)字节输入输出流
FileInputStream图示:
FileOutputStream图示:
使用FileInputStream读取文件【文件如果有中文,则使用字节输入流可能会乱码】
public class InputStreamExercise { public static void main(String[] args) { } // 使用read(),单个字节读取文件 @Test public void readFile01(){ String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt"; FileInputStream fileInputStream = null; int readData = 0; try { fileInputStream = new FileInputStream(filePath); while((readData = fileInputStream.read()) != -1){ System.out.print((char) readData); } } catch (IOException e) { System.out.println(e.getMessage()); } finally { try { fileInputStream.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } } // 使用read(byte[] arr),用字节数组读取文件 @Test public void readFile02(){ String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt"; FileInputStream fileInputStream = null; int readLen = 0; byte[] bytes = new byte[5]; try { fileInputStream = new FileInputStream(filePath); while((readLen = fileInputStream.read(bytes)) != -1){ // 注意这里创建字符串的new String(bytes,0,readLen),按照每次读取的长度,创建字符串 // 以免重复数据进入 System.out.print(new String(bytes,0,readLen)); } } catch (IOException e) { System.out.println(e.getMessage()); } finally { try { fileInputStream.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } } }
使用FileOutputStream写入文件
public class OutputStreamExercise { public static void main(String[] args) { } @Test public void writeFile(){ String filePath = "F:\\韩顺平java基础笔记\\java图片\\a.txt"; FileOutputStream fileOutputStream = null; try { // 创建方式1:fileOutputStream = new FileOutputStream(filePath);【内容会覆盖】 // 创建方式2:fileOutputStream = new FileOutputStream(filePath,true);【追加内容】 // fileOutputStream = new FileOutputStream(filePath); fileOutputStream = new FileOutputStream(filePath,true); // 写入一个字节 // fileOutputStream.write('H'); // 写入字符串 // String str = "hello java"; // fileOutputStream.write(str.getBytes()); // 指定写入的字符串 String str = "hello world"; fileOutputStream.write(str.getBytes(),0,5); } catch (IOException e) { System.out.println(e.getMessage()); } finally { try { fileOutputStream.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } } }
使用FileInputStream和FileOutputStream进行文件拷贝
public class fileCopy { public static void main(String[] args) { } @Test // 将F:\韩顺平java基础笔记\java图片路径下的图片,拷贝到F:\韩顺平java基础笔记 public void filesCopy (){ // 首先创建输入流InputStream读取路径的文件 String parentPath = "F:\\韩顺平java基础笔记\\java图片\\desk.jpg"; String targetPath = "F:\\韩顺平java基础笔记\\desk.jpg"; FileInputStream inputStream = null; FileOutputStream outputStream = null; byte[] bytes = new byte[10]; int readLen = 0; try { inputStream = new FileInputStream(parentPath); outputStream = new FileOutputStream(targetPath); while ((readLen = inputStream.read(bytes)) != -1){ outputStream.write(bytes,0,readLen); } } catch (IOException e) { e.printStackTrace(); } finally { try { inputStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
注意:字节流的默认字符集是UTF-8
2)字符输入输出流
FileReader输入流图示:
FileWriter输出流图示:
使用FileReader读取文件【不会乱码】
public class FileReaderExercise { public static void main(String[] args) { } @Test public void ReadFile01(){ String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt"; FileReader fileReader = null; int readData = 0; try { fileReader = new FileReader(filePath); // readData = fileReader.read() 单字节的读取文件 while ((readData = fileReader.read()) != -1){ System.out.print((char) readData); } } catch (IOException e) { System.out.println(e.getMessage()); } finally { if(fileReader != null){ try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void ReadFile02(){ String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt"; FileReader fileReader = null; int readLen = 0; char[] chars = new char[10]; try { fileReader = new FileReader(filePath); // readLen = fileReader.read(chars) 按照chars字符数组的长度,读取文件 while ((readLen = fileReader.read(chars)) != -1){ // 实际内容,与readLen有关,因此new String(chars,0,readLen) System.out.print(new String(chars,0,readLen)); } } catch (IOException e) { System.out.println(e.getMessage()); } finally { if(fileReader != null){ try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
使用FileWriter写文件
public class FileWriterExercise { public static void main(String[] args) { } @Test public void WriteFile(){ String filePath = "F:\\韩顺平java基础笔记\\java图片\\hello.txt"; FileWriter fileWriter = null; char[] chars = {'h','e','l','l','o'}; try { // fileWriter = new FileWriter(filePath); // 默认是覆盖方式 fileWriter = new FileWriter(filePath,true); // 追加方式 // 写入单个字符 // fileWriter.write('H'); // 写入字符数组 // fileWriter.write(chars); // 写入字符数组的指定部分 // fileWriter.write(chars,0,3); // 写入字符串 // fileWriter.write("韩顺平教育java"); // 写入字符串的指定部分 fileWriter.write("你好生活,银魂",0,4); } catch (IOException e) { e.printStackTrace(); } finally { if(fileWriter != null){ try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
注意:字符流的默认字符集是UTF-8
三. 处理流
节点流Vs处理流
处理流是节点流的包装,处理流的功能比节点流更加丰富,但是实质上处理流的功能是在节点流基础上扩展的。
例如 BufferedReader源码:【其他处理流,创建原理等同】
由于多态性质,Reader可以存放字符输入流Reader的任意子类,提高了流的功能性。
1)字符处理流
BufferedReader图示:
BufferedWriter图示:
使用BufferedReader读取文件:
public class BufferReader_ { public static void main(String[] args) { } @Test public void BufferReadFile(){ String filePath = "F:\\韩顺平java基础笔记\\java图片\\a.txt"; BufferedReader bufferedReader = null; String nextLine = null; try { // BufferedReader的成员变量中有Reader in // 带有Reader类的对象参数的BufferedReader构造器【类的多态】 bufferedReader = new BufferedReader(new FileReader(filePath)); // (nextLine = bufferedReader.readLine()) != null 每次读取文件的一行 while ((nextLine = bufferedReader.readLine()) != null) { System.out.println(nextLine); } } catch (IOException e) { e.printStackTrace(); } finally { // 只需关闭处理流即可 if(bufferedReader != null){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
使用BufferedWriter写入文件:
public class BufferWriter { public static void main(String[] args) { } @Test public void BufferWriteFile() throws IOException { String filePath = "F:\\韩顺平java基础笔记\\java图片\\b.txt"; // 覆盖写入 // BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath)); // 追加写入 BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true)); // 写入一个字符串 bufferedWriter.write("hello1 韩顺平教育"); // 插入一个与系统相关的换行符 bufferedWriter.newLine(); bufferedWriter.write("hello2 韩顺平教育"); bufferedWriter.newLine(); bufferedWriter.write("hello3 韩顺平教育"); bufferedWriter.newLine(); bufferedWriter.close(); } }
使用BufferedReader和BufferedWriter进行文件拷贝:
public class BufferFileCopy { public static void main(String[] args) { } /** * 由于BufferedReader和BufferedWriter是操作字符流文件 * 因此不能操作字节流文件【二进制文件】 例如,声音,视频,doc,pdf * @throws IOException */ @Test public void BufferCopyFile() throws IOException { String srcFilePath = "F:\\韩顺平java基础笔记\\java图片\\a.txt"; String destFilePath = "F:\\韩顺平java基础笔记\\java图片\\a1.txt"; BufferedReader bufferedReader = new BufferedReader(new FileReader(srcFilePath)); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(destFilePath)); String nextLine = null; while((nextLine = bufferedReader.readLine()) != null){ bufferedWriter.write(nextLine); bufferedWriter.newLine(); } if(bufferedReader != null){ bufferedReader.close(); } if(bufferedWriter != null){ bufferedWriter.close(); } } }
注意:关于文件拷贝
如果文件是字符流文件,则使用BufferedReader【FileReader】和BufferedWriter【FileWriter】进行文件拷贝
如果文件是字节流文件,则使用BufferedInputStream【FileInputStream】和BufferedOutputStream【FileOutputStream】进行文件拷贝
2)字节处理流
BufferedInputStream图示:
BufferedOutputStream图示:
使用BufferedInputStream和BufferedOutputStream拷贝二进制文件
public class BufferInputStreamTest { public static void main(String[] args) { } @Test public void BufferedCopyFile() throws IOException { String srcFilePath = "F:\\韩顺平java基础笔记\\java图片\\desk.jpg"; String destFilePath = "F:\\韩顺平java基础笔记\\java图片\\desk1.jpg"; BufferedInputStream bufferedInput = new BufferedInputStream(new FileInputStream(srcFilePath)); BufferedOutputStream bufferedOutput = new BufferedOutputStream(new FileOutputStream(destFilePath)); byte[] bytes = new byte[1024]; int readLen = 0; while ((readLen = bufferedInput.read(bytes)) != -1){ bufferedOutput.write(bytes,0,readLen); } if(bufferedInput != null) { bufferedInput.close(); } if(bufferedOutput != null) { bufferedOutput.close(); } } }
阶段总结:
字节流:FileInputStream和FileOutputStream,既可以处理字节流文件【图片,视频,doc,pdf】,也可以处理字符流文件【txt】
字符流:FileReader和FileWriter只能处理字符流文件【txt】
处理流的核心操作仍然是字节流和字符流,扩展了功能
字节处理流:BufferedInputStream和BufferedOutputStream可以处理所有文件
字符处理流:BufferedReader和BufferedWriter只能处理字符流文件【txt】
3)对象处理流
ObjectInputStream【反序列化】图示:
ObjectOutputStream【序列化】图示:
使用ObjectOutputStream序列化
public class ObjectOutputStreamTest { public static void main(String[] args) throws Exception{ String filePath = "F:\\韩顺平java基础笔记\\java图片\\objectData.bat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); oos.write(100); oos.writeBoolean(true); oos.writeChar('A'); oos.writeDouble(9.5); oos.writeUTF("韩顺平"); oos.writeObject(new Dog("大白",12)); System.out.println("执行完成"); } } // 如果需要序列化类的对象,则该类需要实现接口Serializable class Dog implements Serializable { private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = age; } }
使用ObjectInputStream反序列化
重点重点:在序列化过程中,当Dog类不是public时,即不是主类时
由于此时Dog不是public,因此不能import导入,如果将Dog类的代码复制到ObjectInputStreamTest中去,运行结果出错。
public class ObjectInputStreamTest { public static void main(String[] args) throws Exception { String filePath = "F:\\韩顺平java基础笔记\\java图片\\objectData.bat"; ObjectInputStream inputStream= new ObjectInputStream(new FileInputStream(filePath)); System.out.println(inputStream.readInt()); System.out.println(inputStream.readBoolean()); System.out.println(inputStream.readChar()); System.out.println(inputStream.readDouble()); System.out.println(inputStream.readUTF()); Object dog = inputStream.readObject(); System.out.println(dog.getClass()); System.out.println(dog); // 要想调用Dog的特定方法,调用run()方法 // 必须将Dog类改成public 主类,否则报错 Dog pet = (Dog) dog; pet.run(); inputStream.close(); } } // 如果需要序列化类的对象,则该类需要实现接口Serializable class Dog implements Serializable { private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } public void run(){ System.out.println(name + "在跑步..."); } }
运行结果如下:
100 true A 9.5 韩顺平 class exercise.file_.buffer.objectbuffer.Dog Dog{name='大白', age=12} Exception in thread "main" java.lang.ClassCastException: exercise.file_.buffer.objectbuffer.Dog cannot be cast to exercise.file_.buffer.objectBuffered.Dog at exercise.file_.buffer.objectBuffered.ObjectInputStreamTest.main(ObjectInputStreamTest.java:23) Process finished with exit code 1
原因:在ObjectOutputStream反序列化后,文件已经保存了Dog的包名+类名,下图文件保存的Dog类的内容
而在ObjectInputStreamTest中复制的Dog类,包名是exercise.file_.buffer.objectBuffered.Dog。
在ObjectInputStreamTest程序中:
// 向下转型 Dog pet = (Dog) dog; pet.run();
dog对象的运行类型是exercise.file_.buffer.objectbuffer.Dog
但是这里的Dog类确是exercise.file_.buffer.objectBuffered.Dog,因此无法向下转型
正确写法:将Dog提升至主类,ObjectOutputStream和ObjectInputStream引用(import)同一个类。
import exercise.file_.buffer.objectbuffer.Dog; public class ObjectInputStreamTest { public static void main(String[] args) throws Exception { String filePath = "F:\\韩顺平java基础笔记\\java图片\\objectData.bat"; ObjectInputStream inputStream= new ObjectInputStream(new FileInputStream(filePath)); System.out.println(inputStream.readInt()); System.out.println(inputStream.readBoolean()); System.out.println(inputStream.readChar()); System.out.println(inputStream.readDouble()); System.out.println(inputStream.readUTF()); Object dog = inputStream.readObject(); System.out.println(dog.getClass()); System.out.println(dog); // 要想调用Dog的特定方法,调用run()方法 // 必须将Dog类改成public 主类,否则报错 Dog pet = (Dog) dog; pet.run(); inputStream.close(); } }
对象处理流的使用细节:
四. 转换流
InputStreamReader图示:
将指定字符集的InputStream子类【字节流】转换成Reader子类【字符流】。
OutputStreamWriter图示:
将指定字符集的OutputStream子类【字节流】转换成Writer子类【字符流】。
使用InputStreamReader读取指定字符集的文件
public class TransferInOutput { public static void main(String[] args) throws IOException { // 使用字节流读取txt文件 // 字节流的字符集,默认是utf-8 // 字符流的字符集,默认是utf-8 String filePath = "F:\\韩顺平java基础笔记\\java图片\\b.txt"; FileInputStream fileReader = new FileInputStream(filePath); BufferedInputStream bufferedReader = new BufferedInputStream(fileReader); int readLen = 0; byte[] bytes = new byte[1024]; while((readLen = bufferedReader.read(bytes)) != -1){ System.out.print(new String(bytes,0,readLen)); } bufferedReader.close(); } @Test public void transfer() throws IOException{ String filePath = "F:\\韩顺平java基础笔记\\java图片\\b.txt"; // 1.创建字节流 FileInputStream inputStream = new FileInputStream(filePath); // 2.创建转换流,将指定字符集的字节流转换成字符流 InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"gbk"); // 3.通过字符流【节点流】创建字符处理流【处理流】 BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while((str = bufferedReader.readLine()) != null){ System.out.println(str); } bufferedReader.close(); } }
使用OutputStreamWriter将写入的内容,按照指定的字符集,保存到文件中
public class TransferOutInput { public static void main(String[] args) throws IOException { String filePath = "F:\\韩顺平java基础笔记\\java图片\\b1.txt"; String charset = "gbk"; OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charset); osw.write("韩顺平教育"); osw.close(); System.out.println("字符集: " +charset + "文件创建成功"); } }