我的IO笔记2

ByteArrayInputStream和ByteArrayOutputStream

之前所讲解的程序中,输出和输入都是从文件中来得,当然,也可以将输出的位置设置在内存之上,此时就要使用ByteArrayInputStream、ByteArrayOutputStream来完成输入输出功能了

ByteArrayInputStream的主要功能将内容输入到内存之中

ByteArrayOutputStream的主要功能是将内存中的数据输出

此时应该把内存作为操作点


ByteArrayInputStream类的定义:

public class ByteArrayInputStream extends InputStream

构造方法:

public ByteArrayInputStream(byte[] buf)

接受一个byte数组,实际上内存的输入就是在构造方法上将数据传入到内存中。

ByteArrayOutputStream:输出就是从内存中写出数据

public void write(int b)

 

以下是以内存操作流完成的一个大小写字母转换的程序:

复制代码
 1 import java.io.ByteArrayInputStream;  2 import java.io.ByteArrayOutputStream;  3 import java.io.IOException;  4 import java.io.InputStream;  5 import java.io.OutputStream;  6  7 public class Test22 {  8 public static void main(String[] args) throws IOException {  9 String str="HELLO WORlD!!!"; 10 InputStream input=new ByteArrayInputStream(str.getBytes()); 11 OutputStream output=new ByteArrayOutputStream(); 12 int temp=0; 13 while((temp=input.read())!=-1){ 14 output.write(Character.toLowerCase(temp)); 15 } 16 input.close(); 17 output.close(); 18 System.out.println(output.toString()); 19 } 20 }

复制代码

管道流(线程通信流)

管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutputStream)、管道输入流(PipedInputStream),如果想要进行管道输出,则必须要把输出流连在输入流之上,在PipedOutputStream类上有如下的一个方法用于连接管道:

public void connect(PipedInputStream snk)throws IOException

例子:线程之间用管道流进行通讯

