javaIO stream (IV) - input and output support

A print stream
  if we want to achieve output of content through the program, the nature of the core must rely on the support of OutputStream OutputStream class but there is a major drawback, the limited data output operation function of this class, all data must be converted after byte array can only operate: public void write (byte b [ ]) throws IOException, assuming said possible output item is long, double, date, in this case the data must be converted to byte the processed form, such a process must be very troublesome when it is initially in order to solve such a repeated operation, they tend to self-defined by the developer in the development of some functional classes to simplify output operation:

. 1  class PrintUtil {     // implement some common data output Mountains 
2      Private the OutputStream Output;         // regardless of the output operations, the core is the OutputStream 
. 3      
. 4      public  void Print (String STR) throws IOException {       // output string 
. 5          the this .OUTPUT .write (str.getBytes ());
 . 6      }
 . 7 }

- In our output over, we can not only to the operation of the output files, memory, a single pipeline for output, output for the environment can be very much, so we can not limit output environment, so if we in PrintUtil directly class that defines an instance object OutputStream class, then the class code completed coupling will cause severe (this class can only be output using the specified class), since there are many sub-class OutputStream class we used to be, the best solution is through the construction method, incoming external OutputStream object, we can imitate java achieve print stream of ideas to improve our code:

. 1  class PrintUtil the implements AutoCloseable {     // implement some common data output Mountains 
2      Private the OutputStream Output;         // regardless of the output operations, the core is the OutputStream 
. 3  
. 4      public PrintUtil (the OutputStream Output) {
 . 5          the this .OUTPUT = Output;
 . 6      }
 . 7  
. 8      public  void Print ( Long NUM) throws IOException {
 . 9          the this .print (String.valueOf (NUM));
 10      }
 . 11  
12 is      public  void print(String str) throws IOException {      //输出字符串
13         this.output.write(str.getBytes());
14     }
15 
16     public void println(long num) throws IOException {
17         this.println(String.valueOf(num));
18     }
19 
20     public void println(String str) throws IOException {
21         this.print(str + "\r\n");
22     }
23 
24     @Override
25     public void close() throws Exception {
26         output.close();
27     }
28 }
29 
30 public class Demo {
31     public static void main(String[] args) throws Exception {
32         File file = new File("d:" + File.separator + "java_test" + File.separator + "demo01.txt");
33         PrintUtil printUtil = new PrintUtil(new FileOutputStream(file));
34         printUtil.println("第一次输出: 你好");
35         printUtil.println ( "second output this: Do you like it" );
 36          printUtil.print ( ", you write code like you?" );
 37          printUtil.print (123456 );
 38          printUtil.close ();
 39      }
 40 }

- Open the file to view the output results

The first output: hello
second this output: Do you like it
, you like it write code 123456?

- During the entire operation, the nature of print design flow is to improve the function of existing class, OutputStream class is the only operator to provide standard output standard class, so it should be at the core of its fundamental, but this type of output limited operating functions, so inconvenient to output each data type, then make a layer of packing for his design ideas above code then we can call it "decorative design mode.".
- Now that we have found the original OutputStream insufficient function, java designers must also be aware of this problem, so in java, io package provides the print stream for us:
  PrintStream (JDK1.0): byte stream print

--可以发现在PrintStream的构造方法中又传递了OutputStream,这样的结构形式和代理模式是非常相似的,但是其主要的区别是:代理是围绕接口展开的,代理的时候调用的方法一定是接口中的方法而装饰设计模式中所使用的方法一定不是OutputStream中的方法,
  PrintWriter(JDK1.1):  字符打印流

--可以发现PrintWriter的构造方法中,除了可以接收OutputStream以外,还可以接收Writer等参数.
--范例:使用PrintWriter来实现数据的输出操作:

 1 public class PrintWriterDemo {
 2     public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
 3         File file = new File("d:" + File.separator + "java_test" + File.separator + "demo01.txt");
 4         PrintWriter printWriter = new PrintWriter(new FileOutputStream(file));
 5         printWriter.println("第一次输出: 你好");
 6         printWriter.println("第二此输出: 你也好");
 7         printWriter.print(",你喜欢写代码吗?");
 8         printWriter.print(123456);
 9         printWriter.close();
10     }
11 }

 

 

--PrintWriter在JDK1.5之后追加了格式化输出操作的支持:public PrintWriter printf(String format, Object ... args)

