黑马程序员—IO文件操作(2)

来源:互联网 发布:mac安装win10精简版 编辑:程序博客网 时间:2024/06/06 07:03

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

1、内存操作流

 

操作内存流的时候(从读取出来,注意一定要把真正的数据toByteArray或者toCharArray将数据读出来)

之前的文件操作流是以文件的输入输出为主的,当输出的位置变成了内存,那么就称为内存操作流。此时要使用内存流完成内存的输入和输出操作。

如果程序运行过程中要产生一些临时文件,可采用虚拟文件方式实现;

直接操作磁盘的文件很耗性能,使用内存流可以提升性能;jdk里提供了内存流可实现类似于内存虚拟文件的功能。

ByteArrayInputStream:将内容写到内存中     CharArrayReader

ByteArrayOutputStream:将内存中的数据写出      CharArrayWriter

ByteArrayInputStream:构造方法:

publicByteArrayInputStream(byte[] buf):全部内容

publicByteArrayInputStream(byte[] buf,int offset,int length):指定范围的内容

ByteArrayOutputStream:

publicByteArrayOutputStream()

 

 

我的总结:内存流操作:先把数据写到内存中去,然后再从内存中读取出来!提升了性能!

 

例子

//此处用的是内存字节流(写入加输出)

package june6D;

 

importjava.io.ByteArrayInputStream;

importjava.io.ByteArrayOutputStream;

import java.io.IOException;

 

public class ByteArrayDemo7{

    public static void main(String[] args) throws IOException {

       String s = "java is a good language";

       ByteArrayOutputStream bos = new ByteArrayOutputStream();//输出流

       bos.write(s.getBytes());

       // 已经把信息写到了内存中

 

       byte[]bys = bos.toByteArray();//得到真正的数据

       ByteArrayInputStream bis = new ByteArrayInputStream(bys);//输入流,需要源。

       byte[] b = new byte[1024];

       int len;

       while ((len = bis.read(b)) != -1) {

           String data = new String(b, 0, len);

           System.out.println(data);

       }

    }

}

 

 

package june6D;

 

import java.io.CharArrayReader;

import java.io.CharArrayWriter;

 

public class CharArrayDemo8 {

 

    public static void main(String[] args)throws Exception {

       // 用内存字符流先把数据保存到内存中,然后从内存中取出数据

       String s = "河南城建学院";

       CharArrayWriter cw = new CharArrayWriter();

       cw.write(s);// 数据写到了内存中

       char[] ch = cw.toCharArray();

       CharArrayReader cr = new CharArrayReader(ch);

       char[] b = new char[1024];

       int len;

       while ((len = cr.read(b)) != -1){

           String data = new String(b, 0, len);

           System.out.println(data);

       }

    }

}

 

 

2、打印流

(只有两个,PrintWriter和PrintStream)

思考:如果现在要想完成一个字符串或者是boolean型或者是字符型的数据输出使用OutputStream是否方便?

肯定是不方便的,因为OutputStream中只能操作字节数据,所以其他的数据类型很难操作,那么在JavaIO包中为了解决这种问题增加了两种类:PrintStreamPrintWriter

打印流有非常好的打印功能,可以打印任何的数据类型。如,整数,小数,字符串等。

观察PrintStream类的构造:

       public PrintStream(File file) throwsFileNotFoundException    

       public PrintStream(OutputStream out)

虽然PrintStream是OutputStream的子类,但是在实例化的时候依然需要一个OutputStream的对象。

 

PrintWriterPrintStream都属于输出流,分别针对字符和字节。

PrintWriter和PrintStream重载的print()和println()用于多种数据类型的输出。

print()里的参数不能为空;println()可以

PrintWriter和PrintStream输出操作不抛出异常

PrintStream调用println方法有自动flush功能;

 

 

Eg:

package june6D;

 

import java.io.FileWriter;

import java.io.PrintStream;

import java.io.PrintWriter;

 

public class PrintDemo9 {

    public static void main(String[] args)throws Exception {

 

       PrintStream ps = new PrintStream("out.txt");

       // ps.write(12);

       ps.println(10086);

       ps.println(false);

       // ps.print();针对print而言,不可以出现这样的(无参)

       ps.println();// 此时就可以

 

       //备注:System.out.println();想当于ps =System.out;

 

       ps = System.out;

       ps.println("您好!");//控制台操作,注意上一句

       // 字符打印流

       PrintWriter pr = new PrintWriter("out2.txt");

       // PrintWriter(OutputStream out, boolean autoFlush)通过现有的OutputStream创建新的PrintWriter(构造方法)

 

       pr = new PrintWriter(new FileWriter("out2.txt"),true);//自动刷新,否则的话需要关闭资源!

       // 与PrintStream不同,若PrintWriter使用了自动刷新方法,那么必须调用println,print,format这些方法的其中一个才可以实现操作

       pr.println("呼哈哈哈哈");

       pr.println(false);

 

       pr = new PrintWriter(System.out,true);//打印在控制台上

       pr.println(false);

       pr.println("河南城建学院");

       pr.println(376430645);

       // pr.close();//因为使用了自动刷新。

    }

}

 

 

