System.out:对应的是标准输出设备:控制台。
System.in :对应的是标准输入设备:键盘。
所以in类型实际上是字节读取流对象。
1、简要的试验代码如下:
import java.io.*;
public class InDemo
{
public static void main(String[] args) throws IOException
{
InputStream fr=System.in;
String s=null;
System.out.println("\r\n");
//方式一:一次读至所预先开辟好的内存字节数组中来
//缺点:1、若行数的字节数超过预先开辟的个数,则有遗漏
// 2、每次都要新建一个新的字符串对象,浪费内存
/*
int ch=0;
byte[] b=new byte[1024];
while((ch=fr.read(b))!=-1)
{
s=new String(b,0,ch);
if("over\r\n".equals(s))
{
System.out.println("跳出循环");
break;
}
else
System.out.print(s);
}
*/
//方式二:一次读取一个,然后加入到StringBuilder的容器中
StringBuilder b=new StringBuilder();
int ch=0;
while((ch=fr.read())!=-1)
{
if(ch=='\r')
continue;
if(ch=='\n')
{
if("over".equals(b.toString()))
break;
System.out.println(b.toString().toUpperCase());
b.delete(0, b.length());
}
else
b.append(ch);
}
fr.close();
}
}
方式一与方式二的区别实际上就两点:1、read()方法使用不同,2、容器与数组的区别。
注意:read()与readLine()方法均为阻塞式方法:即 在字符可用、发生 I/O 错误或者已到达流的末尾前,此方法一直阻塞。
在上述代码里,我一开始一直有个疑问,我从键盘敲上字母后,为什么直到我按回车,程序才能运行?现在我觉得是这样的,我敲上字母后,应该是直到我按回车,那敲上的字母才能进入读流对象中,否则读流对象中根本没内容,即没有字符可用,由于read()方法是阻塞式方法,自然不能够通过read()方法读出字符;另外read()方法如果读到末尾处会返回-1,但是从键盘处无法直接敲进-1,而“ctrl”+“c”实际上敲进去的就是-1,因此认为是末尾,可以退出循环!
2、转换流:
2.1、读转换流
将上述代码用字符流缓冲区中BufferedReader中的readLine()方法每次读出一行:
InputStreamReader isr=new InputStreamReader(fr);
BufferedReader bufr=new BufferedReader(isr);
String s=null;
while((s=bufr.readLine())!=null)
{
if("over".equals(s))
break;
else
System.out.println(s);
}
2.2、写转换流
将上述输出到控制台的代码做一下改变:
InputStreamReader isr=new InputStreamReader(fr);
BufferedReader bufr=new BufferedReader(isr);
OutputStream out=System.out; //创建输出流字节对象
OutputStreamWriter fw=new OutputStreamWriter(out);//创建字符-字节转换流对象
BufferedWriter bufw=new BufferedWriter(fw); //创建字符流对象缓冲区
String s=null;
while((s=bufr.readLine())!=null)
{
if("over".equals(s))
<span style="white-space:pre"> </span>break;
else
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>bufw.write(s);
<span style="white-space:pre"> </span>bufw.newLine(); //缓冲区的换行方法
bufw.flush(); //刷新缓冲区
}
}
2.3 指定编码表时
在流字符流对象中,默认编码表为"GBK",如果要指定编码表时,如"UTF-8",那么FileReader与FileWriter相对应的就不能使用,而其父类InputStreamReader与OutputStreamWriter转换流具备指定编码表的功能,但是作为转换流,前者是字节转字符,后者是字符转字节,均需传入字节流对象:如果是硬盘文件,应相应传入FileInputStreamReader与FileOutputStreamWriter
3、流操作规律3.1、明确源和目的
源: 输入流:InputStream Reader
目的:输出流:OutputStream Writer
3.2、操作的数据是否为纯文本
是: 字符流
不是:字节流
3.3、当体系明确后,再明确要使用哪个具体的对象:通过设备来划分
源设备: 内存、硬盘、键盘
目的设备:内存、硬盘、控制台
3.4、需不需要指定编码表
需要:InputStreamReader OutputStreamWriter
练习;将键盘里输入保存为一个文件
import java.io.*;
public class ioRule_Test1
{//将键盘里输入保存为一个文件
/*源:InputStream Reader
*纯文本:是
*设备:键盘,用System.in
*因此:需要转换流InputStreamReader,
*InputStreamReader isr=new InputStreamReader(System.in);
*需要提高效率:BufferedReader,
*BufferedReader bufr=new BufferedReader(isr)
*
*
*目的:OutputStream Writer
*纯文本:是
*设备:硬盘,用FileWriter
*不需要转换流
*FileWriter fw=new FileWriter("目的文件路径");
*需要提高效率:BufferedWriter
*BufferedWriter bufw=new BufferedWriter(fw);
*/
public static void main(String[] args)
{
BufferedReader bufr=null;
BufferedWriter bufw=null;
try
{
bufr=new BufferedReader(new InputStreamReader(System.in));
//bufw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\Users\\LJ_Z\\Desktop\\test1.txt")));
bufw=new BufferedWriter(new FileWriter("C:\\Users\\LJ_Z\\Desktop\\test1.txt"));
String s=null;
while((s=bufr.readLine())!=null)
{
if("over".equals(s))
break;
else
{
bufw.write(s);
bufw.newLine();
bufw.flush();
}
}
}
catch(IOException e)
{
throw new RuntimeException();
}
finally
{
try
{
if(bufr!=null)
bufr.close();
}
catch(IOException e)
{
System.out.println("关输入流失败");
}
try
{
if(bufw!=null)
bufw.close();
}
catch(IOException e)
{
System.out.println("关写入流失败");
}
}
}
}