--范例:格式化输出

 1 public class PrintWriterDemo {
 2     public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
 3         File file = new File("d:" + File.separator + "java_test" + File.separator + "demo01.txt");
 4         PrintWriter printWriter = new PrintWriter(new FileOutputStream(file));
 5         String name = "张三";
 6         int age = 75;
 7         double money = 45612.5236856;
 8         printWriter.printf("姓名:%s,年龄:%d,收入:%9.2f", name, age, money);
 9         printWriter.close();
10     }
11 }

--打开文件查看输出结果 

姓名:张三,年龄:75,收入: 45612.52

--相比直接使用OutputStream类,那么使用PrintWriter,PrintStream类的处理操作会更加的简单,因此只要是程序进行内容输出的时候应全部使用打印流.

二.System类的IO的支持
  System类是一个系统类,而且是一直都在被使用的系统类,而且在这个类中定义有三个常量:
--System类中的静态常量:
  标准输出(显示器):public final static PrintStream out
  错误输出:public final static PrintStream err
  标准输入(键盘):public final static InputStream in
--范例:查看标准输出与错误输出

 1 public class OutAndErrorDemo {
 2     public static void main(String[] args) {
 3         try {
 4             Integer.valueOf("a");
 5         }catch (Exception e){
 6             System.out.println(e);
 7             System.err.println(e);
 8         }
 9     }
10 }

--运行结果

java.lang.NumberFormatException: For input string: "a"
java.lang.NumberFormatException: For input string: "a"

Process finished with exit code 0

---我们所使用的编译器可以为我们进行一些细微的差别优化(颜色),如果使用命令行去编译执行我们的java代码,那么我们将无法区别两者输出显示的差别
--System.out以及System.err是同一种类型的,最早设置两个输出的操作是有目的的:System.out是输出那些希望用户可以看见的信息,而System.err是输出那些不希望用户看见的信息.如果有需要,现在也可以修改输出的位置:
--修改out的输出位置:

 1 public class OutAndErrorDemo {
 2     public static void main(String[] args) throws FileNotFoundException {
 3         File file = new File("d:" + File.separator + "java_test" + File.separator + "demo02.txt");
 4         System.setErr(new PrintStream(
 5                 new FileOutputStream(file)));
 6         try {
 7             Integer.valueOf("a");
 8         }catch (Exception e){
 9             System.out.println(e);
10             System.err.println(e);
11         }
12     }
13 }

--在System类中还提供有一个in的常量,而这个常量对应的是标准输入设备键盘的输出处理,可以实现键盘的数据输入:

1 public class SystemInDemo {
2     public static void main(String[] args) throws IOException {
3         InputStream input = System.in;      //此时的输入流为键盘输入
4         System.out.println("请输入信息:");
5         byte[] data = new byte[1024];
6         int len = input.read(data);
7         System.out.println("输入内容为: " + new String(data,0,len));
8     }
9 }

--执行结果

请输入信息:
你好
输入内容为: 你好


Process finished with exit code 0

--这样的键盘输入处理,本身是有缺陷的,如果我们接受的数组长度不足,那么只能接受部分数据,所以输入有可能需要进行重复的输入流数据接受,而且在接收的时候,还有可能会牵扯到输入中文的情况,如果我们对中文的处理不当,则有可能造成乱码问题.

三.BufferedReader缓冲流

  BufferedReader类提供的是一个缓冲字符输入流的概念,也就是说利用BufferedReader类可以很好的解决输入流数据的读取问题,实际上java.io所提供的Buffer类还有BufferedOutputStream,BufferedInputStream,BufferedWriter等类,但是BufferedReader这个类是在最初的时候提供的最完善的数据输入的处理(JDK1.5),在之后则出了一个功能更为强大的类.之所以我们使用BufferedReader类来处理,因为该方法中有一个重要的方法:public String readLine() throws IOExpection;以换行符为分割点读取一行数据
--BufferedReader类继承结构分析:

--要先使用此类完成一个键盘输入事件的处理,我们需要知道对于键盘输入事件,java所提供的方法就是System.in(InputStream),而BufferedReader的构造器所接受的是Reader类,因此我们需要使用到转换流:InputStreamReader:

--范例:实现键盘数据输入

1 public class BufferedReaderDemo {
2     public static void main(String[] args) throws IOException {
3         BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
4         System.out.println("请输入信息:");
5         String msg = input.readLine();      //接收输入信息
6         System.out.println("输入内容为: " + msg);
7     }
8 }

