------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1.IO流用来处理设备之间的数据传输
2.Java对数据的操作是通过流的方式
3.Java用于操作流的对象都在IO包中
4.流按操作数据分为两种:字节流与字符流
5.流按流向分为:输入流,输出流。
1.字节流的抽象基类:
InputStream ,OutputStream。
2.字符流的抽象基类:
Reader ,Writer。
注:由这四个类派生出来的子类名称都是 以其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream。
如:Reader的子类FileReader。
1、建立一个流对象,将已存在的一个文件加载进流。如果文件不存在,或者它是一个目录,而不是一个常规文件,或者无法打开进行读取。会抛出FileNotFound异常。
FileReader fr = new FileReader(f);
2.读取数据。
1)读取单个字符。
int ch=0;
ch=fr.read();
read()方法返回的是作为整数读取的字符,每调用一次read()方法就读取一个字符,如果达到流的末尾就返回-1。
2)将字符读入数组。
创建一个临时存放数据的数组。
char[] buf = new char[1024];
int num=0;
调用流对象的读取方法将流中的数据读入到数组中
num=fr.read(buf);
此read方法返回实际读入到字符数组的字符个数,如果达到流的末尾就返回-1。
构建字符串,就可以打印出数据了。
System.out.println(new String(buf,0,num));
3.加入缓冲技术,提高读取效率。
BufferedReader bufr=new BufferedReader(fr);
String line=null;
while((line=bufr.readLine())!=null)
{
System.out.println(line);
}
readLine()是缓冲流对象bufr的特有方法,返回读取的一行字符(不包括换行符),如果达到流的末尾就返回null。
关闭缓冲,其实关闭缓冲区,就是关闭缓冲区中的流对象。就可以不用写fr.close();
bufr.close();
3.关闭资源。
fr.close();
注意:
1.read方法配合while循环可以读取完文件所有的数据。
2.readLine方法原理:无论是读一行。或者读取多个字符。其实最终都是在在硬盘上一个一个读取。所以最终使用的还是read方法一次读一个的方法。相对于read()方法, 降低了一个一个字符的读取时出错的概率。
3.无论是read()、read(buf)、readLine()如果发生 I/O 错误,抛出IOException,关闭缓冲流对象bufr.close() bufw.close() 发生错误会抛出IOException。所以要对发生错误就会抛出异常的代码进行try{}catch{}处理。
1.创建流对象,建立数据存放文件
FileWriter fw = new FileWriter("Test.txt");
如果存储位置有Test.txt文件,则创建一个空文本的Test.txt覆盖原文件。
如果不想覆盖原文件,想进行续写则加上true属性。
FileWriter fw=new FileWriter("Test.txt",true);
2.写入数据。
方式一:调用流对象的写入方法,将数据写入流
fw.write("text");
方式二:加入缓冲区,提高写入效率。
将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
BufferedWriter bufw=new BufferedWriter(fw);
bufw.write("我是数据");
根据需求是否写入跨平台的换行符
bufw.newLine();
只要用到缓冲区,就要记得刷新。(关闭流同样会刷新,但为了排除意外事故,保证数据存在,建议写入一次就刷新一次)
bufw.flush();
其实关闭缓冲区,就是在关闭缓冲区中的流对象。就可以不用写fw.close();
bufw.close();
3.关闭流资源,并将流中的数据清空到文件中。就是先flush再关闭资源,不然文件里面没有数据
fw.close();
注意:定义文件路径时,可以用“/”或者“\\”。反之视为相对路径(如“Test.txt”)。
1.缓冲区的出现提高了对数据的读写效率。需要先将需要缓冲的流对象初始化到构造函数中。
2.对应类:
BufferedWriter
BufferedReader
3.缓冲区要结合流才可以使用。
4.在流的基础上对流的功能进行了增强
5、BufferedWriter、BufferedReader内部封装了一个字符数组,默认大小8kb。
示例一:拷贝文本文件
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class TextFileCopy
{
public static void main(String[] args) throws IOException
{
//1.一个一个字符的拷贝
textcopy_1();
//2.每次拷贝指定大小的字符数组
textcopy_2();
}
public static void textcopy_1() throws IOException
{
//1.创建读取文件流对象,关联文件。
FileWriter fw=new FileWriter("c:/zzz.java");
//2.建立文件写入流对象,关联文件。
FileReader fr=new FileReader("C:\\copy_1.java");
//3.读取文件数据。
int ch=0;
while((ch=fr.read())!=-1)
{
fw.write(ch);
}
//4.关闭资源。close方法会先flush在释放Windows资源。
fw.close();
fr.close();
}
public static void textcopy_2()
{
//1.建立文件读取、写入流对象的引用。
FileWriter fw=null;
FileReader fr=null;
//处理将会抛出异常的代码。
try
{
//2.文件实例化
fw=new FileWriter("c:/zzz.java");
fr=new FileReader("C:\\copy_2.java");
//3.读取文件数据,写入到目的地。
char[] buf=new char[1024];
int len=0;
while((len=fr.read(buf))!=-1)
{
fw.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
//4.关闭资源。
if(fr!=null)
{
try
{
fr.close();
}
catch (IOException e)
{
throw new RuntimeException("读取文件流关闭失败");
}
}
if(fw!=null)
{
try
{
fw.close();
}
catch (IOException e)
{
throw new RuntimeException("写入文件流关闭失败");
}
}
}
}
}
示例二:带缓冲区复制文本文件
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Day19_03缓冲区复制文件 {
public static void main(String[] args)
{
//1.建立文件读取、写入流对象的引用,避免变量不能跨代码块使用。
BufferedWriter bufw=null;
BufferedReader bufr=null;
try
{
//2.实例化流对象,关联文件。
bufr= new BufferedReader(new FileReader("C:\\java.txt"));
bufw= new BufferedWriter(new FileWriter("C:\\javacopy.txt"));
//3.读取文本数据。一次读取一行数据。
//readLine方法的原理:无论是读一行,获取读取多个字符。其实最终都是在硬盘上一个一个读取。
//所以最终使用的还是read方法一次读一个的方法。
String line=null;
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();//写入换行符(跨平台)
bufw.flush();//将缓冲区的数据刷新至输出流对象中,将数据写入到文件
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
//4.关闭资源。
try
{
if(bufr!=null)
{
bufr.close();
}
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(bufw!=null)
{
bufw.close();
}
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
}
}
}
一、定义:当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。
二、特点:
1、装饰类通常会通过构造方法接收被装饰的对象。
2、并基于被装饰类的对象的功能,提供更强的功能。
三、装饰和继承的区别:
1、装饰模式比继承要灵活。避免了继承体系的臃肿,且降低了类与类之间的关系。
2、装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类都必须所属同一个接口或者父类。
3、从继承结构转为组合结构。
注:1、在定义类的时候,不要以继承为主;可通过装饰设计模式进行增强类功能。灵活性较强,当装饰类中的功能不适合,可再使用被装饰类的功能。
2、BufferedWriter、BufferedReader也是装饰类。
示例三:MyBufferedReader的例子就是最好的装饰设计模式的例子。
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
class MyBufferedReader extends Reader//Reader里面有抽象方法必须覆盖
{
//1.将FileReader对象传入,基于已有的功能,并提供加强功能。
private FileReader r;
MyBufferedReader(FileReader r)
{
this.r=r;
}
//2.一次读一行数据。
public String myReadLine() throws IOException
{
//定义一个临时容器。原BufferReader封装的是字符数组。
//3.为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
StringBuilder sb = new StringBuilder();
int num=0;
while((num=r.read())!=-1)
{
//识别换行符。Windows换行 \r\n
if (num=='\r')
{
continue;
}
else if(num=='\n')
{
return sb.toString();
}
else
sb.append((char)num);
}
if(sb.length() != 0)
return sb.toString();
return null;
}
public void myClose() throws IOException
{
r.close();
}
//4.覆盖Reader类中的抽象方法。
public void close() throws IOException
{
r.close();
}
public int read(char[] cbuf, int off, int len) throws IOException
{
return r.read(cbuf, off, len);
}
}
public class Day19_05MybufferedReader
{
public static void main(String[] args) throws IOException
{
//1.建立读取流对象,关联文件。
FileReader fr=new FileReader("buf.txt");
//2.加入自定义的缓冲包装读取流对象。
MyBufferedReader myBuf=new MyBufferedReader(fr);
//3.读取数据并,打印在控制台上。
String line=null;
while((line=myBuf.myReadLine()) !=null)
{
System.out.println(line);
}
//4.关闭资源。
myBuf.myClose();
}
}
LineNumberReader:
1、跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
public class Day19_09LineNumberReader
{
public static void main(String[] args) throws IOException
{
//1.建立读取文件流对象。
FileReader fr=new FileReader("copy.txt");
LineNumberReader lnr=new LineNumberReader(fr);
String line=null;
//lnr.setLineNumber(100);//起始值从100开始
while((line=lnr.readLine())!= null)
{
System.out.println(lnr.getLineNumber()+":"+line);
}
lnr.close();
}
}
1.基本操作与字符流类相同,但它不仅可以操作字符文件,还可以操作其他媒体文件。
2.由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流flush动作。
1、建立一个流对象,将已存在的一个文件加载进流。
FileInputStream fis = new FileInputStream("山水间.mp3");
2、建立流对象,关联数据存放文件。
FileOutputStream fos = new FileOutputStream("c:\\山水间copy.mp3");
加上true属性续写文件。
FileOutputStream fos = new FileOutputStream("c:\\山水间copy.mp3",true);
注意:1、2步会抛出异常:
FileNotFound - 如果文件不存在,或者它是一个目录,而不是一个常规文件,或者无法打开进行读取。
SecurityException - 如果存在安全管理器,且其 checkRead 方法拒绝对文件进行读取访问。
3、读取数据、写入数据。
1)方式一:读、写单个字节
读取: int num = fis.read();
写入: fos.write(num);
2)方式二:读取、写入规定大小的字节数组
读取: byte[] buf=new byte[1024];
int len=0;
len=fis.read(buf);//返回的是实际读取的字节数量
写入:fos.write(buf,0,len);
3)方式三:读取、写入文件大小的字节数组。
byte[] buf=new byte[fis.available()];//定义一个刚刚好的缓冲区,不用在循环了
读取: fis.read(buf);
写入: fos.write(buf);
注意:可以利用此方法来指定读取方式中传入数组的长度,从而省去循环判断。但是如果文件较大,而虚拟机启动分配的默认内存一般为64M。当文件过大时,此数组长度所占内存空间就会溢出。所以,此方法慎用,当文件不大时,可以使用。
4)方式四:加入缓冲区提高读取数据的效率。
缓冲读取流:BufferedInputStream bufis=new BufferedInputStream(fis);
缓冲输出流:BufferedOutputStream bufos=new BufferedOutputStream(fos);
byte[] buf=new byte[1024];
int len=0;
len=bufis.read(buf);
fos.write(buf,0,len);
bufis.close();
bufos.close();
注意关闭了缓冲流对象,也就关闭了fis.close(); fos.close();
4、关闭资源
fis.close();
fos.close();
注意:字节流的Read()、write()方法
对于读取字节文件,当读取的字节是11111111是即-1,此时read方法会默认数据读取至流末,就结束了读取导致文件残缺,为了避免这种情况发生:
1)read()方法返回的是4字节的int类型,API规定了这个方法会把读取的字节的高字节位置补零3个字节,因此如果读到数据,返回值必然在0到255之间,如果未读到返回-1;
2)write(int)的参数是4个字节的int类型,实现类在写入时会强转为1个字节的byte类型,这个强转会发生去掉溢出的3个字节,比如write(256),实际写入的是0x00,也就等效于write(0);
示例五:复制图片
/*
复制一个图片
思路:
1.用字节读取流对象和图片关联。
2.用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3.通过循环读写,
图片读一段会查表,字符流别拷贝媒体文件。
* */
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class PicCopy
{
public static void main(String[] args)
{
//1.建立字节流对象引用。
FileOutputStream fos=null;
FileInputStream fis=null;
//处理会抛异常的代码
try
{
//2.流对象实例化。
fos=new FileOutputStream("c:\\copy.png");
fis=new FileInputStream("c:\\1.png");
//3.读取字节数组数据
byte [] buf=new byte[1024];
int len=0;
while((len=fis.read(buf))!=-1)
{
//4.写入字节数组数据。
fos.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("复制文件失败");
}
finally
{
//5.关闭资源。
try
{
if(fis!=null)
fis.close();
}
catch (IOException e1)
{
throw new RuntimeException("写入文件失败");
}
try
{
if(fos!=null)
fos.close();
}
catch (IOException e2)
{
throw new RuntimeException("读取文件失败");
}
}
}
}
1、基本操作与字符流类相同
但它不仅可以操作字符,还可以操作其他 媒体文件
示例六:字节流缓冲区复制mp3
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Mp3Copy
{
public static void main(String[] args) throws IOException
{
//计算复制文件的时间
long start=System.currentTimeMillis();
piccopy();
long end=System.currentTimeMillis();
System.out.println((end-start)+"毫秒");
}
public static void piccopy() throws IOException
{
//1.建立文件读取、写入流对象,关联文件。
BufferedInputStream bufis=new BufferedInputStream(new FileInputStream("D:\\时间煮雨.mp3"));
BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("D:\\时间煮雨copy.mp3"));
int by=0;
byte [] buf=new byte[1024];
//2.读取数据
while((by=bufis.read(buf)) !=-1)
{
//3.写入数据。
bufos.write(buf,0,by);
}
//4.关闭资源。
bufos.close();
bufis.close();
}
}
示例七:自定义缓冲区复制MP3
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
class MyBufferedInputStream
{
private InputStream in;
private byte[] buf=new byte[1024];
private int pos=0,count=0;
MyBufferedInputStream(InputStream in)
{
this.in=in;
}
public int myRead() throws IOException
{
//byte型&0xff向上转成int型
if(count==0)
{
count=in.read(buf);
if(count<0)
return -1;
pos=0;
byte b= buf[pos];
count--;
pos++;
return b&0xff;
}
else if(count>0)
{
byte b=buf[pos];
count--;
pos++;
return b&255;
}
return -1;
}
public void myClose() throws IOException
{
in.close();
}
}
public class MyBuffer
{
public static void main(String[] args) throws IOException
{
//计算复制时间。
long start=System.currentTimeMillis();
mp3_copy();
long end=System.currentTimeMillis();
System.out.println((end-start)+"毫秒");
}
public static void mp3_copy() throws IOException
{
//1.建立文件读取、写入流对象。
MyBufferedInputStream bufis=new MyBufferedInputStream(new FileInputStream("D:\\小时代 - 时间煮雨.mp3"));
BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("D:\\小时代 - 时间煮雨copy.mp3"));
//2.读取数据
int by=0;
while((by=bufis.myRead()) !=-1)//read在提升
{
//3.写入数据。
bufos.write(by);//write在强转 保证原数据不变 避免-1的发生。
}
//4.关闭资源。
bufos.close();
bufis.myClose();
}
}
一、核心功能实现类:所谓的核心功能实现类,也就是实现了最基础的写入功能——实现了原子操作write(int)和read()。ByteArrayOutputStream实现内存字节流的写入。
ByteArrayInputStream实现内存字节流的读取。
1、内存读写已经保证了多线程安全,但是文件读写没有保证;
2、内存读写不需要调用close方法;而文件读写使用文件系统,必须调用close方法释放文件资源;
3、字节流核心写入类都不带缓存功能,因此直接使用时无需调用flush方法;
4、FileOutputStream对象在创建时,就会执行一个native的open操作,如果是覆盖模式,此操作会立刻清除原文件内容,因此创建覆盖模式的FileOutputStream对象要非常谨慎,就算我们没做任何写入操作,文件内容也会被覆盖。
5、ByteArrayInputStream支持标记和重置功能,FileInputStream不支持;
6、ByteArrayInputStream的mark(int)方法中,参数无意义,随便传。
FilterOutputStream在close方法中默认调用flush方法,这样在使用字节流写入的装饰子类时,无需在关闭前调用flush方法了。
五、注意事项:
1、缓存读写的装饰类都额外保证了读写操作的多线程安全性;
2、缓存读写的缓存大小默认都是8KB,可以通过构造方法指定,但读取操作的缓存是可变的,使用中大小可能发生变化;
3、缓存读取还附带实现了标记和重置功能,不同于ByteArrayInputStream的标记重置功能,BufferedInputStream读取提供的mark(int)的参数有意义,指定了标记在多少个字节内是起效的。
1、“标准”输入流
static InputStream in
2、“标准”输出流
static PrintStream out
PrintStream的父类是FilterOutputStream。
3、通过System类的setIn,setOut方法可以对默认设备进行改变
将标准输入改成文件。
System.setIn(newFileInputStream(“Demo.java”));
将目的改成文件
System.setOut(newFileOutputStream(“info.txt”));
示例八:流改变标准输入输出设备
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
public class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
//System.setIn(new FileInputStream("Demo.java"));
//1.将标准输出流目的地改为文件。
System.setOut(new PrintStream("zzz.txt"));
//2.建立带缓冲功能的键盘输入流、输出流、文件输出流对象。
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
BufferedWriter bufile=new
BufferedWriter(new OutputStreamWriter(new FileOutputStream("UTF.txt"),"UTF-8"));
//3.读取键盘数据。
String line=null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
//4.将数据写入到zzz.txt
bufw.write(line.toUpperCase());
//5.将数据按照UTF-8编码表,写入到UTF.txt中
bufile.write(line);
//刷流。
bufile.newLine();
bufile.flush();
bufw.newLine();
bufw.flush();
}
//6.关闭资源。
bufr.close();
bufw.close();
}
}
二、转换流InputStreamReader,OutputStreamWriter
一、转换流的由来
InputStreamReader 是字节流通向字符流的桥梁。
OutputStreamWriter 是字符流通向字节流的桥梁。
方便了字符流与字节流之间的操作
二、转换流的应用
字节流中的数据都是字符时,转成字符流操作更高效。
例如:InputStreamReader将字节流通向字符流
1)、获取键盘录入对象。
InputStream in = System.in;
2)、将字节流对象转成字符流对象,使用转换流。
InputStreamReader isr = new InputStreamReader(in);
3)、为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReade这样就可以调用readLine方法。
BufferedReader bufr = new BufferedReader(isr);
三、键盘录入最常见写法
BufferedReader bufi = new BufferedReader(new InputStreamReader(System.in));
打印到控制台的常见写法
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
示例九:键盘录入数据将其小写字母变成大写字母打印到控制台上
/*读取键盘录入
System.out:对应的是标准输出设备,控制台
System.in:对应的是标准输入设备:键盘
需求:通过键盘录入数据。
当录入一行数据后,就将该行数据进行打印。
如果录入的数据是over,那么就停止录入。
通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。
也就是readLine方法。
能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?
readLine方法时字符流BufferedReader类中的方法。
而键盘录入的read方法是字节流InputStream的方法。
那么能不能将字节流转成字符流在使用字符流缓冲区的readLine方法呢?
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Day19_15IO读取键盘录入
{
public static void main(String[] args) throws IOException
{
// //1.获取键盘录入对象
// InputStream in=System.in;
// //将字节流对象转成字符流对象,使用转换流。InputStreamReader
// InputStreamReader isr=new InputStreamReader(in);
// //为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
// BufferedReader bufr=new BufferedReader(isr);
//3句合并 键盘录入最常见写法。
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
// OutputStream out=System.out;
// OutputStreamWriter osw=new OutputStreamWriter(out);
// BufferedWriter bufw=new BufferedWriter(osw);
//建立控制台流对象。加入缓冲。
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
//2.每次读取一行字符串。
String line=null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
//3.打印数据到控制台上
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
//4.关闭资源。
bufr.close();
/* 第二种方式
StringBuilder sb=new StringBuilder();
while(true)
{
int ch=in.read();
if(ch=='\r')
continue;
if(ch=='\n')
{
String s=sb.toString();
if("over".equals(s))
break;
System.out.println(s.toUpperCase());
sb.delete(0,sb.length());
}
else
sb.append((char)ch);
}
*/
}
}
流操作的基本规律,通过三个步骤来完成。
1.明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer
2.操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3.当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存、硬盘、键盘
目的设备:内存、硬盘、控制台。
示例分析:
1.将一个文本文件中数据存储到另一个文件中。复制文件。
1)源:因为是源,所以使用读取流。InputStream Reader
是不是操作文本文件。
是!这时就可以选择Reader
这样体系就明确了。
2)接下来明确使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象时FileReader
FileReader fr=new FileReader("a.txt");
BufferedReader bufr=new BufferedReader(fr);
是否需要提高效率:是! 加入Reader体系中的缓冲区BufferedReader
目的:OutputStream Writer
是否是纯文本。
是!Writer
设备:硬盘,一个文件
Writer体系中可以操作文件的对象FileWriter。
是否需要提高效率:是! 加入Writer体系中的缓冲区BufferedWriter
FileWriter fw=new FileWriter("a.txt");
BufferedWriter bufw=new BufferedWriter(fr);
2.需求:将键盘录入的数据保存到一个文件中。
1)这个需求中有源和目的存在。
那么分别分析
源:InputStream Reader
是不是纯文本?是!Reader
2)设备:键盘。对应额是System.in.
不是选择Reader吗?System.in对应的不是字节流吗?
为了操作键盘的文本数据方便。转成字符流按照字符串操作时最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。
用了Reader体系中转换流,InputStreamReader
InputStreamReader isr=new InputStreamReader(System.in);
需要提高效率吗?需要!BufferedReader
BufferedReader bufr=new BufferedReader(isr);
3)目的:OutputStream Writer
是否是纯文本? 是! Writer。
设备:硬盘。一个文件。 使用FileWriter。
FileWriter fw=new FileWriter("c.txt");
需要提高效率吗?需要。
BufferedWriter bufw=new BufferedWriter(fw);
3、把录入的数据按照指定的编码表(utf-8),将数据存到文件中。
1)目的:OutputStream Writer
是否是纯文本? 是! Writer。
设备:硬盘。一个文件。 使用FileWriter。
2)但是FileWriter是使用默认编码表。GBK。
但是存储时,需要加入指定编码表。而指定的编码表只有转换流可以指定。
所以要使用的对象时OutputStreamWriter。
而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream
OutputStreamWriter osw= new OutputStreamWriter(new FileOutputStream("d.txt"), "UTF-8")
3)需要提高效率吗?需要。
BufferedWriter bufw=new BufferedWriter(osw);
所以记住。转换流什么使用。字符和字节之间的桥梁,通常涉及到字符编码转换时,需要用到转换流。
FileReader使用的默认编码GBK
OutputStreamWriter(OutputStream out, String charsetName)
创建使用指定字符集的 OutputStreamWriter。
见示例八
当程序在执行过程中的时候,try代码块中的语句可能会抛出的异常,被catch语句捕捉到将抛出的错误信息以日志的形式存储起来,形成异常的日志信息。方便程序员分析错误。
示例十:异常的日志信息
import java.io.*;
import java.text.*;
import java.util.*;
class ExceptionInfo
{
public static void main(String[] args)
{
try
{
int[] arr =new int[2];
System.out.println(arr[3]);
}
catch (Exception e)
{
try
{
Date d=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String s=sdf.format(d);
PrintStream ps=new PrintStream("info.log");
System.setOut(ps);//修改输出流设备
ps.println(s);//输出时间
}
catch (IOException ex)
{
throw new RuntimeException("文件创建失败");
}
e.printStackTrace(System.out);//将异常信息数据写入到info.log
}
}
}
1.获取系统信息:
Properties getProperties()
2.将信息输出到指定输出流中
void list(PrintStream out)
3.将输出流中数据存入指定文件中
new PrintStream("info.txt")
示例一十一:系统信息
import java.util.*;
import java.io.*;
class SystemInfo
{
public static void main(String[] args)
{
PrintStream ps = null;
try
{
//获取系统信息对象
Properties pop = System.getProperties();
//创建输出流对象,将输出流中数据存入指定文件中
ps = new PrintStream("info.txt");
//将属性列表输出到指定的输出流
pop.list(ps);
}
catch (Exception e)
{
throw new RuntimeException("获取系统信息失败。");
}
}
}