3、格式化输出

 

Java5后,PrintStream类多了printf()方法用于格式化输出操作。但是格式化输出的时候必须指定输出数据的类型:

 

(构造方法)

PrintStream format(String fo, Object... args)使用指定格式字符串和参数将格式化字符串写入此输出流中。

 

 

 

备注:当然你也可以全部使用“%s”来表示所有的数据类型!

格式:

需要格式 % 占位符

 

Eg:

package july7file;

 

import java.io.FileWriter;

import java.io.PrintStream;

import java.io.PrintWriter;

 

public class Demo9 {

    public static void main(String[] args)throws Exception {

      

       PrintStream ps = new PrintStream("E:/name.txt");

      

       ps.write("123456".getBytes());

      

       ps.println(false);

       ps.print(false);

      

       PrintWriter pw = new PrintWriter(new FileWriter("E:/name1.txt"),true);

      

       pw.println("我们的未来!");//write不可以

      

       pw = new PrintWriter(System.out,true);

       pw.println("我们的未来!");//打印在控制台上

      

       String name = "刘昭";

       int age = 13;

       char score = 'A';

      

       String format = "姓名=%s,年龄=%d,成绩=%c";

      

       System.out.printf(format,name,age,score);

      

       int i = System.in.read();//流的重定向

       System.out.println((char)i);

    }

}

 

 

4、标准流

 

   标准输入流:  System.in   默认表示的是键盘录入

   标准输出流:  System.out  默认表示的是屏幕输出

 

Eg:

package june6D;

 

import java.io.FileInputStream;

import java.io.IOException;

import java.io.PrintStream;

 

public class SyetemDemo {

    public static void main(String[] args)throws IOException {

       /**

        *  标准流:标准输入流: System.in 默认表示的是键盘录入

标准输出流:System.out 默认表示的是屏幕输出

        *

        * 若现在我输出不想打印在屏幕上,怎么办?

        * 若现在我不想通过键盘来录入数据,有怎么办?

        *

        * 流的重定向:static void setOut(PrintStream out)重新分配“标准”输出流。 staticvoid

        * setIn(InputStream in)重新分配“标准”输入流。

        */

       System.out.println("123456789");//最普通的打印

       System.err.println("123652");//同样是一种输出流,打印出的是123652

 

       /**

        * static voidsetOut(PrintStream out) 重新分配“标准”输出流。

        */

 

       // 输出流就被重新定义到了文件,而不是屏幕

       System.setOut(new PrintStream("68Demo.txt"));//只有在定义过后才生效,所以上面的还是会输出到控制台

       System.out.println("AAAA");

       System.out.println("BBBB");//就输出了在文件里

 

       int i = System.in.read();//接受从键盘输入的数据,写在最前面(没有任何重新分配)才有效

       System.out.println("i所对应的是:" + (char) i);//把它转换为字符型

       System.out.println(i);

       /**

        * 重新分配,由标准键盘输入变为由文件输入

        */

       System.setIn(new FileInputStream("copy6.4"));//备注:打印的是文件copy6.4中的数据,而且打印在文件68Demo.txt中。

       byte[] buff = new byte[1024];

       int len = 0;

       while ((len = System.in.read(buff)) != -1) {

           System.out.println(new String(buff, 0, len));//此时不会打印在控制台上,因为上面已经重新定义了由打印到屏幕上转换为打印到文件里

       }

    }

}

 

5、Scanner(简单文本扫描器)

 

Scanner(File source) 构造一个新的 Scanner,它生成的值是从指定文件扫描的。

备注:实现了Iterable接口

 

package june6D;

 

import java.io.File;

import java.io.PrintStream;

import java.util.Scanner;

 

public class ScannerDemo18 {

    public static void main(String[] args)throws Exception {

 

       // 参照api

       Scanner sc = new Scanner(System.in);//从键盘输入

       // int i = System.in.read();

       /*  连着进行了三次,没有完成的话不停止运行

           System.out.println(sc.next());                                                                                                                                     System.out.println(sc.next());

        *  System.out.println(sc.next());

        */

       System.setOut(new PrintStream("Scanner.txt"));//流的重定向(打印到哪里)

       sc = new Scanner(new File("copy6.4"));//扫描位置

       int line = 1;

       while (sc.hasNextLine()) {//是否有下一行//一行一行的读取,这样的话格式好看

           System.out.println(line +" " + sc.nextLine());//读取下一行

           line++;

       }

    }

}

 