--运行结果

请输入信息:
hello你好
输入内容为: hello你好

Process finished with exit code 0

--在实际的开发之中,经常会遇见输入数据的情况,而所有输入数据的类型,都是通过String描述的,那么这样就方便了接收者进行各种处理
--范例:接收整型数据并验证

 1 public class BufferedReaderDemo {
 2     public static void main(String[] args) throws IOException {
 3         BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
 4         System.out.println("请输入您的年龄:");
 5         String msg = "";      //接收输入信息
 6         while (!(msg = input.readLine()).matches("\\d+")) {
 7             System.out.println("您输入的数据有误,请重新输入: ");
 8         }
 9         System.out.println("输入的年龄为: " + msg);
10     }
11 }

--运行结果

请输入您的年龄:
sad
您输入的数据有误,请重新输入: 
ss
您输入的数据有误,请重新输入: 
56
输入的年龄为: 56

Process finished with exit code 0

--对于现代的java开发,由键盘输入数据的情况并不多,但是作为一些基础的逻辑训练,还是可以使用键盘输入数据的,而最早的键盘输入数据的实现做法就是如上的操作

四.Scanner类
  Scanner类是在java.util下在JDK1.5之后追加的程序类,其主要的目的是为了解决输入流的访问问题的,可以理解为BufferedReader的替代产品类,此类存在如下构造方法:Scanner(InputStream source)
--常用方法:
  判断是否有数据: public boolean hasNext();
  取出数据:  public String next();
  设置分隔符:public Scanner useDelimiter(String pattern)
--范例:使用Scanner实现键盘数据输入:

 1 public class ScannerDemo {
 2     public static void main(String[] args) {
 3         Scanner scanner = new Scanner(System.in);
 4         System.out.println("请输入年龄:");
 5         if(scanner.hasNextInt()){       //是否有整数输入
 6             int age = scanner.nextInt();        //直接接收数据
 7             System.out.println("您的年龄: " + age);
 8         }else {
 9             System.out.println("您输入的不对啊");
10         }
11         scanner.close();
12     }
13 }

--运行结果

请输入年龄:
55
您的年龄: 55

Process finished with exit code 0

--我们可以发现Scanner的处理会更加的简单,使用Scanner输入数据,最大的特点是直接可以结合正则使用进行自定义输入验证:

 1 public class ScannerDemo {
 2     public static void main(String[] args) throws ParseException {
 3         Scanner scanner = new Scanner(System.in);
 4         System.out.println("请输入您的生日:");
 5         if (!scanner.hasNext("\\d{4}-\\d{2}-\\d{2}")) {
 6             System.out.println("您的输入有误");
 7         }else {
 8             String birthday = scanner.next();
 9             System.out.println("您的生日为: " + new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
10         }
11         scanner.close();
12     }
13 }

--运行结果

请输入您的生日:
1888-08-05
您的生日为: Sun Aug 05 00:00:00 CST 1888

Process finished with exit code 0

--可以发现Scanner的整体设计要好于BufferReader,而且要比直接使用InputStream类要强大的,读取更加方便.例如现在要读取一个文本文件中的所有内容信息,如果采用的
是InputStream,那么必须采用内存输出流进行临时数据的保存,随后还需要判断读取的内容是否是换行,再进行输出,如果使用Scanner读取则结果如下:

 1 public class ScannerReadFileDemo {
 2     public static void main(String[] args) throws FileNotFoundException {
 3         File file = new File("d:" + File.separator + "java_test" + File.separator + "demo01.txt");
 4         Scanner scanner = new Scanner(file);
 5         scanner.useDelimiter("\n"); //设置读取分割符
 6         while (scanner.hasNext()){
 7             System.out.println(scanner.next());
 8         }
 9         scanner.close();
10     }
11 }

--运行结果

1 姓名:张三,年龄:75,收入: 45612.52
2 姓名:张三,年龄:75,收入: 45612.52
3 大叔关于不压缩大本营
4 1561441852
5 水水水水水水水水水水水水水水
6 
7 Process finished with exit code 0

--在此我们可以进行如下总结:如果程序需要输出数据一定使用打印流,输入数据使用Scanner(BufferReader)

Guess you like

Origin www.cnblogs.com/skykuqi/p/11415576.html