------- android培训、java培训、期待与您交流! ----------
前言:通过观看毕向东老师的java基础视频,查漏补缺,将一些自己掌握的还不牢固的知识写出来,希望和大家交流分享。
1.流操作的基本规律
1.流操作的基本规律:对于IO流的使用,由于流对象有很多,不知道该用哪一个。 可以通过三个明确来完成:
1) 明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer
2)操作的数据是否是纯文本。
是:字符流
否:字节流
3 ) 当体系明确后,再明确要使用哪个具体的对象。通过设备来进行区分:
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
2.举例说明:
1) 将一个文本文件中数据存储到另一个文件中。复制文件。
a)源:因为是源,所以使用读取流:InputStream和Reader
明确体系:是否操作文本:是,Reader
明确设备:明确要使用该体系中的哪个对象:硬盘上的一个文件。Reader体系中可以操作文件的对象是FileReader
是否需要提高效率:是,加入Reader体系中缓冲区 BufferedReader.
FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);
b)目的:输出流:OutputStream和Writer
明确体系:是否操作文本:是,Writer
明确设备:明确要使用该体系中的哪个对象:硬盘上的一个文件。Writer体系中可以操作文件的对象FileWriter。
是否需要提高效率:是,加入Writer体系中缓冲区 BufferedWriter
FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);
2 )将一个图片文件中数据存储到另一个文件中。复制文件。要按照以上格式自己完成三个明确。
a)源:输入流,InputStream和Reader
是否是文本?否,InputStream
源设备:硬盘上的一个文件。InputSteam体系中可以操作文件的对象是FileInputSteam
是否需要提供效率:是,BufferedInputStream
BufferedInputSteam bis=new BufferedInputStream(new FileInputStream("1.jpg"));
b)目的:输出流,OutputStream和Writer
是否是文本?否,OutputStream
源设备:硬盘上的文件,FileOutputStream
是否需要提高效率:是,加入BufferedOutputStream
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("2.jpg"));
3) 需求:将键盘录入的数据保存到一个文件中。
a)源:InputStream和Reader
是不是纯文本?是,Reader
设备:键盘。对应的对象是System.in。——为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。用Reader体系中转换流,InputStreamReader
需要提高效率吗?需要,BufferedReader
InputStreamReader isr = new InputStreamReader(System.in);
<pre name="code" class="java">
BufferedReader bufr = new BufferedReader(isr);
b)目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。需要提高效率吗?需要。
FileWriter fw = newFileWriter("c.txt");
BufferedWriter bufw = new BufferedWriter(fw);
3. 扩展:想要把录入的数据按照指定的编码表(UTF-8)(默认编码表是GBK),将数据存到文件中。用到转换流。
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘上的一个文件。使用 FileWriter。——但是FileWriter是使用的默认编码表:GBK。
而存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。所以要使用的对象是OutputStreamWriter。
该转换流对象要接收一个字节输出流,而且还可以操作的文件的字节输出流:FileOutputStream
<pre name="code" class="java"> OutputStreamWriter osw =new OutputStreamWriter(newFileOutputStream("d.txt"),"UTF-8");
需要高效吗?需要,BufferedWriter
BufferedWriter bufw = new BufferedWriter(osw);
转换流什么使用? 字符和字节之间的桥梁。通常,涉及到字符编码转换时,需要用到转换流。
练习:将一个文本数据打印在控制台上。要按照以上格式自己完成三个明确。
1)源:InputStreamReader
是文本?是:Reader
设备:硬盘。上的文件:FileReader
是否需要提高效率?是:BufferedReader
BufferedReader br=new BufferedReader(newFileReader("1.txt"));
2)目的:OutputStream Writer
是文本?是:Writer
设备:控制台。对应对象System.out。由于System.out对应的是字节流,所以利用OutputSteamWriter转换流
是否提高效率?是:BufferedWriter
BufferedWriter bw =new BufferedWriter(newOutputStreamWriter(system.out));
4.通过System类的setIn,setOut方法可以对默认标准输入输出设备进行改变
System.setIn(newFileInputStream(“1.txt”));//将源改成文件1.txt。
System.setOut(newFileOutputStream(“2.txt”));//将目的改成文件2.txt
5. 简单的异常日志信息:当程序运行出现异常时,不希望直接打印在控制台,而是打印到日志文件中,方便程序员查看,并及时调整的。
package file;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionToLog {
public static void main(String[] args) {
try {
int[] a = new int[2];
System.out.println(a[3]);
} catch (Exception e) {
try {
//创建时间对象
Date date = new Date();
//时间模块格式对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd HH:mm:ss");
String s = sdf.format(date);
//打印流对象
PrintStream ps = new PrintStream("e.log");
//修改输出流设备
System.setOut(ps);
//输出时间
ps.print(s);
} catch (Exception e2) {
throw new RuntimeException("文件创建失败!");
}
e.printStackTrace(System.out);//将异常信息输出指定输出流
}
}
}
运行结果:
6.系统属性信息存入文本
package file;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Properties;
/**
* 系统属性信息存入文本
* 获取系统信息:Properties getProperties()
* 将信息输出到指定输出流中:void list(PrintStream out)
* 将输出流中数据存入指定文件中:new PrintStream("systeminfo.txt")
* @author songwenju
*
*/
public class SystemInfor {
public static void main(String[] args) throws IOException {
Properties p = System.getProperties();
PrintStream ps = new PrintStream("systemInfo.txt");
System.setOut(ps);
p.list(System.out);
}
}
2.Properties——配置文件类
1.Properties是Hashtable的子类,它具备Map集合的特点。而且它里面还有存储的键值对,都是字符串,无泛型定义。是集合中和IO技术想结合的集合容器。
2. 可用于键值对形式的配置文件,在加载时,需要数据有固定的格式,常用的是:键=值
3.方法:
1)设置
Object setProperty(String key,String value);//设置键和值,调用Hashtable的方法put
2)获取
String getProperty(String key); //指定key搜索value
Set<String> stringPropertyName();//返回属性列表的键集,存入Set集合
3、加载流和存入流
void load(InputStream ism); //从输入字节流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。
void load(Reader reader);//从输入字符流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。
void list(PrintStream out);//将属性列表输出到指定的输出流
void store(OutputStreamout,String comments);//对应load(InputStream )将属性列表(键值对)写入输出流。comments属性列表的描述。
void store(Writerwriter, String comments); //对应load(Reader)将属性列表(键值对)写入输出流。comments属性列表的描述。
代码示例一:
package file;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
public static void main(String[] args)throws Exception {
//setAndGet();
//getFromFile();
loadDemo();
}
/**
* 使用Properties方法加载文件,修改文件并保存文件
* @throws Exception
*/
public static void loadDemo()throws Exception{
FileInputStream fis = new FileInputStream("infor.txt");
//定义Properties集合
Properties p = new Properties();
//加载文件
p.load(fis);
FileOutputStream fos = new FileOutputStream("infor.txt");//位置应该放在这里不然会被全覆盖。
//修改相应配置并保存
p.setProperty("sex", "female");
p.store(fos, "修改了一下");
p.list(System.out);
fos.close();
fis.close();
}
/**
* 演示,如何将流中的数据存储到集合中。 想要将info.txt中键值数据存到集合中进行操作。
* 1,用一个流和info.txt文件关联。
* 2,读取一行数据,将该行数据用"="进行切割。
* 3,等号左边作为键,右边作为值。
* 存入到Properties集合中即可。
* 将文件数据存储进Properties集合方法
*/
public static void getFromFile()throws Exception{
//定义Properties集合
Properties p = new Properties();
//使用字符读取缓冲流关联文件
BufferedReader bfr = new BufferedReader(new FileReader("infor.txt"));
String line = null;
while ((line = bfr.readLine())!= null) {
//System.out.println(line);
String[] pStrings =line.split("=");//将一行数据以“=”号进行分割
//将=左边作为键存入,将=右边作为值存入
p.setProperty(pStrings[0], pStrings[1]);
}
bfr.close();//关流
System.out.println(p);
}
/**
* 设置属性和得到属性
*/
public static void setAndGet(){
Properties p = new Properties();
p.setProperty("name", "song");
p.setProperty("age", "13");
//System.out.println(p);
Set<String> keys = p.stringPropertyNames();
p.setProperty("age", 20+"");
for (String string : keys) {
System.out.println(string+":"+p.getProperty(string));
}
}
}
代码示例二:
package file;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Properties;
/**
* 练习:用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示。
* 分析: 很容易想到的是:计数器。可是该计数器定义在程序中,随着该应用程序的退出,该计数器也在内存中消失了。
* 所以要建立一个配置文件,用于记录该软件的使用次数。该配置文件使用键值对的形式。键值对数据是map集合。
* 数据是以文件形式存储。使用io技术。那么map+io——>Properties。
* 思路:
* 1、用读取流关联文本信息文件。如果存在则读取,如果不存在,则创建
* 2、每次运行,将文件数据存入集合中,读取值,判断次数,如果小于等于5次,则次数增加1次,如果大于则输出提示信息。
* 3、将值小于等于5次的信息数据存入文件中
* @author songwenju
*/
public class RunCount {
public static void main(String[] args) throws Exception {
//创建集合对象 ,文件+io考虑properties
Properties prop = new Properties();
//将文件进行封装
File file = new File("count.ini");
//判断是否存在
if (!file.exists()) {
file.createNewFile();
}
//将文件于读取流进行关联
FileReader fReader = new FileReader(file);
//加载流中的文件数据到集合中
prop.load(fReader);
//定义计数器
int count = 0;
//获取次数值
String vaule = prop.getProperty("time");
//如果值不等于null,则将其赋值给count
if (vaule != null) {
count = Integer.parseInt(vaule);
}
//每启动一次自增
count++;
if (count >= 5) {
System.out.println("软件试用次数5次已经到了,请购买!");
return ;
}
//将次数记录住集合
prop.setProperty("time", count+"");
FileWriter fWriter = new FileWriter(file);
//将集合中的数据存入硬盘文件中
prop.store(fWriter, "软件使用次数");
//关流
fWriter.close();
fWriter.close();
}
}
运行结果:
3.打印流
1.打印流包括:PrintStream和PrintWriter,该流提供了打印方法,可将各种类型的数据都原样打印。
2.字节打印流:PrintStream
构造方法中可接收的参数类型:
1)File对象。File(能接受文件的对象都是需要重点掌握的)
2)字符串路径:String
3)字符输出流:OutputStream
3.字符打印流:PrintWriter
构造方法中可接受的参数类型
1)File对象:File
2)字符串路径:String
3)字节输出流:OutputStream
4)字符输出流:Writer
与 PrintStream 类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,
而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。
代码示例:
package file;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
/**
* @author songwenju
*
*/
public class PrintWriteDemo {
public static void main(String[] args) throws Exception {
//键盘录入
BufferedReader bur = new BufferedReader(
new InputStreamReader(System.in));
//对流的操作,打印到控制台
//PrintWriter pw = new PrintWriter(System.out,true);
//打印流关联文件,自动刷新
PrintWriter pw = new PrintWriter(new FileWriter("a.txt"),true);//对println,printf进行自动刷新。只对流有用。
String line = null;
while ((line = bur.readLine())!= null) {
if (line.equals("over")) {
break;
}
pw.println(line.toUpperCase());
//pw.flush();
}
//关闭流
pw.close();
bur.close();
}
}
4.序列流
1)SequenceInputStream对多个读取流进行合并成一个读取流。也被称为合并流。
2)常用构造函数
SequenceInputStream(Enumeration<?extends FileInputStream> e)
3)常见合并多个流文件步骤
a)创建集合,并将流对象添加进集合
b)创建Enumeration对象,将集合元素加入。
c)创建SequenceInputStream对象,合并流对象
d)创建写入流对象,FileOutputStream关联写入文件
e)利用SequenceInputStream对象和FileOutputStream对象读数据进行反复读写操作。
代码示例:package file;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;
/**
* 将三个文件的内容合并为一个
* SequenceInputStream 合并流
* 需求:将三个文本文件中的数据合并到一个文本文件中
* 思路:1、创建一个Vector集合,将三个文本文件字节流添加到集合中
* 2、创建Enumeration对象,创建SequnceInputStream对象关联Enumeration
* 3、输出流关联新文本文件
* 4、反复读写操作
* @author songwenju
*
*/
public class SequenceDemo {
public static void main(String[] args) throws Exception {
//创建vector集合,并添加相关流对象
Vector<FileInputStream> vector = new Vector<FileInputStream>();
vector.add(new FileInputStream("1.txt"));
vector.add(new FileInputStream("2.txt"));
vector.add(new FileInputStream("3.txt"));
//创建枚举对象
Enumeration<FileInputStream> e = vector.elements();
//合并流
SequenceInputStream sis = new SequenceInputStream(e);
//关联写入文件
FileOutputStream fos = new FileOutputStream("4.txt");
//反复读写操作
byte[] b = new byte[1024];
int len;
while ((len = sis.read(b))!= -1) {
fos.write(b,0,len);
fos.flush();
}
//关流
fos.close();
sis.close();
}
}
运行结果: