IO流用来处理设备间的数据传输 流对象都封装在java.io包中
按流向分 输入流 输出流
按操作数据分字节流 字符流 一般多用字节流 为什么出现字符流 因为不同地方有不同的编码表,在不同国家,不同操作系统的电脑上面会出现乱码,所以字符流可以在内部去融合编码表。
流有4个基类都是抽象类
字符流的抽象基类 InputStream 输入 OutputStream输出
字节流的抽象基类 Reader 读 Writer写
Writer类运用
write
(String str)
写入字符串
write
(char[] cbuf)
写入字符数组
write
(char[] cbuf, int off,int len)
写入字符数组的某一部分。
flush
()
刷新该流的缓冲
close
()
关闭流但会刷新它
在硬盘上创建数据并写入一些文字数据
FileWriterfw = new FileWriter(“
文件路径”);//创建FileWriter对象
fw.write()
; //调用writer方法将数据写入到内存中
fw.close()
; //将内存中的数据刷新到目的地,并关闭流对象
这种方法会把以前的内容覆盖掉若进行续写的话则FileWriter提供了方法
FileWriter
(String fileName, boolean append)
根据给定的 File 对象构造一个 FileWriter 对象。如果第二个参数为true
,则将字节写入文件末尾处,而不是写入文件开始处
FileWriterfw = new FileWriter(“
文件路径”,true);
处理异常
方法一 直接抛出异常 throws IOException
方法二try{ }catch(){ }
需要注意的是流最后都是要关闭的所以把close()方法放在finally中。但是有时候创建文件时路径不存在,则文件无法创建但无法调用close()方法,导致出现NullPointerException异常。所以需要对关闭的流对象进行空的判断。
代码:
FileWriter fw =null;
try
{
fw = new FileWriter("abc.txt");
fw.write("abcd");
}
catch(IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(fw!=null)
fw.close();
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
读取分两种
第一种一次读一个字节
FileReaderfr = new FileReader("abc.txt");//创建文件读取对象和指定名称的文件相关联
intch = 0;
while((ch= fr.read())!=-1);//进行循环读取,read()方法如果已到达流的末尾,则返回-1
System.out.println("ch="+(char)ch);//ch强制转换成char型
fr.close();
第二种一次读数组
FileReaderfr = new FileReader("abc.txt");
char[]buf = new char[2];//创建字符数组buf 数组长度为2。一般以1024的倍数定义
intnum = 0;
while((num= fr.read(buf))!= -1)
System.out.println(newString(buf,0,num));//String
(char[] value,int offset, int count)
从0开始取,取num个字符
fr.close();
进行文件的拷贝
方法一 一次写一个字符
FileWriter fw = new FileWriter(”目的地”)
FilerReader fr = new FileReader(“读取文件路径”);
Int ch = 0;
while((ch = fr.read())!=-1);
fw.write(ch);
fw.close();
fr.close();
方法二 一次写数组
FileWriter fw = new FileWriter(“目的地”);
FileReader fr = new FileReader(“读取路径”);
Char[] buf = new char[1024];
Int num = 0;
While((num = fr.raed(buf))!= -1);
Fw.writer(buf);
fw.close();
fr.close();
字符流缓存区为了提高读写效率
BufferedReader 和BufferedWriter类 只要将被提高效率的流对象作为参数传递给缓存区的构造函数即可。因此在创建缓存区前必须有流对象。
例: BufferReader br =new BufferReader(new(FileReader(“读取文件路径”)));
br.close() 关闭缓存区就是关闭缓存区的流对象
在 BufferedWriter中 newline()方法写入一个行分隔符
在 BufferedReader中 readLIne()方法读取一文本行包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null.
readLine()方法的原理是 一个个字节的读取,然后将读取的字节放入缓存区中,遇到/r/n返回.
BufferedWriter
FileWriter fw = new FileWriter("2.txt");
BufferedWriter bw = new BufferedWriter(fw);
for(int x=0; x<5; x++){
bw.write("abcdefg"+"::"x);
bw.newLine();
}
bw.flush();
bw.close();
BufferedReader
循环读一行
FileReader fr = new FilerReader(“读取文件地址”);
BufferedReader br = new BufferedReader(fr);
String line = null;
While((line=br.readLine())!= null)
System.out.println(line);
Br.close;
一次读取单个字符
FileReader fr = new FileReader("2.txt");
BufferedReader br = new BufferedReader(fr);
int num = 0;
while((num=br.read())!=-1){
System.out.print((char)num);
}
自己定义BufferedReader
class MyBufferedReader{
private FileReader r;
//定义构造函数
MyBufferedReader(FileReader r){
this.r = r;
}
//定义myReader方法,用于一次读取一行
public String myReader() throws IOException{
//定义一个临时容器
StringBuilder sb = new StringBuilder();
int ch = 0;
//当文本没有读到末尾时
while((ch=r.read())!=-1){
//如果包含任何行终止符'\r',则继续
if(ch=='\r'){
continue;
}//如果包含任何行终止符'\n',则返回容器中的数据
if(ch=='\n'){
return sb.toString();
}//如果都不满足,则将字符加入临时容器中
else{
sb.append((char)ch);
}
}
return null;
}
//定义一个关闭缓存区方法
public void myClose() throws IOException{
r.close();
}
}
装饰设计模式
当想要对已有对象进行功能增强时,可以定义类将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类成为装饰类
装饰类通常会通过构造方法接收被装饰的对象
装饰和继承的区别
装饰比继承要灵活避免了继承的臃肿,而且降低了类与类之间的关系。装饰类因增强已有对象具备的功能和已有的是相同的,但提供了更强的功能。所以装饰类和被装饰类通常位于一个体系之下。
比如MyWriter类中有MyFileWriter 也可以增加MyWordWriterMyPageWriter。但为了提高他们的写入效率加入缓存区MyBufferedFileWriter MyBufferedWordWriter MyBufferedPageWriter 但这样不利于程序的扩展性 他们都加入了缓存技术所以直接继承MyWriter就可以 定义MyBufferedWriter即可。提高了可扩展性。即使再加入了其他的类也可以调用MyBuffered
LineNumberReader运用
WriterFileReaderfr = new FileReader("2.txt");
LineNumberReader ln = new LineNumberReader(fr);
String line = null;
ln.setLineNumber(100);//设置行号
while((line=ln.readLine())!=null){
System.out.println(ln.getLineNumber()+"::"+line);//获取行号
}
字节流
InputStream 和 OutputStream
FileOutputStream fos = new
FileOutputStream (“
文件路径”);//创建
FileOutputStream对象
fos.write(“abcd”.getBytes())
; //把字符串转变成字符数组
fw.close()
; //关闭流对象
单个读取
FileInputStream fis = new FileInputStream(“
文件名”);
int ch = 0;
while((ch =fis.read())!= -1);
System.out.println((char)ch);
Fis.close();
读取数组
FileInputStream fis = new FileInputStream(“
文件名”);
byte[] buf =new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1);
System.out.println(new String(buf,0,len));
Fis.close();
方法三 因为
FileInputStream中定义了available()方法可以获取字符数
FileInputStream fis = new FileInputStream(“
文件名”);
byte[] b =new byte[fis.available()];
fis.read(buf);
System.out.println(newString(buf));
fis.close();
方法二和方法三区别在于定义的缓存区空间大小不一样。一般文件大采用方法三会造成缓存区溢出。所以方法三适用于小文件。一般采用方法二。
拷贝图片
FileInputStream fis = new FileInputStream("s1.jpg");
FileOutputStream fos = new FileOutputStream("s1-copy.jpg");
byte[] bt = new byte[1024];
int leg = 0;
while((leg=fis.read(bt))!=-1){
fos.write(bt);
}
fos.close();
fis.close();
字节流的缓存区
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream("s2.mp3"));
BufferedInputStream bis =
new BufferedInputStream(new FileInputStream("s1.mp3"));
int num = 0;
while((num=bis.read())!=-1){
bos.write(num);
}
bos.close();
bis.close();
键盘录入
System.out:
对应的是标准的输出设备 控制台
System.in
:对应的是标准的输入设备 键盘
方法一
InputStream is = System.in;
StringBuffer sb = new StringBuffer();
//方法二
/* while(true){
int num = is.read();
if(num == '\r')
continue;
if(num == '\n'){
String s = sb.toString();
if("over".equals(s));
System.out.println(s);
sb.delete(0, sb.length());
}
else
sb.append((char)num);
}*/
//方法一:
int num = 0;
while((num=is.read())!=-1){
if(num == '\r')
continue;
if(num == '\n'){
String s = sb.toString();
if("over".equals(s));
System.out.println(s);
sb.delete(0, num);
}
else
sb.append((char)num);
} }
方法二 转换流
方法一录入一行数据就是读取一行,也就是readLine()方法。但readLine()方法是BufferedReader()里的。将字节流转换成字符流需要调用转换流,被封装在字符流中。
InputStreamis = System.in;//创建输入流对象
InputStreamReaderisr = new InputStreamReader(is);//转换流
BufferedReaderbr = new BufferedReader(isr);
Stringline = null;
while((line=br.readLine())!=null)
{
if("over".equals(line))
break;
System.out.println(line.toUpperCase());
}
br.close();
对方法二读取转换流的优化
BufferedReaderbr =
newBufferedReader(new(InputStreamReader(System.in)))
读取转换流
BufferedWriterbw =
newBufferedWriter(new(OutputStreamWriter(System.out)))
录入转换流
InputStreamReader:字节流通向字符流的桥梁
OutputStreamWriter:字符流通向字节流的桥梁。
录入的是字符存在硬盘上的是字节
流的操作规律
流对象有很多,具体调用哪个流对象
第一:明确源和目的。 即输入流还是输出流。
第二:明确是否是纯文本文件。 是字符流。 不是 字节流。
第三:明确调用什么设备。 硬盘file 键盘System.in 控制台System.out。
要将数据按照指定编码表存入文件中。
在OutputStreamWriter中定义了
OutputStreamWriter
(OutputStream out, String charsetName)
创建使用指定字符集的OutputStreamWriter。
而在FileWriter中定义死了采用默认的编码形式,所以要指定编码则需要把字符流转变成字节流。
改变标准的输入输出设备。
在System中分配了从新分配标准的输入输出流。SetIn SetOut。
System.SetIn(newFileInputStream(“abc.txt”));
System.SetOut(newPrintStream(“a.txt”));
File类 用于将文件或者文件夹封装成对象,并且作为参数直接传递给流对象。
创建File对象
File f1 = newFile(“c:\\abc”,”abc.txt”);
在上例中出现目录分隔符\\,若在LINUX中无法识别。所以在File中定义了separator字符,用于替换目录分隔符。
File f1 = newFile(“c:”+”File.separator”+”abc”,”abc.txt”)
功能
1. 创建 createNewFile()
Filef1 = new File(”abc.txt”);
System.out.println(“create”+”f1.createNewFile()”);
若文件已存在则不创建返回false
创建文件夹
File f1 = newFile(”abc”);
System.out.println(“create”+”f1.mkdirs()”);
2. 删除 delete() 和deletetExit()
System.out.println(“create”+”f1.deleted()”);
上例中若出现异常则语句无法执行。如果放在finally中则有时删除不掉如文件正在运行时。所以采用delectExit()方法。在程序退出时删除指定文件
System.out.println(“create”+” deletetExit()”);
3. 判断
Exists()文件是否存在
isDirectory()是否是目录
isFile()是否是文件
isHidden()是否隐藏
isAbsolute()是否绝对路径
4. 获取信息
getName()名称 getPath()路径 getParent()父目录 length()大小
list()返回一个字符串数组 listFiles()返回一个抽象路径名数组
递归
列出指定目录下所有文件和文件夹包括子目录
publicstatic void main(String[] args){
Filedir = new File("d:\\java"); //创建File对象
showDir(dir);
}
publicstatic void showDir(File dir){
System.out.println(dir); //输出文件夹
File[]files = dir.listFiles(); //创建数组
for(intx=0; x<files.length; x++){
if(files[x].isDirectory()) //如果文件是目录
showDir(files[x]); //循环调用
else
System.out.println(files[x]);
}
}
在上面函数自己点用自身 这种表现形式叫做递归。
有序的迭代
public class day2005 {
public static void main(String[] args) {
File dir = new File("d:\\java");
getDir(dir,0);
}
public static String getLevel(int level){
StringBuffer sb = new StringBuffer();
for(int x=0; x<level; x++)
sb.append("|--");
return sb.toString();
}
public static void getDir(File dir,int level){
System.out.println(getLevel(level)+dir.getName());
level++;
File[] c = dir.listFiles();
for(int x=0; x<c.length; x++){
if(c[x].isDirectory())
getDir(c[x],level);
else
System.out.println(getLevel(level)+c[x]);
}
}
删除带内容目录
public static void main(String[] args){
Filedir = new File("d:\\java"); //创建File对象
deleteDir(dir);
}
publicstatic void deleteDir(File dir){
System.out.println(dir); //输出文件夹
File[]files = dir.listFiles(); //创建数组
for(intx=0; x<files.length; x++){
if(files[x].isDirectory()) //如果文件是目录
deleteDir(files[x]); //循环调用
else
System.out.println(files[x].toString()+::+files[x].delete());
}
}\
/*1.将指定的目录进行递归
2.获取递归过程所有的java文件的路径
3.将这些路径存储到集合中
4.将集合中的数据写入到一个文件中*/
public class day2010 {
public static void main(String[] args) throws IOException {
File dir = new File("d:\\java");
List list = new ArrayList();
fileToList(dir,list);
File file = new File(dir,"javaList.txt");
writeToFile(list,file.toString());
}
public static void fileToList(File dir,List list){
File[] files = dir.listFiles();
for(int x=0; x<files.length; x++){
if(files[x].isDirectory())
fileToList(files[x],list);
else
list.add(files[x]);
}
}
public static void writeToFile(List<File> list,String javaList) throws IOException{
BufferedWriter bw =
new BufferedWriter(new FileWriter(javaList));
for(File f : list){
String path = f.getAbsolutePath();
bw.write(path);
bw.newLine();
bw.flush();
}
}
Properties
Properties
继承于 Hashtable
所以继承map集合的特点,而且它里面存储的键值对都是字符串;是集合和IO相结合的集合容器。
特点:用于键值对形式的配置文件
存取:
Propertiespro = new Properties();
pro.setProperty("zhangsan","30");
pro.setProperty("lisi","40");
System.out.println(pro);//
存入
String value =pro.getProperty("lisi");
System.out.println(value);//
获取值
Set<String> names =pro.stringPropertyNames();
for(String s : names)
System.out.println(s+":"+pro.getProperty(s));//
全部获取
存取配置文件:
//1.
创建流对象和a.txt想关联
//2.
读取一行数据,并用=切割
//3.
左边为键 右边为值,存入到Properties集合中
public staticvoid loadDemo() throws IOException{
FileReader fr = newFileReader("a.txt");//读取a.txt文件内容
BufferedReader br = newBufferedReader(fr);
Properties pro = newProperties();
String line = null;// 读取一行数据,
while((line=br.readLine())!=null){
String[] arr =line.split("=");// 用=切割
//System.out.println(line);
pro.setProperty(arr[0],arr[1]);//左边为键 右边为值,存入到Properties集合中
}
br.close();
System.out.println(pro);//输出pro集合中的数据
IO包中其他类
打印流
字节打印流 PrintStream 字符打印流PrintWriter
构造函数可接收的类型
1.file对象 File 2. 字符串路径 String 3. 字节输出流 OutputStream
字符打印流多出个 字符输出流 Writer
BufferedReader br =
new BufferedReader(newInputStreamReader(System.in));
PrintWriter pw= new PrintWriter(System.out,true);//输出字节输出流,
//如果为 true,则 println、printf 或 format 方法将刷新输出缓
String line = null;
while((line = br.readLine())!=null) {
if("over".equals(line))
break;
pw.println(line);
pw.flush();//获取一次就刷新一次
}
br.close();
知识总结
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class 总结 {
}
/*
字符流:
Reader 为了提高效率产生了缓冲区
---InputStreamReader
---FileReader
---BufferedReader
---LineNumberReader
getLineNumber() 获得当前行号。
setLineNumber(int lineNumber) 设置当前行号。
Writer 为了提高效率产生了缓冲区
---OutputStreamWriter
---FileWriter
---BufferedWriter
InputStream 方法: close(); read() 读取单个字符;
read(char[] cbuf, int offset, int length) 将字符读入数组中的某一部分。
OutputStream 方法:close(); flush(); write(int c) 写入单个字符;
write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
BufferedReader方法:close() 关闭该流并释放与之关联的所有资源。
read() 读取单个字符。
read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
readLine() 读取一个文本行。
BufferedWriter方法:close() 关闭此流,但要先刷新它。
newLine() 写入一个行分隔符。
write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
write(int c) 写入单个字符。
应用:复制一个文件
方法一:一次读一个字符
FileReader fr = new FileReader("1.txt");
FileWriter fw = new FileWriter("2.txt");
int num =0;//定义一个变量,用于存储字符
while((num=fr.read())!=-1){
fw.writer((char)num);
}
fw.close;
fr.close;
方法二: 一次读取数组
FileReader fr = new FileReader("1.txt");
FileWriter fw = new FileWriter("2.txt");
char[] c = new char[1024];定义一个数组
int num = 0;
while((num=fr.read(c)!=-1){
fw.writer(c,0,num); //num的作用 定义数组c为1024个字节,如果不定义num则把1024个字节全部占用了。如果定义了则到文件末尾处就结束了
}
fw.close;
fr.close;
缓冲区:
BufferedReader br = new BufferedReader(new FileReader("2.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("3.txt"));
String leng = null;//一次读取一行
while((leng=br.readLine()!=null){
bw.writer(leng);
}
int num =0; //如果一次读取一个字符
while((num=fr.read())!=-1){
bw.writer(num);
}
bw.close;
br.close;
设置行号和获取行号:
FileReader fr = new FileReader("1.txt");
LineNumberReader lnr = new LineNumberReader(fr);
lnr.setLineNumber("100");设置行号
String leg = null;
while((leg=lbr.readLine())!=-1){
System.out.println(lnr.getLineNumber());获取行号
}
装饰设计模式:
class MyBufferedReader{
private FileReader r;
//定义构造函数
MyBufferedReader(FileReader r){
this.r = r;
}
//定义myReader方法,用于一次读取一行
public String myReader() throws IOException{
//定义一个临时容器
StringBuilder sb = new StringBuilder();
int ch = 0;
//当文本没有读到末尾时
while((ch=r.read())!=-1){
//如果包含任何行终止符'\r',则继续
if(ch=='\r'){
continue;
}//如果包含任何行终止符'\n',则返回容器中的数据
if(ch=='\n'){
return sb.toString();
}//如果都不满足,则将字符加入临时容器中
else{
sb.append((char)ch);
}
}
return null;
}
//定义一个关闭缓存区方法
public void myClose() throws IOException{
r.close();
}
}
*/
/*
字节流
InputStream
---FileInputStream
---FilerInputStream
---BufferedInputStream
OutputStream
---FileOutputStream
---FilerOutputStream
---BufferedOutputStream
FileInputStream方法: available()方法可以获取字符数; close();
read() 从此输入流中读取一个数据字节。
read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
FileOutputStream方法: close(); write(int b) 将指定字节写入此文件输出流。
write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
拷贝图片:
FileInputStream fis = new FileInputStream("s1.jpg");
FileOutputStream fos = new FileOutputStream("s1-copy.jpg");
byte[] bt = new byte[1024];
int leg = 0;
while((leg=fis.read(bt))!=-1){
fos.write(bt);
}
fos.close();
fis.close();
缓冲区:
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("s2.mp3"));
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("s1.mp3"));
int num = 0;
while((num=bis.read())!=-1){
bos.write(num);
}
bos.close();
bis.close();
键盘录入
System.out:对应的是标准的输出设备 控制台
System.in:对应的是标准的输入设备 键盘
键盘录入:
InputStream is = System.in;
StringBuilder sb = new StringBuilder();
while(true){
int ch = is.read();
if(ch=='\r')
continue;
if(ch=='\n')
String s = sb.toString();//将缓冲区变成字符串
if("over".equals(s))//如果遇到over则结束while循环
break;
else
System.out.print(sb);
sb.delete(0, sb.length());//清空容器里的数据
}
else
sb.append(ch);//数据继续添加到容器里
}
通过键盘录入方法可以看到和字符流BufferedReader中的readLine()方法相同 。所以是否可以把字节流转换成字符流
转换流:
读取转换流
BufferedReader br = new BufferedReader(new(InputStreamReader(System.in)))
录入转换流
BufferedWriter bw =new BufferedWriter(new(OutputStreamWriter(System.out)))
将键盘输入的数据输出在显示器中
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter (System.out));
String leg = null;
while((leg=br.readLine())!=null){
if("over".equals(leg))
break;
bw.write(leg);
bw.newLine();//newLine()方法在BufferedWriter 中。
bw.flush();
改变标准的输入输出设备
System 中的 SetIn(); SetOut();方法
将异常信息转换到文件中 log4j日志工具
*/