复制代码
 1 import java.io.IOException;  2 import java.io.PipedInputStream;  3 import java.io.PipedOutputStream;  4  5 class Send implements Runnable{  6  7 private PipedOutputStream pos;//管道输出流  8 public Send(){  9 pos=new PipedOutputStream(); 10 } 11 @Override 12 public void run() { 13 String str="Hello World!"; 14 try { 15 pos.write(str.getBytes()); 16 } catch (IOException e) { 17 e.printStackTrace(); 18 } 19 try { 20 pos.close(); 21 } catch (IOException e) { 22 e.printStackTrace(); 23 } 24 } 25 public PipedOutputStream getPos() { 26 return pos; 27 } 28 } 29 30 class Receive implements Runnable{ 31 32 private PipedInputStream pis;//管道输入流 33 public Receive(){ 34 pis=new PipedInputStream(); 35 } 36 @Override 37 public void run() { 38 byte[] b=new byte[1024]; 39 int len=0; 40 try { 41 len=pis.read(b); 42 } catch (IOException e) { 43 e.printStackTrace(); 44 } 45 try { 46 pis.close(); 47 } catch (IOException e) { 48 e.printStackTrace(); 49 } 50 System.out.println(new String(b,0,len)); 51 } 52 public PipedInputStream getPis() { 53 return pis; 54 } 55 } 56 57 public class Test23 { 58 public static void main(String[] args) { 59 Send send=new Send(); 60 Receive receive=new Receive(); 61 try { 62 send.getPos().connect(receive.getPis());//连接管道 63 } catch (IOException e) { 64 e.printStackTrace(); 65 } 66 new Thread(send).start();//启动线程 67 new Thread(receive).start();//启动线程 68 } 69 }
复制代码

在整个IO包中,打印流是输出信息最方便的类,主要包含字节打印流(PrintStream)和字符打印流(PrintWrite)。打印流提供了非常方便的打印功能,可以打印任何的数据类型,例如:小数、整数、字符串等等。

 

看一下PrintStream的构造方法:

public PrintStream(OutputStream out)

在PrintStream中定义的构造方法中可以清楚的发现有一个构造方法可以直接接收OutputStream类的实例,这是因为与OutputStream相比起来,PrintStream可以更加方便的输出数据,这就好比将OutputStream类重新包装了一下,使之输出更加方便。

使用PrintStream输出信息:

复制代码
 1 import java.io.File;  2 import java.io.FileOutputStream;  3 import java.io.IOException;  4 import java.io.PrintStream;  5  6 public class Test24 {  7 public static void main(String[] args) throws IOException {  8 File f = new File("d:" + File.separator+"test.txt");  9 PrintStream output=new PrintStream(new FileOutputStream(f)); 10 output.println("Hello World!"); 11 output.print("1+1="+2); 12 output.close(); 13 } 14 }
复制代码

也就是说此时,实际上是将FileOutputStream类的功能包装了一下,这样的设计在java中称为装饰设计

但如果仅仅是上面的那些功能也未免太寒碜了吧,好吧,看绝招,大家学过C吧~:

复制代码
 1 import java.io.File;  2 import java.io.FileOutputStream;  3 import java.io.IOException;  4 import java.io.PrintStream;  5  6 public class Test25 {  7 public static void main(String[] args) throws IOException {  8 File f = new File("d:" + File.separator+"test.txt");  9 PrintStream output=new PrintStream(new FileOutputStream(f)); 10 String name="Jim"; 11 int age=20; 12 float score=90.5f; 13 char sex='M'; 14 output.printf("姓名:%s 年龄:%d 成绩:%f 性别:%c", name,age,score,sex); 15 output.close(); 16 } 17 }
复制代码

哈哈,竟然有printf!~而且你要是觉得%s %d %f %c太麻烦,可以全用%s代替,比C的printf还好用

System类的常量

System表示系统类,此类也对IO给予了一定的支持。

  • public static final PrintStream out  对应系统标准输出,一般是显示器
  • public static final PrintStream err   错误信息输出
  • public static final InputStream in   对应着标准输入,一般是键盘
又是由于历史遗留问题 全局变量没有大写~

System.out

使用System.out输出的时候就是将输出的位置定义在了显示器之中。

FileOutputStream是定位在文件里,而System.out是定位在屏幕上。

使用OutputStream完成屏幕上输出(PrintStream是OutputStream的子类

 1 import java.io.IOException;  2 import java.io.OutputStream;  3  4 public class Test26 {  5 public static void main(String[] args) throws IOException {  6 OutputStream out=System.out;  7 out.write("Hello World!".getBytes());  8 out.close();  9 } 10 }
这其实就是多态的一种表现

 

System.err

System.err表示的错误的标准输出,如果程序中出现了错误的话,则直接使用System.err进行打印输出即可。

复制代码
 1 public class Test27 {  2 public static void main(String[] args) {  3 String str="Hello World";  4 try{  5 int a=Integer.parseInt(str);  6 }catch(Exception e){  7 System.err.println(e);  8 }  9 } 10 }
复制代码

但是有些人会问这跟System.out输出的结果完全一样的嘛,有什么区别啊?

 

System.out与System.err的区别

  • System.out和System.err都是PrintStream的实例化对象,而且通过实例代码可以发现,两者都可以输出错误信息,但是一般来讲System.out是将信息显示给用户看,是正常的信息显示,而System.err的信息正好相反是不希望用户看到,会直接在后台打印,是专门显示错误的
  • 一般来讲,如果要想输出错误信息的时候最好不要使用System.out而是直接使用System.err,这一点只能从其概念上划分。

System.in

System.in实际上是一个键盘的输入流,其本身是InputStream类型的对象。那么,此时就可以利用此方式完成从键盘读取数据的功能。

InputStream对应的是输入流,输入流的话肯定可以从指定位置上读取,之前使用的是FileInputStream是从文件中读取的

复制代码
 1 import java.io.IOException;  2 import java.io.InputStream;  3  4 public class Test28 {  5 public static void main(String[] args) throws IOException {  6 InputStream in=System.in;  7 byte[] b=new byte[1024];  8 int len=in.read(b);  9 System.out.println(new String(b,0,len)); 10 } 11 }
复制代码

如果不使用byte数组指定长度呢:

复制代码
 1 import java.io.IOException;  2 import java.io.InputStream;  3  4 public class Test29 {  5 public static void main(String[] args) throws IOException {  6 InputStream in=System.in;  7 StringBuilder buf=new StringBuilder();  8 int temp=0;  9 while((temp=in.read())!=-1){ 10 char c=(char) temp; 11 if(c=='\n')break; 12 buf.append(c); 13 } 14 in.close(); 15 System.out.println(buf.toString()); 16 } 17 }
复制代码

但以上代码还是有很大问题的,输入中文的话~,所以最好的方法还是一次性把数据都放在内存了,再一次性全部拿出来,要实现这个功能的话,要用到BufferedReader类,下回介绍~

 

输入输出重定向

System.out、System.err、System.in都有重定向功能,分别是setOut、setErr、setIn方法

System.out重定向

复制代码
 1 import java.io.File;  2 import java.io.FileNotFoundException;  3 import java.io.PrintStream;  4  5 public class Test30 {  6 public static void main(String[] args) throws FileNotFoundException {  7 File f = new File("d:" + File.separator+"test.txt");  8 System.setOut(new PrintStream(f));  9 String str="This is a test!"; 10 System.out.println(str); 11 } 12 }
复制代码

System.err重定向

复制代码
 1 import java.io.ByteArrayOutputStream;  2 import java.io.PrintStream;  3  4 public class Test31 {  5 public static void main(String[] args) {  6 ByteArrayOutputStream out=new ByteArrayOutputStream();  7 System.setErr(new PrintStream(out));  8 System.err.println("Test---------------");  9 System.out.println(out.toString()); 10 } 11 }
复制代码

一般不建议修改err的重定向,因为这些信息都不太希望用户看到

System.in重定向

复制代码
 1 import java.io.File;  2 import java.io.FileInputStream;  3 import java.io.IOException;  4 import java.io.InputStream;  5  6 public class Test32 {  7 public static void main(String[] args) throws IOException {  8 File f = new File("d:" + File.separator+"test.txt");  9 System.setIn(new FileInputStream(f)); 10 InputStream in=System.in; 11 byte[] b=new byte[1024]; 12 int len=in.read(b); 13 in.close(); 14 System.out.println(new String(b,0,len)); 15 } 16 }
复制代码


一般,使用最多的还是System.out的重定向~

如果想要接收任意长度的数据,而且避免乱码产生,就可以使用BufferedReader

public class BufferedReader extends Reader

因为输入的数据有可能出现中文,所以,此处使用字符流完成。BufferedReader是从缓冲区之中读取内容,所有的输入的字节数据都将放在缓冲区之中。

System.in本身表示的是InputStream(字节流),现在要求接收的是一个字符流,需要将字节流变成字符流才可以,所以要用InputStreamReader

复制代码
 1 import java.io.BufferedReader;  2 import java.io.IOException;  3 import java.io.InputStreamReader;  4  5 public class Test33 {  6 public static void main(String[] args) throws IOException {  7 BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));  8 String str=reader.readLine();  9 System.out.println(str); 10 } 11 }
复制代码



在JDK1.5之后Java提供了专门的输入数据类,此类可以完成BufferedReader类的功能,也可以方便的对输入数据进行验证,此类存放在java.util包中

使用Scanner接收键盘的输入数据:

复制代码
1 import java.util.Scanner; 2 3 public class Test34 { 4 public static void main(String[] args) { 5 Scanner s=new Scanner(System.in); 6 String str=s.next(); 7 System.out.println(str); 8 } 9 }
复制代码

比直接使用BufferedReader更加方便,但是这个程序是有问题的,如果输入的字符串中存在空格,那么就会截止,如果我们要接收空格的下,将分隔符变成“\n”。

复制代码
 1 import java.util.Scanner;  2  3 public class Test34 {  4 public static void main(String[] args) {  5 Scanner s=new Scanner(System.in);  6 s.useDelimiter("\n");//使用分隔符  7 String str=s.next();  8 System.out.println(str);  9 } 10 }
复制代码

转载于:https://my.oschina.net/liting/blog/424430

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值