在程序中,我们使用java.io.File这个类来描述和操作磁盘上的一个文件或文件夹(目录)。
File这个类,能新建、删除、移动,重命名文件或文件夹,也能获取或者修改文件或文件夹的信息(如大小,修改时间等),但File不能访问文件里的内容。
如果需要访问文件里的内容,则需要使用输入/输出流。
路径:用来描述一个文件或者文件夹所存在的位置,可以分为 绝对路径 和 相对路径。
从磁盘的根目录开始,一层层的向内查找,直到找到这个文件。在不同的操作系统中,根目录的表示方式可能略有不同。例如,在UNIX和Linux系统中,根目录用斜杠(/)表示,如/home/user/file.txt
;而在Windows系统中,根目录用驱动器名和冒号表示,如C:\Users\User\file.txt
。
是相对于当前工作目录或另一个已知位置的路径。它描述的是文件或目录与当前位置之间的相对关系。相对路径通常省略了根目录部分,直接从当前目录开始描述路径。例如,假设当前工作目录是/home/user,要访问该目录下的文件file.txt,可以使用相对路径file.txt,而不需要写出完整的绝对路径。
./ : 表示当前工作目录。 ./可以省略
../ : 表示返回到上一层目录
关于目录分隔符,在不同的操作系统中,不一样。在windows中,使用 \ 作为目录分隔符,但是,在 ⾮windows的操作系统中,例如: Linux、 Unix,使用 / 作为目录分隔符。
关于路径分隔符,在不同的操作系统中,不一样。在windows中,使用 ; 作为路径分隔符,但是,在 ⾮windows的操作系统中,例如: Linux、 Unix,使用 : 作为路径分隔符。
虽然,在windows中,使用 \ 作为目录分隔符,但是大部分情况下,使用 / 也可以。
而File的静态常量会获取程序所在的系统环境中的具体分隔符。这样就省去了程序员来区分不同操作系统的麻烦。
System.out.println(File.separator);// 目录分隔符,用来分隔两个目录,返回一个 字符串
System.out.println(File.separatorChar);// 目录分隔符,用来分隔两个目录,返回一个字符
System.out.println(File.pathSeparator);// 路径分隔符,用来分隔两个路径,返回一个字符串
System.out.println(File.pathSeparatorChar);// 路径分隔符,用来分隔两个路径,返回一个字符
抽象路径应该尽量使用相对路径,并且目录的层级分隔符不要直接写/
或者\
,应该使用File.separator这个常量表示,以避免不同系统带来的差异
- File(String pathname)
作用:通过指定字符串转换成抽象路径名来创建一个File实例
- File(File parent,String child)
作用:从负抽象路径名和子路径名字符串创建新的File实例
- File(String parent, String child)
作用:从父路径名字符串和子路径名字符串创建新的File实例
File file = new File("D:\\a.txt"); if (!file.exists()) { //创建文件 file.createNewFile(); } File dir1 = new File("D:\\Dir1"); if (!dir1.exists()) { // touch //创建文件夹 dir1.mkdir(); } File dir111 = new File("D:\\Dir1\\Dir11","dir111"); if (!dir111.exists()) { //多层级创建文件夹 dir111.mkdirs(); } File dir1112 = new File(new File("D:\\Dir1\\Dir11\\dir111"),"dir1111"); if (!dir1112.exists()) { dir1112.mkdir(); }
- String getName()
作用:返回由此抽象路径名表示的文件或目录的名称
- String getPath()
作用: 将此抽象路径名转换为路径名字符串
- File getAbsoluteFile()
作用:返回此抽象路径名的绝对形式。
- String getAbsolutePath()
作用:返回此抽象路径名的绝对路径名字符串。
- String getParent()
作用:返回此抽象路径名的父路径名字符串,如果此路径名未指定父目录,则返回null。
- boolean renameTo(File newName)
作用:重命名由此抽象路径名表示的文件。
- boolean exists()
作用:测试此抽象路径名表示的文件或目录是否存在
- boolean canWrite()
作用:测试应用程序是否可以修改由此抽象路径名表示的文件
- boolean canRead()
作用:测试应用程序是否可以读取由此抽象路径名表示的文件
- boolean isFile()
作用:测试此抽象路径名表示的文件是否为普通文件
- boolean isDirectory()
作用:测试此抽象路径名表示的文件是否为目录
- long lastModify()
作用:返回此抽象路径名表示的文件上次修改的时间
- long length()
作用:返回由此抽象路径名表示的文件的长度
File f1 = new File("D:\\Dir1\\file.txt"); System.out.println("是否存在:"+f1.exists()); System.out.println("文件的名字:"+f1.getName()); System.out.println(""+f1.getPath()); System.out.println("绝对路径:"+f1.getAbsolutePath()); System.out.println(""+f1.getAbsoluteFile()); System.out.println(""+f1.getParent()); System.out.println(""+f1.getParentFile()); System.out.println("是否是一个文件:"+f1.isFile()); System.out.println("是否是一个目录"+f1.isDirectory()); System.out.println("文件大小:"+f1.length()); System.out.println("最后一次修改的时间(毫秒数):"+f1.lastModified()); System.out.println("可执行?"+f1.canExecute()); System.out.println("可写?"+f1.canWrite()); System.out.println("可读?"+f1.canRead()); System.out.println("是否隐藏:"+f1.isHidden()); //更名, 可以更改位置。 boolean b = f1.renameTo(new File("D:\\Dir1\\Dir11\\f1111.txt")); System.out.println("b:"+b);
- String[] list()
作用:返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录
拿到子文件的名字
- String[] list(FilenameFilter filter)
作用:返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录
- File[] listFiles()
作用:返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件
File f3 = new File("D:\\Dir1"); String[] list = f3.list(); System.out.println(Arrays.toString(list)); String[] list1 = f3.list((f, name) -> name.endsWith("bat")); System.out.println(Arrays.toString(list1));
- boolean createNewFile()
作用:当且仅当具有该名称的文件尚不存在时,创建一个由该抽象路径名命名的新的空文件
- boolean mkdir()
作用:创建由此抽象路径名命名的目录
- boolean mkdirs()
作用:创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。
- boolean delete()
作用:删除由此抽象路径名表示的文件或目录。
注意:删除目录时,必须保证此目录下是空目录,如果目录不是空的,需要先删除里面的东西,再删除目录。
注意:删除是永久删除,不会进入回收站
File f2 = new File("D:\\Dir1\\Dir11\\dir111\\dir1111"); boolean delete = f2.delete(); System.out.println(delete);
逻辑:1.先判断是否为文件,可以直接删除
2. 否则就是文件夹了,查看里面的内容,如果为空,可以直接删除,如果不为空,需要再次遍历每一个文件(是否......)
public static void main(String[] args) { File dir = new File("D:\\Dir1"); deleteFile(dir); } public static void deleteFile(File dir) { if(dir.isDirectory()) { File[] files = dir.listFiles(); for(File file : files) { deleteFile(file); } } dir.delete(); }
编程时,想读取硬盘上的某一个文件,又或者想将程序中的某些数据写入到硬盘上的一个文件里。这时,我们就要使用I/O流。
这个“外部”范围很广,包括诸如键盘、显示器、文件、磁盘、网络、另外一个程序等。“数据”也可以是任何类型的,例如一个对象、串字符、图像、声音等
- Input(输入):是指数据流入程序,通常我们读取外界数据时使用,所以输入是用来读取数据的。 (数据-------->程序)读取
- Output(输出):是指数据从程序流出,通常我们需要写出数据到外界时使用,所以输出是用来写出数据的。 (程序-------->数据)写出
一个流就是一个从数据源向目的地的数据序列
I/O流类一旦被创建就会自动打开
通过调用close方法,可以显式关闭任何一个流,如果流对象不再被引用,Java的垃圾回收机制也会隐式地关闭它
不论数据从哪来,到哪去,也不论数据本身是何类型,读写数据的方法大体上都是一样的
- 读操作:
1.打开一个输入流
2.读信息
3.关闭流
- 写操作:
1.打开一个输出流
2.写信息
3.关闭流
按照数据的流向分类:
输入流
输出流
按照处理数据的单位分类:
字节流
字符流
按照流的功能分类:
节点流:可以从一个特定的IO设备上读/写数据的流。也称之为低级流
处理流:是对一个已经存在的流的连接和封装,通过所封装的流的功能调用实现数据读/写操作。通常处理流的构造器上都会带有一个其他流的参数。也称之为高级流或者过滤流
传统的文件File类,只能够对文件进行属性的操作,例如:创建、移动、删除、属性获取等操作。但是不能获取到文件中的内容
如果需要对文件中的内容进行读写操作,需要使用到IO流。
使用场景:对磁盘或者网络中的文件件进行读写操作。
InputStream是字节输入流的顶级父类,是抽象类。定义了基本的读取方法。
OutputStream是字节输出流的顶级父类,也是抽象类,定义了基本的写出方法。
- int read()
从输入流中读取一个字节,把它转换为0-255之间的整数,并返回这一整数,如果返回-1,说明读到文件末尾(EOF)
- int read(byte[] b)
从输入流中读取若干个字节,把它们保存到缓冲区b中,返回的整数表示读取的字节数,如果遇到输入流的结尾,返回-1
- int read(byte[] b, int off, int len)
从输入流读取最多 len字节的数据到一个字节数组。从指定下标off开始存。返回的整数表示实际读取的字节数。如果遇到输入流的结尾,返回-1
- void close()
关闭输入流
- int available()
返回可以从输入流中读取的字节数目
- long skip(long n)
从输入流中跳过参数n指定数目的字节
- boolean markSupported()
测试这个输入流是否支持 mark和 reset方法。
- void mark(int readLimit)
标记此输入流中的当前位置。
- void reset()
将此流重新定位到上次在此输入流上调用 mark方法时的位置。
- void write(int b)
向输出流写出一个字节
- void write(byte[] b)
将 b.length字节从指定的字节数组写入此输出流
- void write(byte[] b,int off, int len)
从指定的字节数组写入 len个字节,从偏移 off开始输出到此输出流
- void close()
关闭输出流
- void flush()
OutputStream类本身的flush方法不执行任何操作,它的一些带缓冲区的子类覆盖了flush方法,该方法强制把缓冲区内的数据写到输出流中
是文件的字节输出流,以字节为单位写出数据到文件。
重写模式构造方法:
- FileOutputStream(File file)
创建一个 向指定file对象表示的文件中 写出数据的文件输出流
- FileOutputStream(String filename)
创建一个 向具体指定名称的文件中 写出数据的文件输出流
追加模式构造方法:
- FileOutputStream(File file,boolean append)
创建一个 向指定file对象表示的文件中 写出数据的文件输出流
- FileOutputStream(String filename,boolean append)
创建一个 向具体指定名称的文件中 写出数据的文件输出流
注意:
若指定的文件已经包含内容,那么当使用该流进行写出数据时,会将原有内容全部清除
若指定目录中的指定文件不存在,任何输出流都会自动将该文件创建出来,
FileOutputStream fos = null; try{ //创建一个文件输出流对象,用来向磁盘上的某一个文件里写数据: D:\\myfile1001.txt fos = new FileOutputStream(new File("D:\\myfile1001.txt")); //先看一下 中 的字符数字 System.out.println(Arrays.toString("中".getBytes())); //[-28, -72, -83] // 11100100 10111000 10101101 ==‘中’ //调用写方法,向文件中写数据 fos.write('中'); // 写一个字节 fos.write(new byte[]{-28,-72,-83}); //写了三个字节, 对应的"中" byte[] bs = new byte[]{-28,-72,-83,-27, -101, -67}; //写了三个字节 对应的是“国” fos.write(bs,3,3); }catch(Exception e){ e.printStackTrace(); }finally { //关闭流 fos.close(); } catch (IOException e) { throw new RuntimeException(e); } }
是文件的字节输入流,该流以字节为单位从文件中读取数据。
常用构造方法:
- FileInputStream(File file)
创建一个从指定File对象表示的文件中读取数据的文件输入流
- FileInputStream(String name)
创建一个从指定路径名所指定的文件中读取数据的文件输入流
FileInputStream fis = null; try{ fis = new FileInputStream("D:\\myfile1001.txt"); //读取数据的方法 int c1 = fis.read(); //读取一个字节,返回int类型, 如果读不到字节,则返回-1. System.out.println(c1); int c2 = fis.read(); byte[] bs = new byte[20]; int count = fis.read(bs);// 一次性读取多个字节,存储到数组中,最多一次性读取数组的长度个。 返回的是读取的真实长度。 System.out.println(count); //将字节数组翻译成对应的字符 String str = new String(bs,0,13); System.out.println(str); }catch (Exception e){ e.printStackTrace(); }finally { try { fis.close();//注意关闭流 } catch (IOException e) { throw new RuntimeException(e); } }
在向硬件设备做写出操作时,增大写出次数无疑会降低写出效率,为此,我们可以使用缓冲输出流来一次性批量写出若干数据来减少写出次数来提高写出效率。
常用构造器:
- BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
- BufferedOutputStream(OutputStream out, int size)
创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。(自定义缓存区的大小, 默认是8k(8192个字节))
BufferedOutputStream bos = null; try{ bos = new BufferedOutputStream(new FileOutputStream("D:\\myfile1001.txt",true)); //调用书写一个字节的方法, 先写到缓存区(即内部的byte数组中) bos.write('A'); bos.flush();// 手动调用冲刷方法,冲刷缓冲区到目的地。 bos.write("中国你好".getBytes()); }catch (Exception e){ e.printStackTrace(); }finally { try { // 如果流的内部维护了缓存区,在关闭流前,一定会先flush缓存区 bos.close(); } catch (IOException e) { throw new RuntimeException(e); } }
常用构造器:
- BufferedInputStream(InputStream in)
以指定节点流in作为参数,创建一个缓冲输入流
- BufferedInputStream(InputStream in, int size)
以指定节点流in和缓冲区大小作为参数,创建一个缓冲输入流。(自定义缓存区的大小, 默认是8k(8192个字节))
BufferedInputStream bis = null; try{ bis = new BufferedInputStream(new FileInputStream("D:\\myfile1001.txt")); //调用读取方法 int read = bis.read();//从缓存中获取一个字节 System.out.println(read); //定义一个空的字节数组 byte[] bs = new byte[100]; //从缓存区中获取字节存储到空数组中,指定偏移量开始存储,存储length个长度。 // 注意: 当length<文件中剩余的字节数时,实际上读取length个。 // 当length>文件剩余的字节数,实际上就是读取了剩余的字节数量 // 简单来说就是读少的 int read1 = bis.read(bs, 10, 13); System.out.println(read1); System.out.println(Arrays.toString(bs)); String str = new String(bs,10,13); System.out.println(str); }catch (Exception e){ e.printStackTrace(); }finally { try { bis.close(); } catch (IOException e) { throw new RuntimeException(e); } }
DataOutputStream dos = null; try{ dos = new DataOutputStream( new BufferedOutputStream( new FileOutputStream("D:\\Data.txt") )); dos.writeInt(65); dos.writeLong(65); dos.writeDouble(65); dos.writeChar('A'); dos.writeBoolean(true); dos.writeUTF("中国你好"); }catch (Exception e){ e.printStackTrace(); }finally { try { dos.close(); } catch (IOException e) { throw new RuntimeException(e); } }
DataInputStream dis = null; try{ dis = new DataInputStream( new BufferedInputStream( new FileInputStream("D:\\Data.txt") )); int i = dis.readInt(); System.out.println(i); long l = dis.readLong(); System.out.println(l); double v = dis.readDouble(); System.out.println(v); char c = dis.readChar(); System.out.println(c); boolean b = dis.readBoolean(); System.out.println(b); String s = dis.readUTF(); System.out.println(s); }catch (Exception e){ e.printStackTrace(); }finally { try { dis.close(); } catch (IOException e) { throw new RuntimeException(e); } }
对象是存在于内存中的,有的时候我们需要将对象保存到硬盘上,又有时我们需要将对象传输到另一台计算机上等等这些的操作。
此时,我们需要将对象转换成一个字节序列,这个过程我们称之为序列化。
相反,我们将一个字节序列转换成对应的对象,这个过程我们称之为反序列化
通过ObjectOutputStream流的方法WriteObject(Object o)实现对象序列化。
常用构造器:
- ObjectOutputStream(OutputStream os)
public static void main(String[] args) throws IOException { Person person = new Person("zhangsan",23,'男'); /** * 将该内存中的对象保存到磁盘上 */ ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream("D:\\person.ser")); //: 将内存中的对象转成了字节数组然后写到了文件中 oos.writeObject(person); oos.close(); }
通过ObjectInputStream流的方法readObject()实现对象反序列化。
常用构造器:
- ObjectInputStream(InputStream is)
public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\person.ser")); //读取文件中的字节数组,也要使用readObject Object o = ois.readObject(); Person person = (Person) o; System.out.println(person); ois.close(); }
注意:
Serializable接口:
ObjectOutputStream在对对象进行序列化时有一个要求,就是需要对象所属的类型必须实现Serializable接口。此接口内什么都没有,只是作为可序列化的标识。
serailVersionUID:
通常实现序列化接口的类需要提供一个常量serialVersionUID,表明该类的版本。
若不显示的声明,在该对象序列化时也会根据当前类的各个方面计算该类的默认serialVersionUID。但是不同平台的编译器实现有所不同,想要跨平台,都应该显示的声明版本号。
如果类的对象序列化存入硬盘上面,之后随着需求的变化更改了类的属性(增加或减少或改名等),那么当反序列化时,就会出现异常(InvalidClassException),这样就造成了不兼容性的问题。但当serialVersionUID相同时,就会将不一样的field以type的预设值反序列化,避免不兼容问题。
transient关键字:
使用transient关键字修饰的属性在序列化时其值将被忽略,可以忽略某些不必要的属性,从而对序列化后得到的字节序列“瘦身”
public class Person implements Serializable { private static final long serialVersionUID = 1001L; private transient String name; private int age; // 假如,在序列化时性别这个属性不重要,我们就可以在该属性前使用一个新的修饰词transient // 这样:序列化时就不会保存该属性的值。 从而减少了字节序列的传输。 private transient char gender; private String address; public Person(){} public Person(String name, int age, char gender) { this.name = name; this.age = age; this.gender = gender; } public Person(String name, int age, char gender, String address) { this.name = name; this.age = age; this.gender = gender; this.address = address; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && gender == person.gender && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(name, age, gender); } public String toString(){ return name+","+age+","+gender+","+address; } }
- Reader是字符输入流的父类,抽象类
- Writer是字符输出流的父类,抽象类
字符流是以字符(char)为单位读写数据的,一次处理一个unicode。但字符流的底层仍然是基本的字节流。
- int read()
读一个字符
- int read(char[] cbuf)
将字符读入数组。
- abstract int read(char[] cbuf, int off, int len)
将字符读入数组的一部分。
- void write(char[] cbuf)
将一个字符数组写出去。
- abstract void write(char[] cbuf, int off, int len)
写入字符数组的一部分。
- void write(int c)
写一个字符
- void write(String str)
写一个字符串
- void write(String str, int off, int len)
写一个字符串的一部分。
使用该流可以设置字符集,并按照指定的字符集将字符转换成字节后通过该流写出
常用构造器:
- OutputStreamWriter(OutputStream out,String charsetName)
基于给定的字节输出流以及字符集创建字符输出流对象
- OutputStreamWriter(OutputStream out)
根据系统默认字符集创建字符输出流对象
OutputStreamWriter osw = null; try{ osw = new OutputStreamWriter( new FileOutputStream("D:\\char.txt"),"GB2312"); //调用方法开始书写字符到文件中 osw.write('中'); osw.write("欢迎来到china".toCharArray(),2,7); osw.write("我们国家是美丽的hello"); }catch (Exception e){ e.printStackTrace(); }finally { try{ osw.close(); }catch (Exception e){ e.printStackTrace(); } }
使用该流可以设置字符集,并按照指定的字符集从流中按照该编码将字节数据转换为字符并读取
常用构造器:
- InputStreamReader(InputStream in,String charsetName)
基于给定的字节输入流以及字符集创建字符输入流
- InputStreamReader(InputStream in)
该构造方法会根据系统默认字符集( utf-8)创建字符输入流
InputStreamReader isr = null; try{ isr = new InputStreamReader( new FileInputStream("D:\\char.txt"),"GB2312"); int read = isr.read(); System.out.println((char)read); char[] cs = new char[1024]; int read1 = isr.read(cs); // 读取数据源里的数据到空数组中,返回的是读取的真正字符的个数。 如果返回-1,说明读到文件末尾了。 String str = new String(cs,0,read1); System.out.println(str); }catch (Exception e){ e.printStackTrace(); }finally { try{ isr.close(); }catch (Exception e){ e.printStackTrace(); } }
PrintWriter是具有自动行刷新的缓冲字符输出流,其提供了比较丰富的构造方法,通常比BufferedWriter更实用。
为什么不用BufferedWriter:
是因为PrintWriter的功能更加强大,方法更多,提供了行自动刷新功能。里面提供了除了write方法外的很多个print和println方法,其中println这个方法有个特点, 每写完我们传入的目标数据后,还是写一个换行符号。如果我们设置了自动行刷新功能,则写完一行,就直接刷新缓冲区。
常用构造器:
- PrintWriter(Writer writer)
- PrintWriter(Writer writer, boolean autoFlush)
常用构造方法:
- PrintWirter(File file)
- PrintWriter(String filename)
- PrintWriter(OutputStream out)
- PrintWriter(OutputStream out,boolean autoFlush)
- PrintWriter(Writer writer)
- PrintWriter(Writer writer,boolean autoFlush)
- 常用方法:
- void println()
通过写入行分隔符字符串来终止当前行。
- void println(boolean x)
打印一个布尔值,然后终止该行。
- void println(char x)
打印一个字符,然后终止该行。
- void println(char[] x)
打印字符数组,然后终止行。
- void println(double x)
打印双精度浮点数,然后终止行。
- void println(float x)
打印一个浮点数,然后终止该行。
- void println(int x)
打印一个整数,然后终止该行。
- void println(long x)
打印一个长整型,然后终止行。
- void println(Object x)
打印一个对象,然后终止该行。
- void println(String x)
打印一个字符串,然后终止行。
PrintWriter pw = null; try{ pw = new PrintWriter( new OutputStreamWriter( new FileOutputStream("D:\\charBuffer.txt"), "UTF-8"),true); pw.println("中国"); //pw.flush(); 如果不想手动调用flush来冲刷缓存区,可以使用构造器来设置为true,进行自动行刷新。前提必须调用println的方法 pw.println(65); pw.println(3.14); }catch (Exception e){ e.printStackTrace(); }finally { try{ pw.close(); }catch (Exception e){ e.printStackTrace(); } }
BufferedReader是缓冲字符输入流,内部提供了缓冲区,可以提高读取效率。
常用构造器:
- BufferedReader(Reader reader)
- BufferReader(Reader reader,int size)
常用方法:
- String readLine()
连续读取一行字符串,直到读取到换行符位置,返回的字符串中不包含换行符
public static void main(String[] args) { BufferedReader br = null; try{ br = new BufferedReader(new InputStreamReader( new FileInputStream("D:\\charBuffer.txt"),"UTF-8")); String line = null; while ((line = br.readLine()) != null) { System.out.println(line); } }catch (Exception e){ e.printStackTrace(); }finally { try{ br.close(); }catch (Exception e){ e.printStackTrace(); } }
相当于OutputStreamWriter和FileOutputStream合起来的功能
构造方法:
- FileWriter(File file)
- FileWriter(File file,boolean append)
- FileWriter(String filepath)
- FileWriter(String filepath,boolean append)
常用方法:
- 继承了OutputStreamWriter等父类的方法,内部也维护着一个缓存区,需要手动调用flush方法进行刷新。
- 文件输出流,用来向文件中书写字符的,使用的是默认字符集,第二个参数传true,表示追加写操作,不使用第二个参数,相当于第二个参数是false,表示覆盖写操作。
FileWriter fw = null; try{ fw = new FileWriter("D:\\filewriter.txt"); fw.write("你好,中国"); fw.flush(); fw.append("哈哈哈"); }catch (Exception e){ e.printStackTrace(); }finally { try{ fw.close(); }catch (Exception e){ e.printStackTrace(); } }
相当于InputStreamReader和FileInputStream合起来的功能,但是不能设置字符集。
构造方法:
- FileReader(File file)
- FileReader(String filepath)
常用方法:
- 继承了InputStreamReader等父类的方法,内部也维护着一个缓存区,可以提高读取效率。
FileReader fr = null; try { fr = new FileReader("D:\\filewriter.txt"); char[] buf = new char[1024]; int len = fr.read(buf); String s = new String(buf, 0, len); System.out.println(s); } catch (Exception e) { e.printStackTrace(); } finally { try { fr.close(); } catch (Exception e) { e.printStackTrace(); } }
为PrintStream类型,代表标准输出流,默认的数据输出是控制台
为InputStream类型,代表标准输入流,默认的数据源为键盘
为PrintStream类型,代表标准错误输出也流,默认的数据输出是控制台
public static void main(String[] args) throws FileNotFoundException { //默认情况下数据源来自键盘, //即in这个静态变量存储的地址指向的是一个输入流, //而输入流的数据源指向的是键盘 //这里将数据源改成文件 注意存储原来的数据源为键盘的地址 InputStream in = System.in; //临时存储起来 //将数据源指向某一个文件: System.setIn(new FileInputStream("D:\\charBuffer.txt")); Scanner sc = new Scanner(System.in); String s = sc.nextLine(); System.out.println(s); s = sc.nextLine(); System.out.println(s); s = sc.nextLine(); System.out.println(s); System.err.println("-----------ABCDEFG---"); }
public static void testSTDOUT() throws FileNotFoundException { //默认情况下是输出到控制台console //这里将输出源改到指定文件 // 将out原有的地址临时存储起来 PrintStream outTemp = System.out; //将一个输出流对象的地址存储到out里, 即更换输出位置。 System.setOut(new PrintStream("D:\\other.txt")); System.out.println("no zuo no die"); //后续代码再更改回来,输出到控制台 System.setOut(outTemp); System.out.println("---ABCDEFG---"); }
拷贝一个文件或者目录到另外一个位置上。
src 源文件/文件夹
dest 目的文件夹
public static void copy(File src, File dest) { //文件边读边写 //文件夹 再创建 里面的东西 递归 if(src.isDirectory()) { if(!dest.exists()) { dest.mkdir(); } } File[] files = src.listFiles(); if(files != null) { for (File file : files) { copy(file, new File(dest, file.getName())); } }else{ try(InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest)) { byte[] buf = new byte[1024]; int btyesRead; while((btyesRead = in.read(buf)) != -1){ out.write(buf, 0, btyesRead); } }catch (IOException e) { throw new RuntimeException(e); } } }