电子商务网站建设描述,网站在哪里找,做网站 建站,公司创建的法制网站前面介绍了利用文件写入器和文件读取器来读写文件#xff0c;因为FileWriter与FileReader读写的数据以字符为单位#xff0c;所以这种读写文件的方式被称作“字符流I/O”#xff0c;其中字母I代表输入Input#xff0c;字母O代表输出Output。可是FileWriter的读操作并不高效…前面介绍了利用文件写入器和文件读取器来读写文件因为FileWriter与FileReader读写的数据以字符为单位所以这种读写文件的方式被称作“字符流I/O”其中字母I代表输入Input字母O代表输出Output。可是FileWriter的读操作并不高效缘由在于FileWriter每次调用write方法都会直接写入文件假如某项业务需要多次调用write方法那么程序就会写入文件同样次数。因为写文件本质是写磁盘磁盘的速度远不如内存所以频繁地写文件必然严重降低程序的运行效率。为此Java又设计了缓存写入器BufferedWriter它的write方法并不直接写入文件而是先写入一块缓存等到缓存写满了再将缓存上的数据写入文件。由于缓存空间位于内存之中写入缓存等同访问内存这样相当于把写磁盘动作替换成写内存动作因此BufferedWriter的整体写文件性能要大大优于FileWriter。除此之外BufferedWriter还新增了下列几个方法newLine往文件末尾添加换行标记(Window系统是回车加换行)。当然实际上是先往缓存添加换行标记并非直接往磁盘写入换行标记。flush立即将缓冲区中的数据写入磁盘。默认情况要等缓冲区满了才会写入磁盘或者调用close方法关闭文件之时也会写入磁盘但是有时程序猴急一定要立即写入磁盘此时就需调用flush方法强行写磁盘。使用缓存写入器之前要先创建文件读取器对象并获得父类Writer的实例然后再据此创建缓存写入器对象。下面是通过缓存写入器把多行字符串写入文件的代码例子private static String mSrcName D:/test/aad.txt;// 使用缓存字符流写入文件private static void writeBuffer() {String str1 白日依山尽黄河入海流。;String str2 欲穷千里目更上一层楼。;File file new File(mSrcName); // 创建一个指定路径的文件对象// try(...)允许在圆括号内部拥有多个资源创建语句语句之间以冒号分隔// 先创建文件写入器再根据文件读取器创建缓存写入器try (Writer writer new FileWriter(file);BufferedWriter bwriter new BufferedWriter(writer);) {// FileWriter的每次write调用都会直接写入磁盘不但效率低性能也差。// BufferedWriter的每次write调用会先写入缓冲区直到缓冲区满了才写入磁盘// 缓冲区大小默认是8K查看源码defaultCharBufferSize 8192;// 资源释放的close方法再把缓冲区的剩余数据写入磁盘// 或者中途调用flush方法也可提前将缓冲区的数据写入磁盘。bwriter.write(str1); // 往文件写入字符串bwriter.newLine(); // 另起一行也就是在文件末尾添加换行标记(Window系统是回车加换行)bwriter.write(str2); // 往文件写入字符串//bwriter.flush(); // 把缓冲区中的数据写入磁盘} catch (Exception e) {e.printStackTrace();}}既然文件写入器有对应的缓存写入器那么文件读取器也有对应的缓存读取器BufferedReader。BufferedReader的实现原理与它的兄弟BufferedWriter类似另外BufferedReader比起文件读取器新增了如下方法readLine从文件中读取一行数据。mark在当前位置做个标记。reset重置文件指针令其回到上次标记的位置。也就是回到上次mark方法标记的文件位置。lines读取文件内容的所有行返回的是Stream流对象之后便可按照流式处理来加工该字符串流。若想使用缓存读取器依然要先创建文件读取器再根据其父类的读取器实例创建缓存读取器。下面是通过缓存读取器从文件中读取多行字符串的代码例子// 使用缓存字符流读取文件private static void readBuffer() {File file new File(mSrcName); // 创建一个指定路径的文件对象// try(...)允许在圆括号内部拥有多个资源创建语句语句之间以冒号分隔// 先创建文件读取器再根据文件读取器创建缓存读取器try (Reader reader new FileReader(file);BufferedReader breader new BufferedReader(reader);) {breader.mark((int) file.length()); // 做个标记for (int i1; ; i) {// FileReader只能一个字符一个字符地读或者一次性读进字符数组。// BufferedReader还支持一行一行地读。String line breader.readLine(); // 从文件中读出一行文字if (line null) { // 读到了空指针表示已经到了文件末尾break;}System.out.println(第i行的文字为line);}breader.reset(); // 重置文件指针令其回到上次标记的位置for (int i1; ; i) {String line breader.readLine(); // 从文件中读出一行文字if (line null) { // 读到了空指针表示已经到了文件末尾break;}System.out.println(又读了一遍 第i行的文字为line);}//breader.lines(); // 返回Stream对象之后可按照流式处理来加工该字符串流} catch (Exception e) {e.printStackTrace();}}注意到以上代码BufferedWriter和BufferedReader的创建语句都位于try后面的圆括号之中这是因为Writer与Reader两大家族统统实现了AutoCloseable接口所以由它们繁衍而来的所有子类都具备自动释放资源的功能。另外try语句支持同时管理多个资源类只要它们的对象创建语句以冒号隔开程序在运行时即可自动回收相关的资源。结合运用读操作和写操作可以实现文件复制的功能无非是一边从源文件中读出数据另一边紧接着往目标文件写入数据。采用缓存读取器和缓存写入器逐行复制的话具体的文件复制代码示例如下private static String mSrcName D:/test/aad.txt;private static String mDestName D:/test/aad_copy.txt;// 通过缓存字符流逐行复制文件private static void copyFile() {File src new File(mSrcName); // 创建一个指定路径的源文件对象File dest new File(mDestName); // 创建一个指定路径的目标文件对象// try(...)允许在圆括号内部拥有多个资源创建语句语句之间以冒号分隔// 分别创建源文件的缓存读取器以及目标文件的缓存写入器try (BufferedReader breader new BufferedReader(new FileReader(src));BufferedWriter bwriter new BufferedWriter(new FileWriter(dest));) {for (int i0; ; i) {String line breader.readLine(); // 从文件中读出一行文字if (line null) { // 读到了空指针表示已经到了文件末尾break;}if (i ! 0) { // 第一行开头不用换行bwriter.newLine(); // 另起一行也就是在文件末尾添加换行标记}bwriter.write(line); // 往文件写入字符串}} catch (Exception e) {e.printStackTrace();}System.out.println(文件复制完成源文件大小src.length()新文件大小dest.length());}或者也可逐个字符来复制文件此时BufferedReader每次调用的read方法只返回整型数表示一个字符并且BufferedWriter每次调用的write方法也只写入该字符对应的整型数。通过依次遍历源文件的所有字符同时往目标文件依次写入这些字符从而完成逐个字符复制文件的操作流程。下面是采取逐字符复制文件的代码例子// 通过缓存字符流逐个字符复制文件private static void copyFileByInt() {File src new File(mSrcName); // 创建一个指定路径的源文件对象File dest new File(mDestName); // 创建一个指定路径的目标文件对象// try(...)允许在圆括号内部拥有多个资源创建语句语句之间以冒号分隔// 分别创建源文件的缓存读取器以及目标文件的缓存写入器try (BufferedReader breader new BufferedReader(new FileReader(src));BufferedWriter bwriter new BufferedWriter(new FileWriter(dest));) {while (true) { // 开始遍历文件中的所有字符int temp breader.read(); // 从源文件中读出一个字符if (temp -1) { // read方法返回-1表示已经读到了文件末尾break;}bwriter.write(temp); // 往目标文件写入一个字符}} catch (Exception e) {e.printStackTrace();}System.out.println(文件复制完成源文件大小src.length()新文件大小dest.length());}需要注意的是使用字符流复制文件只有逐行复制和逐字符复制两种方式不可采取整个读到字符数组再整个写入字符数组的方式。之所以不能通过字符数组复制文件是因为中文跟英文不一样一个汉字会占用多个字节(GBK编码的每个汉字占用两个字节UTF8编码的每个汉字占用三个字节)。若要把文件内容读到字符数组势必先得知晓该数组的长度可是调用文件对象的length方法只能得到该文件的字节长度并非字符长度。譬如“白日依山尽”这个字符串在内存中的字符数组长度为5写到UTF8编码的文件之后文件大小是5*315字节接着想把文件内容读到字符数组然而15字节的文件天晓得它有几个字符可能有5个UTF8编码的中文字符也可能有15个英文字符也可能有5个GBK编码的中文字符加5个英文字符共10个字符总之你根本想不到该分配多大的字符数组。既然确定不了待读取的字符数组长度就无法一字不差地复制文件内容了。