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

 

posted on 2013-03-28 20:34  小强斋太  阅读(355)  评论(0编辑  收藏  举报

导航