zoukankan      html  css  js  c++  java
  • java基础>I/O 小强斋

    IO操作作为整个JAVA中最复杂的开发包,但是要想跨过此部分,就必须对面向对象的基本概念非常的熟悉,对于抽象类也要熟悉。

    根据实例化子类的不同,完成的功能也不同。这句话就是IO操作的核心。

    整个IO包中实际上需要的就是五个类和一个接口:FileOutputStreamInputStreamWriterReaderSerializable

       所有的类和接口基本上都在java.io包中定义的。

       在IO操作记住:输出的时候使用PrintStream,输入的时候使用Scanner。

    一、File类

     File类的构造:publicFile(String pathname),在建立File对象的时候需要指定一个路径。

    现在要想创建一个文件,可以使用方法:public booleancreateNewFile() throwsIOException

    import java.io.File;
    
    public class FileDemo01 {
    
        public  static void main(String[] args)throws Exception {
    
            File file = new File("d:\\temp.txt");// 指定要操作的文件路径
    
            file.createNewFile();
    
        }
    
    }
    

    既然可以创建文件,那肯定也可以删除:public boolean delete()

    但是如果要想删除文件,则肯定要判断文件是否存在:public boolean  exists()

     那么下面完成这样的一个程序:如果文件存在,则删除掉,如果文件不存在,则创建新的。

    import java.io.File;
    
    public  class FileDemo01 {
    
        public static void main(String[] args)throws Exception {
    
            File file = new File("d:\\temp.txt");// 指定要操作的文件路径
    
            if (file.exists()) {
    
                file.delete(); // 删除文件
    
            } else {
    
                file.createNewFile();// 创建新文件
    
            }
    
        }
    
    }
    

    但是在创建和删除文件的时候发现会出现延迟的问题,因为JAVA运行机制是运行在JVM上,由JVM进行OS的具体的适应,所以中间存在延迟,而且本程序也有问题,在Java的最大特点是可移植性,但是在不同的操作系统中路径的分割符肯定是不一样的:

                       · windows中使用“\”

                       · linux中使用“/”

    那么要想解决这样的问题,就必须观察File类定义的常量:public static final String separator

    separator是一个常量,按照常量的命名要求肯定全部的字母都要大写:SEPARATOR。这些都是由于Java发展的历史原因所造成的问题。

    File file = new File("d:" + File.separator + "temp.txt");// 指定要操作的文件路径
    

    由于在给定文件的路径上有可能给出的是一个文件,也有可能给出的是一个文件夹,那么为了判断,在File类中提供了以下的两个方法:

                       ·判断是否是文件:         public  boolean  isFile()

                       ·判断是否是文件夹:     public  boolean  isDirectory()

    范例:判断类型

    import java.io.File;
    
    public  class FileDemo02 {
    
        public  static  void main(String[] args)throws Exception {
    
            File file1 = new File("d:" + File.separator + "temp.txt");// 指定要操作的文件路径
    
            File file2 = new File("d:" + File.separator + "testjava");// 指定要操作的文件路径
    
            System.out.println(file1.isFile());
    
            System.out.println(file2.isDirectory());
    
        }
    
    }
    

    在File类的操作中可以通过代码列出一个文件夹之中的完整内容,方法如下:

                       ·列出文件或文件夹的名称:public String[] list()

                       ·列出完整的路径,而且返回的是File类的对象:public   File[] listFiles()

    范例:使用list()方法

    import java.io.File;
    
    public  class FileDemo03 {
    
        public  static  void main(String[] args)throws Exception {
    
            File file = new File("d:" + File.separator + "testjava");// 指定要操作的文件路径
    
            if (file.isDirectory()) {// 如果是文件夹,则列出内容
    
                String list[] = file.list();// 列出全部的内容
    
                for (int x = 0; x < list.length; x++) {
    
                    System.out.println(list[x]);
    
                }}}}
    

    范例:使用listFiles()完成列表

    import java.io.File;
    
    public  class FileDemo03 {
    
        public  static   void main(String[] args)throws Exception {
    
            File file = new File("d:" + File.separator + "testjava");// 指定要操作的文件路径
    
            if (file.isDirectory()) {// 如果是文件夹,则列出内容
    
                File list[] =  file.listFiles() ;   // 列出全部内容
    
                for (int x = 0; x < list.length; x++) {
    
                    System.out.println(list[x]);
    
                }}}}
    

    使用listFiles()方法输出的时候可以输出一个完整的路径,而且返回的是File类的对象,可以进行更多的操作。

    import java.io.File;
    
    publicclass FileDemo03 {
    
        public  static  void main(String[] args)throws Exception {
    
            File file = new File("d:" + File.separator + "testjava");// 指定要操作的文件路径
    
            if (file.isDirectory()) {// 如果是文件夹,则列出内容
    
                File list[] = file.listFiles() ;   // 列出全部内容
    
                for (int x = 0; x < list.length; x++) {
    
                    System.out.println(list[x] +" --> " +  list[x].length());
    
                }}}}
    

    思考题:

    现在要求输出一个给定目录中的全部文件的路径。

    本程序肯定只能依靠递归的操作完成,因为在一个给定的路径下有可能还是文件夹,那么如果是文件夹的话则肯定要继续列出,重复判断。

    import java.io.File;
    
    public  class ListFileDemo {
    
        public  static  void main(String[] args) {
    
            File file = new File("D:" + File.separator);
    
            list(file);
    
        }
    
        public  static  void list(File file) {
    
            if (file.isDirectory()) {// 如果是文件夹,则继续列出
    
                File f[] = file.listFiles();
    
                if (f !=null) {// 文件夹的内容已经列出
    
                    for (int x = 0; x < f.length; x++) {
    
                        list(f[x]);// 继续列出每一个内容
    
                    }
    
                }
    
            }
    
            System.out.println(file);
    
        }
    
    }
    

    二、字节流与字符流

             File类本身是与文件操作有关,但是如果要想操作内容则必须使用字节流或字符流完成,但是不管是使用何种的输入输出流,其基本的操作原理是一样的(以文件流为准)

                      1  使用File类找到一个文件

                      2  通过字节流或字符流的子类进行对象的实例化

                      3  进行读或写的操作

                      4  关闭字节或字符流

          由于流的操作属于资源操作,所以在操作的最后一定要关闭以释放资源。

          操作流有以下几个:

                       ·字节流:OutputStream、InputStream

                       ·字符流:Writer、Reader

    2.1、字节输出流

    字节输出流使用的是OutputStream,此类定义如下:

    public abstract  class OutputStream extends Object implements Closeable, Flushable

    本类是一个抽象类,根据面向对象的概念,要通过子类进行对象的实例化操作。

    在此类中定义了如下的几个常用方法:

    public abstract class OutputStream extends Object implements Closeable, Flushable 
    {
        public abstract void write(int b) throws IOException;  	//写入一个字节,抽象方法
        public void write(byte[] b) throws IOException     		//将缓冲区中的若干字节写入输出流
        public void flush() throws IOException {}         		//立即传输
        public void close() throws IOException {}         		//关闭输出流,空方法
    }
    

    但是要想为OutputStream实例化,且进行文件操作的话,就要使用FileOutputStream子类。

         ·构造:public FileOutputStream(File file) throwsFileNotFoundException

    范例:使用字节流进行输出,输出“HelloWorld”。

    import java.io.File;
    
    import java.io.FileOutputStream;
    
    import java.io.OutputStream;
    
    public class OutputStreamDemo01 {
    
        public  static  void main(String[] args)throws Exception {
    
            // 1、通过File找到一个文件
    
            File file = new File("d:" + File.separator + "temp.txt");
    
            // 2、实例化OutputStream对象
    
            OutputStream out = new FileOutputStream(file);
    
            String info = "Hello  World!!!"; //要输出的字符串
    
            byte data[] = info.getBytes();// 将字符串变为字节数组
    
            out.write(data); // 输出内容
    
            out.close();
    
        }
    
    }
    

    现在已经可以向文件中输出内容了,但是此时程序每执行一次,实际上都会输出,但是属于覆盖的操作,如果要想在文件的尾部追加的话,则必须观察FileOutputStream类的另外一个构造:

                      ·追加:public FileOutputStream(File file,boolean append) throwsFileNotFoundException

                       如果需要在追加的上面加入换行的话,使用“\r\n”。

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    public class OutputStreamDemo01 {
    	public static void main(String[] args) throws Exception {
    		// 1、通过File找到一个文件
    		File file = new File("d:" + File.separator + "temp.txt");
    		// 2、实例化OutputStream对象
    		OutputStream out = new FileOutputStream(file, true); // 追加
    		String info = "\r\nHello World!!!"; // 要输出的字符串
    		byte data[] = info.getBytes(); // 将字符串变为字节数组
    		out.write(data); // 输出内容
    		out.close();
    	}
    }
    

    2.2、字节输入流

     程序中可以使用OutputStream进行输出的操作,也可以使用InputStream完成输入的操作,此类定义如下:

    public abstract class InputStream extends Object implements Closeable 
    {
        public abstract int read() throws IOException;   		//返回读取的一个字节,抽象方法
        public int read(byte[] b) throws IOException             //从输入流中读取若干字节到指定缓冲区,返回实际读取的字节数
        public void close() throws IOException {}       			//关闭输入流,空方法
    }
    

    类依然是一个抽象类,肯定要使用子类完成,如果是文件输入,使用FileInputStream类。

    如果要读,则肯定需要一个数组,数组肯定要首先开辟好大小,用于接收内容。

    但是,与OutputStream类似,要读取就要观察FileInputStream类的构造方法:

    ·构造:public FileInputStream(File file) throwsFileNotFoundException

    import java.io.File;
    
    import java.io.FileInputStream;
    
    import java.io.InputStream;
    
    public class InputStreamDemo01 {
    
        public  static  void main(String[] args)throws Exception {
    
            File file = new File("d:" + File.separator + "temp.txt");
    
            InputStream input = new FileInputStream(file);
    
            byte data[] =new byte[1024];// 开辟一个空间
    
            int len = input.read(data);// 接收输入流的内容
    
            System.out.println("内容是:(" + new String(data, 0, len) +")");
    
        }
    
    }
    

    以上的代码属于一次性全部读取,但是在InputStream类中也可以每次读取一个字节。

    import java.io.File;
    
    import java.io.FileInputStream;
    
    import java.io.InputStream;
    
    public class InputStreamDemo02 {
    
        public   static   void main(String[] args)throws Exception {
    
            File file = new File("d:" + File.separator + "temp.txt");
    
            InputStream input = new FileInputStream(file);
    
            byte data[] =new  byte[1024];// 开辟一个空间
    
            int len = 0;// 记录读取的长度
    
            int temp = 0;
    
            do {
    
                temp = input.read();// 读取一个字节
    
                if (temp != -1) {// 如果不为-1表示内容可以增加
    
                    data[len++] = (byte) temp;// 保存在字节数组中
    
                }
    
            } while (temp != -1);// 如果不是-1表示还有内容可以读
    
            System.out.println("内容是:(" + new String(data, 0, len) +")");
    
        }
    
    }
    

    但是以上的读取方式在开发中会变成另外一种代码形式:

    int temp = 0;
    
            while ((temp = input.read()) != -1) {
    
                data[len++] = (byte) temp;
    
            }
    

     2.3、字符输出流

    Writer属于字符输出流,Writer类也是一个抽象类,既然要操作文件,肯定使用FileWriter。

    import java.io.File;
    
    import java.io.FileWriter;
    
    import java.io.Writer;
    
    public  class WriterDemo01 {
    
        public   static  void main(String[] args)throws Exception {
    
            File file = new File("d:" + File.separator + "temp.txt");
    
            Writer out = new FileWriter(file);
    
            out.write("Hello  World");// 直接输出字符串
    
            out.close() ;
    
        }
    
    }
    

    2.4、字符输入流

     Reader也肯定是一个抽象类,要输入文件使用FileReader。

    import java.io.File;
    
    import java.io.FileReader;
    
    import java.io.Reader;
    
    public  class ReaderDemo01 {
    
        public  static  void main(String[] args)throws Exception {
    
            File file = new File("d:" + File.separator + "temp.txt");
    
            Reader read = new FileReader(file);
    
            char data[] =new  char[1024];
    
            int len = read.read(data);
    
            System.out.println(new String(data, 0, len));
    
        }
    
    }
    

    2.5、字节流和字符流的区别

    微笑Java 流在处理上分为字符流和字节流。字符流处理的单元为2个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他编码的字符流和 java 内 Unicode 字符流之间的转换。而类 InputStreamReader 和 OutputStreamWriter 处理字符流和字节流的转换。字符流(一次可以处理一个缓冲区)一次操作比字节流(一次一个字节)效率高。

     微笑字节流和字符流在使用上的代码结构都是非常类似的,但是其内部本身也是有区别的,因为在进行字符流操作的时候会使用到缓冲区,而字节流操作的时候是不会使用到缓冲区的。在输出的时候,OutputStream类即使最后没有关闭内容也可以输出。但是如果是Writer的话,则如果不关闭,最后一条内容是无法输出的,因为所有的内容都是保存在了缓冲区之中,每当调用了close()方法就意味着清空缓冲区了。那么可以证明字符流确实使用了缓冲区。如果现在字符流即使不关闭也可以完成输出的话,则必须强制性清空缓冲区:

    方法:public void flush()throws IOException

    字节流不关闭,但是文件中也依然存在了输出的内容,证明字节流是直接操作文件本身的。

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    
    public class OutputStreamDemo05 {
    	public static void main(String[] args) throws Exception { // 异常抛出, 不处理
    	// 第1步:使用File类找到一个文件
    		File f = new File("d:" + File.separator + "test.txt"); // 声明File 对象
    		// 第2步:通过子类实例化父类对象
    		OutputStream out = null;
    		// 准备好一个输出的对象
    		out = new FileOutputStream(f);
    		// 通过对象多态性进行实例化
    		// 第3步:进行写操作
    		String str = "Hello World!!!";
    		// 准备一个字符串
    		byte b[] = str.getBytes();
    		// 字符串转byte数组
    		out.write(b);
    		// 将内容输出
    		// 第4步:关闭输出流
    		// out.close();
    		// 此时没有关闭
    	}
    }


    字符流不关闭

    import java.io.File;
    import java.io.FileWriter;
    import java.io.Writer;
    
    public class WriterDemo03 {
    	public static void main(String[] args) throws Exception { // 异常抛出, 不处理
    		// 第1步:使用File类找到一个文件
    		File f = new File("d:" + File.separator + "test.txt");// 声明File 对象
    		// 第2步:通过子类实例化父类对象
    		Writer out = null;
    		// 准备好一个输出的对象
    		out = new FileWriter(f);
    		// 通过对象多态性进行实例化
    		// 第3步:进行写操作
    		String str = "Hello World!!!";
    		// 准备一个字符串
    		out.write(str);
    		// 将内容输出
    		// 第4步:关闭输出流
    		// out.close();
    		// 此时没有关闭
    	}
    }

    程序运行后会发现文件中没有任何内容,这是因为字符流操作时使用了缓冲区,而在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭,则缓冲区中的内容是无法输出的,所以得出结论:字符流使用了缓冲区,而字节流没有使用缓冲区。

    两者相比,肯定使用字节流更加的方便,而且在程序中像图片、MP3等都是采用字节的方式的保存,那么肯定字节流会比字符流使用的更广泛。但是需要说明的是,如果要是想操作中文的话,字符流肯定是最好使的。

    2.6、例子:文件拷贝

             现在要求完成一个Copy程序,完全模仿DOS中的拷贝命令。

             命令的运行形式,可以通过初始化参数的方式设置两个路径

                       ·形式:java Copy源文件路径目标文件路径

             本程序完成有两个思路:

                       ·思路一:将所有的内容全部读取进来,之后一次性保存

                       ·思路二:边读边写

             而且要进行读取的时候还要判断源文件是否存在。

    import java.io.File;
    
    import java.io.FileInputStream;
    
    import java.io.FileOutputStream;
    
    import java.io.InputStream;
    
    import java.io.OutputStream;
    
    public class Copy {
    
        public  static  void main(String[] args)throws Exception {
    
            if (args.length != 2) {
    
                System.out.println("语法命令不正确!");
    
                System.exit(1);
    
            }
    
            File file1 = new File(args[0]);
    
            if (file1.exists()) {// 如果源文件存在
    
                File file2 = new File(args[1]);
    
                InputStream input = new FileInputStream(file1);
    
                OutputStream output =new FileOutputStream(file2);
    
                int temp = 0;
    
                while ((temp = input.read()) != -1) {// 边读边写
    
                    output.write(temp);// 输出
    
                }
    
                input.close();
    
                output.close();
    
                System.out.println("文件拷贝完成。");
    
            }
    
        }
    
    }
    

    三、内存操作流

     之前的文件操作流是以文件的输入输出为主的,但是如果现在将输入输出的位置一改变,改变成了内存,那么就称为内存操作流。使用ByteArrayInputStream完成内存的输入操作,而使用ByteArrayOutputStream完成内存的输出操作,但是一定要注意的是,现在的输入和输出都是以内存为标准的。

         ByteArrayInputStream构造:public ByteArrayInputStream(byte[] buf)

    import java.io.ByteArrayInputStream;
    
    import java.io.ByteArrayOutputStream;
    
    import java.io.InputStream;
    
    import java.io.OutputStream;
    
    public  class ByteArrayDemo {
    
        public  static  void main(String[] args)throws Exception {
    
            String info = "helloworld";
    
            InputStream input = new ByteArrayInputStream(info.getBytes());
    
            OutputStream output = new ByteArrayOutputStream();
    
            int temp = 0;
    
            while ((temp = input.read()) != -1) {
    
                output.write(Character.toUpperCase((char) temp));
    
            }
    
            String str = output.toString(); // 取出内容
    
            input.close() ;
    
            output.close() ;
    
            System.out.println(str) ;
    
        }
    
    }
    

    现在虽然完成了内存的操作,但是可以发现现在的IO都是从内存中,也就是说可以将内存当作一个临时的文件进行操作,所以内存操作流一般在产生临时文件内容的时候使用

    四、打印流

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

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

    4.1、 PrintStream

             观察PrintStream类的构造:public PrintStream(OutputStream out)

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

             在PrintStream中定义了一系列的输出操作,可以方便的完成输出,那么这种设计思路就是装饰设计

    import java.io.File;
    
    import java.io.FileOutputStream;
    
    import java.io.PrintStream;
    
    public class PrintStreamDemo01 {
    
        public  static  void main(String[] args)throws Exception {
    
            PrintStream out = new PrintStream(new FileOutputStream(new File("d:"
    
                    + File.separator +"test.txt")));
    
            out.print(1 + " +  " + 1 + " = ");
    
            out.println(1 + 1);
    
            out.println("Hello World!!!") ;
    
        }
    
    }
    

    在开发中由于PrintStream较为好用,所以只要是输出就使用打印流完成。一些数据的表示格式:%d、%f、%s

    import java.io.File;
    
    import java.io.FileOutputStream;
    
    import java.io.PrintStream;
    
    public  class PrintStreamDemo02 {
    
        public  static  void main(String[] args)throws Exception {
    
            PrintStream out = new PrintStream(new FileOutputStream(new File("d:" + File.separator +"test.txt")));
    
            String name = "张三";
    
            int age = 30;
    
            float score = 90.89765f;
    
            out.printf("姓名:%s,年龄:%d,成绩:%5.2f", name, age, score);
    
        }
    
    }
    

    4.2、PrintWriter

    PrintStream是OutputStream的子类,PrintWriter是Writer的子类,两者处于对等的位置上,PrintWriter是一种过滤流,也叫处理流。也就是能对字节流和字符流进行处理,所以它会有一下的构造方法。

    PrintWriter(OutputStream out)  根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。

    PrintWriter(Writer out)        创建不带自动行刷新的新 PrintWriter

    然后PrintWriter能够直接对文件操作,所以还有这两种构造方法:

    PrintWriter(File file)        使用指定文件创建不具有自动行刷新的新 PrintWriter。

    PrintWriter(String fileName)  创建具有指定文件名称且不带自动行刷新的新 PrintWrite

    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.FileWriter;
    import java.io.File;
    
    public class PrintWriterDemo {
    
    	public static void main(String[] args) {
    		PrintWriter pw = null;
    		String name = "wsz";
    		int age = 22;
    		float score = 32.5f;
    		char sex = '男';
    		try {
    			pw = new PrintWriter(new FileWriter(new File("e:\\file.txt")), true);
    			pw.printf("姓名:%s;年龄:%d;性别:%c;分数:%5.2f;", name, age, sex, score);
    			pw.println();
    			pw.println("多多指教");
    			pw.write(name.toCharArray());
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			pw.close();
    		}
    	}
    }

    4.3、两者区别

    PrintStream是字节流,它有处理byte的方法,write(int)和write(byte[],int,int);PrintWriter是字符流,它没有处理byte的方法。PrintStream和PrintWriter的auto flushing机制有点不同,前者在输出byte数组、调用println方法、输出换行符或者byte值10(即\n)时自动调用flush方法,后者仅在调用println方法时发生auto flushing。

    五、System类对IO的支持

             在System类中定义了以下的三个常量:

                       ·错误输出:public static final PrintStream err

                       ·屏幕输出:public static final PrintStream out

                       ·键盘输入:public static final  InputStream  in

    5.1、错误输出

    System.err表示的是错误的输出,此类型也属于PrintStream类型。

    public  class SystemErrDemo {
    
        public  static  void main(String[] args) {
    
            try {
    
                Integer.parseInt("A");
    
            } catch (NumberFormatException e) {
    
                System.err.println(e);
    
            }
    
        }
    
    }
    

    使用System.err和System.out的输出是完全一样的,但是在Eclipse中System.err的输出会使用红色表示。两个的区别只是人为的增加的区别,System.err一般是不希望用户看见的错误,而System.out是希望用户看见的错误。

    5.2、屏幕输出

    System.out属于屏幕输出的操作,对应着显示器,但是可以通过System.out为OutputStream实例化。

    import java.io.OutputStream;
    
    public  class SystemOutDemo {
    
        public  static  void main(String[] args)throws Exception {
    
            OutputStream out = System.out ;
    
            out.write("hello  world".getBytes()) ;
    
        }
    
    }
    

    5.3、键盘输入

     一般的语言中都存在着键盘输入数据的操作,在Java中也有,只是一般来讲这种操作不是现成的,而且必须依靠IO流的操作才能完成,输入靠的是System.in。

    import java.io.InputStream;
    
    public  class SystemInDemo {
    
        public static void main(String[] args)throws Exception {
    
            InputStream input = System.in;// 可以由键盘输入
    
            byte data[] =new byte[1024];
    
            System.out.print("请输入内容:");
    
            int len = input.read(data);
    
            System.out.println("输入的内容是:" + new String(data, 0, len));
    
        }
    
    }
    

    此时已经完成了内容的输入,但是本程序有问题,因为现在所有的输入内容都是保存在了data这个字节数组之中,如果现在输入的内容的长度大于数组中的长度的话,则超出的部分无法接收。

     这种操作出现问题的主要原因是一开始的数组大小限制了长度,那么如果现在没有长度限制呢?

    import java.io.InputStream;
    
    public class SystemInDemo {
    
        public static  void main(String[] args)throws Exception {
    
            InputStream input = System.in;// 可以由键盘输入
    
            StringBuffer buf = new StringBuffer();
    
            System.out.print("请输入内容:");
    
            int temp = 0;
    
            while ((temp = input.read()) != -1) {
    
                char c = (char) temp;
    
                if (c =='\n') {
    
                    break ;
    
                }
    
                buf.append(c);
    
            }
    
            System.out.println("输入的内容是:" + buf);
    
        }
    
    }
    

     这种输入现在只能适合于英文环境上,因为是按照每一个字节的方式读取的,而一个中文是两个字节。

    所以,如果要想彻底的解决问题,最好的做法是,将所有的输入内容暂时存放到一个缓冲区之中,之后从缓冲区里一次性将内容全部读取回来。

    六、BufferedReader

             BufferedReader的主要功能是用于缓冲区读取的,但是有一点,从类的定义上可以发现,此类属于字符输入流,而System.in属于字节流,那么很明显,如果要想使用BufferedReader就需要将一个字节流变成字符流,为了解决这样的问题,在Java中提供了以下的两个转换类

             ·将输入的字节流变为字符流:InputStreamReader

            ·将输出的字符流变为字节流: OutputStreamWriter

             在BufferedReader类中提供了一个专门的读取操作:public String readLine() throws IOException

    import java.io.BufferedReader;
    
    import java.io.InputStreamReader;
    
    public class BufferDemo {
    
        public static void main(String[] args)throws Exception {
    
            BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
    
            System.out.print("请输入内容:");
    
            String info = null;// 用于接收输入的内容
    
            info = buf.readLine(); // 接收内容
    
            System.out.println(info);
    
        }
    
    }
    

    由于所有的内容都是从缓冲区一次性读取完成的,那么不会出现乱码问题。以上就是一个键盘输入的标准程序

    七、Scanner类

     在JDK 1.5之后为了方便输入,又增加了一个新的类:Scanner,此类并不是在java.io包中定义的,而是在java.util包中定义的public final class Scanner implements Iterator<String>,。使用Scanner可以方便的完成各种字节输入流的输入

    构造:public Scanner(InputStream source)

    Scanner类实现了Iterator接口,所以它有以下方法。

    boolean hasNext()方法

    Object next()方法

    void remove()方法

    useDelimiter()使用定界符的意思

    nextXxx()从流中读取一个Xxx并返回Xxx值。

    import java.util.Scanner;
    
    public  class ScannerDemo01 {
    
        public  static void main(String[] args) {
    
            Scanner scan = new Scanner(System.in);
    
            System.out.print("请输入内容:");
    
            if (scan.hasNext()) {// 现在有内容
    
                String str = scan.next();
    
                System.out.println("输入的内容是:" + str);
    
            }
    
        }
    
    }
    

    除了这种功能之外,使用Scanner也可以输入各种数据类型,例如:float。

    import java.util.Scanner;
    
    public  class ScannerDemo02 {
    
        public  static  void main(String[] args) {
    
            Scanner scan = new Scanner(System.in);
    
            System.out.print("请输入内容:");
    
            if (scan.hasNextInt()) {// 现在有内容
    
                int str = scan.nextInt();
    
                System.out.println("输入的内容是:" + str);
    
            }
    
        }
    
    }
    

    但是,如果要想进行其他数据格式验证的话,则就需要编写正则表达式完成了。

    import java.text.ParseException;
    
    import java.text.SimpleDateFormat;
    
    import java.util.Date;
    
    import java.util.Scanner;
    
    publicclass ScannerDemo03 {
    
        public  static  void main(String[] args) {
    
            Scanner scan = new Scanner(System.in);
    
            System.out.print("请输入日期:");
    
            if (scan.hasNext("\\d{4}-\\d{2}-\\d{2}")) {// 现在有内容
    
                String str = scan.next("\\d{4}-\\d{2}-\\d{2}");
    
                Date date = null;
    
                try {
    
                    date = new SimpleDateFormat("yyyy-MM-dd").parse(str);
    
                } catch (ParseException e) {
    
                    e.printStackTrace();
    
                }
    
                System.out.println(date);
    
            }
    
        }
    
    }
    

    使用Scanner类除了可以完成以上的输入之外,也可以从一个文件流中输入内容。

    import java.io.File;
    
    import java.io.FileInputStream;
    
    import java.util.Scanner;
    
    public  class ScannerFileDemo {
    
        public  static  void main(String[] args)throws Exception {
    
            Scanner scan = new Scanner(new FileInputStream(new File("d:"+ File.separator +"test.txt")));
    
            scan.useDelimiter("\n");// 将换行作为分隔符
    
            while (scan.hasNext()) {
    
                String str = scan.next();
    
                System.out.print(str);
    
            }
    
        }
    
    }
    

    八、Java IO 的一般使用原则 :

    一、按数据来源(去向)分类:

    1. 是文件: FileInputStream, FileOutputStream, ( 字节流 )FileReader, FileWriter( 字符 )
    2. 是 byte[] : ByteArrayInputStream, ByteArrayOutputStream( 字节流 )
    3. 是 Char[]: CharArrayReader, CharArrayWriter( 字符流 )
    4. 是 String: StringBufferInputStream, StringBufferOuputStream ( 字节流 )StringReader, StringWriter( 字符流 )
    5. 网络数据流: InputStream, OutputStream,( 字节流 ) Reader, Writer( 字符流 )

    二、按是否格式化输出分:
        要格式化输出: PrintStream, PrintWriter
    三、按是否要缓冲分:
        要缓冲:BufferedInputStream, BufferedOutputStream,(字节流) BufferedReader, BufferedWriter(字符流)
    四、按数据格式分:
        1 、二进制格式(只要不能确定是纯文本的) : InputStream, OutputStream 及其所有带 Stream 结束的子类
        2 、纯文本格式(含纯英文与汉字或其他编码方式); Reader, Writer 及其所有带 Reader, Writer 的子类
    五、按输入输出分:
        1 、输入: Reader, InputStream 类型的子类
        2 、输出: Writer, OutputStream 类型的子类
    六、特殊需要:
        1 、从 Stream 到 Reader,Writer 的转换类: InputStreamReader, OutputStreamWriter
        2 、对象输入输出: ObjectInputStream, ObjectOutputStream
        3 、进程间通信: PipeInputStream, PipeOutputStream, PipeReader, PipeWriter
        4 、合并输入: SequenceInputStream
        5 、更特殊的需要: PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader

    决定使用哪个类以及它的构造进程的一般准则如下(不考虑特殊需要):
    首先,考虑最原始的数据格式是什么: 原则四
    第二,是输入还是输出:原则五
    第三,是否需要转换流:原则六第1点
    第四,数据来源(去向)是什么:原则一
    第五,是否要缓冲:原则三 (特别注明:一定要注意的是 readLine() 是否有定义,有什么比 read, write 更特殊的输入或输出方法)
    第六,是否要格式化输出:原则二

    IO操作记住:输出的时候使用PrintStream,输入的时候使用Scanner

    总结

    1、使用File类可以操作文件,但是在编写文件分隔符的时候要注意使用File.separator

    2、字节流和字符流最大的区别在于字符流使用到了缓冲区操作,但是一般字节流使用较多

    3、内存流是所有的输入输出都在内存中完成:ByteArrayInputStream、ByteArrayOutputStream

    4、如果要输出内容可以使用PrintStream类方便的完成

    5、如果要输入内容可以使用Scanner类

    6、对象序列化http://blog.csdn.net/ncepustrong/article/details/8125025

  • 相关阅读:
    透明的LISTVIEW
    循序渐进实现仿QQ界面(三):界面调色与控件自绘
    循序渐进实现仿QQ界面(一):园角矩形与双缓冲贴图窗口
    循序渐进实现仿QQ界面(二):贴图按钮的三态模拟
    C#中如何通过点击按钮切换窗口
    jQuery -- 光阴似箭(二):jQuery效果的使用
    jQuery -- 光阴似箭(一):初见 jQuery -- 基本用法,语法,选择器
    JavaScript -- 时光流逝(十三):DOM -- Console 对象
    JavaScript -- 时光流逝(十二):DOM -- Element 对象
    JavaScript -- 时光流逝(十一):DOM -- Document 对象
  • 原文地址:https://www.cnblogs.com/xiaoqiangzhaitai/p/5429382.html
Copyright © 2011-2022 走看看