例子:

猜数字游戏:

1. 系统随机生成一个数字[1,100];

2. 从键盘录入一个数字,[1,100]

3.  判断输入的数字和随机数比较:

    随机数 >输入数:你输入太小了

随机数 <输入数:输入太大了

随机数 = 输入数: 恭喜哦

 

思考:先想怎么生成一个随机数;然后怎么在键盘中录入一个随机数,第三步就是比较了;但是注意的是:需要确保输入的数据为数字,而且有范围的限制!

 

 

package july7file;

 

import java.util.Random;

import java.util.Scanner;

 

public class Demo12 {

    public static void main(String[] args) {

      

       guess();

    }

   

    public static void guess(){

       int i = new Random().nextInt(100)+1;

      

       System.out.println(i);

       System.out.println("请输入随机数来匹配,您有五次机会!");

       Scanner sc = new Scanner(System.in);//键盘录入

      

       for (int j = 0; j < 5; j++) {

           String s = sc.nextLine();

          

           if(!s.matches("\\d+")){

              System.out.println("请确认您输入的是数字");

              break;

           }

           Integer in = new Integer(s);

           if(in > 100 | in < 0){

              System.out.println("请确认您输入的数字在0到100之间!");

           }

          

           switch (in.compareTo(i)) {

           case 1:

              System.out.println("您输入的数字过大!");

              System.out.println("请输入:");

              break;

             

           case -1:

              System.out.println("您输入的数字过小!");

              System.out.println("请输入:");

              break;

 

           default:

              System.out.println("恭喜您,您输入的数字正好匹配!");

              return;

           }

       }

    }

}

 

 

6、缓冲流

 

缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写效率,同时增加了一些新的方法。

四种缓冲流

BufferedReader(Readerin)

BufferedReader(Readerin,int sz)//sz表示自定义缓冲区大小

BufferedWriter(Writerout)

BufferedWriter(Writerout,int sz)

BufferedInputStream(InputStreamin)

BufferedInputStream(InputStreamin,int sz)

BufferedOutputStream(OutputStreamout)

BufferedOutputStream(OutputStreamout,int sz)

 

BufferedReader提供readLine方法用于读取一行字符串。

BufferedWriter提供了newLine方法用于写入一个行分隔符。等价于//.writer("\r\n");

对于输出的缓冲流,写出的数据会先在内存中缓冲,使用flush方法将会使内存中的数据立刻写出。

 

Eg:

package june6D;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

 

//用缓冲,性能相对高些

public class BufferedInputStreamDemo22 {

    public static void main(String[] args)throws IOException {

       /*

        * BufferedInputStream bis= new BufferedInputStream(new

        *FileInputStream("68.txt")); BufferedOutputStreambos =new

        *BufferedOutputStream(new FileOutputStream("buffer.txt"));

        *

        * int len= 0;

        * while((len =bis.read()) != -1){

        * bos.write(len);

        * }

        * bos.close();

        * bis.close();

        */

      

       try (

BufferedReader br = new BufferedReader(new FileReader("68.txt"));

    BufferedWriter bw = new BufferedWriter(new FileWriter(

                     "bufferWriter.txt")))

{//java7新特性,自动关闭资源

           String Line = null;

           while ((Line = br.readLine()) !=null) {

              bw.write(Line);

              bw.newLine();//此时必须加上换行操作,注意这是个新用法(方法)

           }

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

}

 

我的总结:在后续的学习中,缓冲流用到的会很多,因为效率高!

 

 

7、合并流(SequenceInputStream)

 

需要两个源文件,还有输出的目标文件

 

SequenceInputStream:

将两个文件的内容合并成一个文件

该类提供的方法:

SequenceInputStream(InputStreams1, InputStream s2) :根据两个字节输入流对象来创建合并流对象。

 

备注:谁放在前面,谁就先打印出来

 

Eg:

package june6D;

 

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import java.io.SequenceInputStream;

 

//和并两个文件的合并流

public class SequenceInputStreamDemo24 {

    public static void main(String[] args)throws IOException {

      

       SequenceInputStream si = new SequenceInputStream(

              new FileInputStream("6.4"),

              new FileInputStream("hello.java"));

      

       OutputStream os = new FileOutputStream("sequence.txt");

       int len;

       byte []b = new byte[1024];

       while((len = si.read(b)) != -1){

           os.write(b, 0, len);

       }

    }

}

0 0