javaIO流文件操作实例详解图片示例
目录(?)[-]
- IO流
- IO流常用基类
- FileWriter
- IO异常处理
- 文本文件的读取方式
- FileReader
- 通过字符数组进行读取
- 字符流的缓冲区
- 对应类
- 装饰设计模式
- 字节流
- 复制一个图片
- 读取键盘录入
- 字符流
- 字节流
- 可通过InputStreamReader将字节流转换为字符流
- OutPutStreamWriter
- 流操作基本规律
- 将键盘录入的数据存入到一个文件中
- 异常日志信息
- 系统信息
- File类
- File对象功能创建删除
- IO流File对象功能判断
- 对象的序列化
- 管道流
- RandomAccessFile
- 操作基本数据类型
- 将字节流写入文件
- 读取文件中的字节
IO流
IO流用来处理设备间的数据传输,java对数据的操作是通过流的方式,java用于操作流的对象都在IO包中
流按照操作数据分为两种:字节流和字符流
流按照流向分为:输入流和输出流。
IO流常用基类:
字节流的抽象基类:InputStream、OutputStream
字符流的抽象基类:Reader、Writer
FileWriter
创建一个FileWriter对象,该对象一被初始化就别需要明确操作的文件。而且该文件会被创建到指定目录下。如果该文件已经存在,将被覆盖。
FileWriter fw = new FileWriter(“Demo.txt”);
→用write方法将字符串写入到流中
fw.write(“ABC”)
→刷新缓冲中的数据,将数据刷新到目的地中
fw.flush();
→fw:关闭流用close()方法,关闭前会刷新一次,关闭流后无法使用。
fw.close();
→flush和close的区别:flush刷新后流可以继续使用,,close刷新后会将流关闭。
注:close必须要做
IO异常处理
在外面建立引用,在try内进行初始化。
FileWriter fw = null;
try{
}catch(IO Exception)
{}
Finally{
try{}catch{}…..
}
文件的续写
New FileWriter(“Demo.txt”,true);
传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处进行数据的续写。
文本文件的读取方式
1、FileReader()
FileReader fr = new FileReader(“文件”);
创建一个文件读取流对象,和指定文件名相关联。要保证该文件时存在的,否则会出现FileNotFoundException
2、通过字符数组进行读取
自定义一个字符数组,用于存储读到的字符
该read(char[])返回的是读到字符个数
char[] buf = new char[1024];
int num = 0;
while((num =fr.read(buf))!= -1)
{
打印(newString(buf,0,num));
}
fr.close();
字符流的缓冲区
提高对数据的读写效率
对应类
BufferedWriter
BufferedReader
l 缓冲区要结合流才可以使用
l 在创建流的基础上对流的功能进行了增强
在创建缓冲区之前必须得先有流对象
FIleWriter fw = new FileWriter()(“xx.txt”);
BufferedWriter bufw = new BufferdWriter(fw);
bufw.write(“xx”);
bufw.flush();只要用到缓冲区就得刷新
bufw.close();关闭缓冲区,就是在关闭缓冲区中的流对象。
bufw.newLine();换行——跨平台的方法,必须用到缓冲区对象才能用到newLine();方法
l BufferedReader();
read();读一个/对数组
readLine();读一行,方便于对文本数据获取
Sting line = null;
while((line = bfr.readLine()) != null)
操作line;
+异常处理
readLine方法返回时,只返回回车符之前的数据内容,并不返回回车符。
readLine原理:无论是读一行还是读取多个字符,其实最终是在硬盘上一个一个读取,所以最终使用的还是read方法(一次读一个)
装饰设计模式
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入基于已有的功能,并提供加强功能,那么自定义的该了称为装饰类
“后期扩展增强功能,不建议修改源代码”
装饰和继承的区别:向上抽取得到父类就(继承体系)
对于扩展性差的类,找到其参数的共同类型,通过多态的形式,可提高扩展性。
装饰模式比继承更灵活,避免了继承体系臃肿,降低了类与类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能,所以装饰和被装饰类通常都属于一个体系。
从继承结构变成组合结构。建议:继承不要过多,用装饰扩展功能。
字节流
字节流操作和字符流一样
字节流的两个基类:InputStream——输入流OutputStream——输出流
*为刷新但必须close();关闭资源
字符流一样走字节,但它吧字节临时存起来,一个中文2个字节。
Windows中的回车2个字节。\r\n
available()可以得到字符个数
所以就不必用while循环来一个一个循环获、输出:
Byte[] buf = new byte[xx.avalible];
xx.read(buf)
注:此方法尽量少用,如果被操作的文件过大的话,会造成内存溢出。
复制一个图片
1、用字节读取流对象和文件关联
FileInputStream fis = new FileInputStream(“图片文件”);
BufferedInputStream bufrIn = new BufferedInputStream(fis);
2、用字节写入流对象创建一个图片文件,用于存储获取到的图片数据。
FileOutputStream fos = new FileOutputStream(“新建图片文件”);
BufferedOutputStream bufrOut = newBufferedOutputStream(fos);
3、通过循环读写,完成数据的存储
byte[] buf = new byte[1024];
int line = 0;
while((line = bufrin.read(buf)) != -1)
{
bufrOut.write(buf,0,len);
}
4、关闭资源
bufrOut.close();
bufrIn.close();
*在对有些文件的拷贝过程中,拷贝后附件的大小为零字节。
这是因为FileInputStream、FileOutputStream的read()、write()方法在读或写的过程中,读或写到的第一个字节就是-1。
read方法在对类型进行提升;
write方法在对类型进行强转。
这就是为什么read方法返回的是int类型而不是byte,避免了“-1”的发生,而write方法将最低4个字节写出去,保证数据的原样性。
读取键盘录入
字符流
Reader
|—-BufferedReader
close();读
|—-InputStreamReader: 字节流通向字符流的桥梁
|—-FileReader:FileReader 用于读取字符流。要读取原始字节流,请考虑
使用 FileInputStream
FileWriter
|—-BufferedWriter
write();写
|—-OutputStreamWriter:字符流通向字节流的桥梁
|—-FileWriter:FileWriter 用于写入字符流。要写入原始字节流,请
考虑使用 FileOutputStream。
字节流
InputStream
|—-FileInputStream
read();读
|—-FilterInputStream
|—-BufferedInputStream:缓冲
read();读
OutputStream
|—-FileOutputStream
write();写
|—-FilterOutputStream
|—-BufferedOutputStream:缓冲
write();写
System.out :对应标准输出设备:控制台
System.in :对应标准输入设备:键盘
操作数据用流对象
System.in.read()是一个阻塞方法,没有键盘录入就会一会一直等。
回车符对应2个字节:“\r”+“\n”
ASCII:\r—13 & \n—10
—————————————————————————————————————-
———-获取键盘输入,将输入字符转换成大写并输出,输入over,则退出————-
[java] view plaincopy- <div style=”text-align: left;”>InputStream in = System.in;</div><div style=”text-align: left;”>StringBuilder sb = new StringBuilder();</div><div style=”text-align: left;”>while(true)</div>{
- <div style=”text-align: left;”> in .read();
- if(ch=</div> intch
- == 13)
- continue;
- <div style=”text-align: left;”> Strings</div> if(ch== 10)
- {
- = sb.toString();
- <div style=”text-align: left;”>ver”.equals(s))
- </div> if(“
- o break;
- <div style=”text-align: left;”> System.out.println(s.toUpperCase());
- </div>
- sb.delete(0,sb.length());
- }
- else
- <div style=”text-align: left;”></div> sb.append((char)ch);
- <div style=”text-align: left;”></div>}
readLine是(字符流)BufferedReader类中的方法。
键盘录入的read是(字节流)InputStream的方法。
※可通过InputStreamReader将字节流转换为字符流。
InputStreamReader在构造的时候,它本身是一个字符流,须接收字节流
[java] view plaincopy- <div style=”text-align: left;”>InputStream in = System.in;</div><div style=”text-align: left;”>InputStreamReader isr = newInputStreamReader(in);</div><div style=”text-align: left;”>BufferedReader bufr = newBufferedReader(isr);</div>
———————————-InputStreamReader——————————————–
InputStreamReader接收InputStream
缓冲区BufferedReader接收Reader类
刚好,InputStreamReader也是Reader的子类
java.io.Reader
java.io.InputStreamReader
————————————– —————————————-
[html] view plaincopy- <div style=”text-align: left;”>String line = null;</div><div style=”text-align: left;”>while((line = bufr.read()) != -1)//////////read()如果读到末尾返回-1;readLine()方法如果读到末尾则返回null.</div><div style=”text-align: left;”>{</div><div style=”text-align: left;”> If(“over”.equals(line))</div> break;
- <div style=”text-align: left;”>close();</div> System.out.println(line.toUpperCase());
- }
- bufr
- <div style=”text-align: left;”>.</div>
※OutPutStreamWriter
字符流通向字节的桥梁
字符—à字节。
write将字符写出去。
录入的时候是字符,存的时候是字节。
键盘录入
BufferedReader bufr = newBufferedrReader(new InputStreamReader(System.in));
流操作基本规律
问题:用哪一个流对象?
① “源”和“目的”
源:输入流 InputStream(字节流)/Reader(字符流)
目的:输出流 OutputStream(字节流)/Writer(字符流)
② 确操作的数据是否为纯文本
是:字符流
否:字节流
※先明确体系,再到体系中指定具体对象
③ 当体系明确后在明确要使用哪个具体的对象
通过设备来区分:
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
将键盘录入的数据存入到一个文件中
※
源:InputStream ,Reader
字符:用Reader
设备:键盘,对应对象System.in
为方便起见,将操作键盘的数据转换成字符流,按照字符串操作。
↓
将System.in转换成字符流
InputStreamReader isr = newInputStreamReader(System.in);
↓
提高效率:BufferedReader
BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in));
&
BufferedReader bufr = newBufferedReader(isr);
※
目的地:OutputStream ,Writer
字符流:Writer
设备:硬盘,FileWriter
FileWriter fw = new FileWriter(“xx.txt”);
↓
提高效率:BufferedWriter
BufferedWriter bufw =new BufferedWriter(newFileWriter(“xx.txt”));
&
BufferedWriter bufw = newBufferedWriter(fw);
扩展:要把录入的数据按照指定的编码表如,UTF-8存到文件中
指定编码表:
OutputStreamWriter(OutputStream out,StringcharsetName);
charsetName:指定字符集(编码表)
存储时需要加入指定编码表UTF-8;
指定编码表只有转换流可以实现;
用OutputStreamWriter对象;
该转换流接收一个字节输出流,而且还可以操作文件的字节输出流:FileOutputStream
↓OutputStreamWriter osw = newOutputStreamWriter(new FileOutputStream(“d.txt”),“UTF-8”);
↓高效
BufferedWriter bufw = newBufferdWriter(osw);
※何时用转换流
字符和字节之间的桥梁,涉及到字符编码转换时。
※该变标准输入输出设备
System.in(new FileInputStream(“xx.txt”));
将输入设备设置为“xx.txt”文件
System.setOut(new PrintStream(“xx.txt”));
将输出设备设置为“xx.txt”文件
PrintStream(String filename)——创建具有指定文件名称和字符集且不带自动刷新的新打印流
异常日志信息
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-ddHH:mm:ss”);
String s = sdf.format(d);
PrintStream ps = new PrintStream(“Exeption.log”);
ps.println(s);
e.printStackTrace(System.out);
将throwable及其追踪输出到指定的输出流
系统信息
Properties prop = System.getProperties();
|——–List(PrintStream Out)将属性列表输出到指定的输出流
prop.list(System.out);—à打印到控制台
prop.list(new PrintStream(“xx.txt”));—à输出到指定文件
File类
流操作的只有数据
数据最明显的出现方式——文件
创建File对象
File f = new File(“a.txt”); & new File(String,pathName)
将a.txt文件封装成file对象
可将已有的和为出现的文件或文件夹封装成对象
File(String parent,String child);
File f2 = new file(“c:\\123”,”b.txt”);
目录和文件分成两个参数来传递
File d = new File(“c:\\123”);
File f3 = new File(d,”c.txt”);
等于new File(“c:\\23”,”c.txt”);
如果是绝对路径就打印绝对路径,如果是相对路径就打印相对路径
Separator() 目录分隔符
与系统有关的默认分隔符,为方便,它被表示成一个字符
File f = new File(“c:”+File.separator+“abc\\a.txt”);
跨平台
File对象功能:创建、删除
1、创建
Boolean createNewFile()
在硬盘创建一个新文件,有调用底层资源
File f = new File(“a.txt”);
f.createNewFile();
createTempFile(String prefix,String suffix)
prefix前缀;suffix后缀
createTempleFile(String,prefix,String suffix,Filedirectory)
在指定目录下创建一个指定前缀和后缀的文件
2、删除
Boolean delete()
删除文件或目录
f.delete();
void deleteOnExit()
退出时删除
IO流(File对象功能——判断)
l Boolean canExecute()
是否可执行
Boolean canRead();
Boolean canWrite();
l Int compareTo(File pathname)
按照字母顺序比较两个抽象路径
l Boolean exists()
测试文件目录是否存在
l Boolean mkdir()
创建指定目录
l Boolean mkdirs()
创建多级目录
l Boolean isDirectory()
判断是否是目录
对象的序列化
Serializable接口——没有方法的接口称为标记接口
ObjectInputStream、ObjectOutputStream直接操作对象的流
持久化、序列化
NotSerialzableException
※静态不能被序列化
静态方法区,
只能将堆中的内容序列化。
用transient关键字修饰非静态成员,被修饰的成员也将不被序列化(虽然在堆内存中)
管道流
输入输出可以直接进行连接,结合线程使用
PipedInputStream、PipedOutputStream
不建议对管道流尝试使用单个线程
RandomAccessFile
随机访问文件
直接集成自Object,但是IO包中的成员,因为它具备读写功能
其内部封装了一个数组,而且通过指针,对数组中的元素进行操作,课通过getFilePoint获取指针位置,同时可通过set改变指针的位置,完成读写的原理:内部封装了字节输入流和字节输出流
‘RandomAccessFile(String name,String mode)throws FileNotFoundException
name:取决与系统文件名
mode:指定用以打开文件的方式
r:以制度方式打开
rw:读写
文件的数据都在数组中,可调整指针来去数据
Raf.seek(8);
SkipBytes(int)跳过多少个字节
流:按顺序读写
RandomAccessFile要操作的文件不存在,会自动创建,如果存在则不会覆盖(rw模式)
如果模式为r,不会创建文件,会去读取已存在的文件,如果文件不存在,会报异常。
通过seek方法改变指针位置,来实现在指定位置的读写
操作基本数据类型
将字节流写入文件
DataOutputStreamdos = new DataOutputStream(newFileOutputStream(“data.txt”));
dos.writeInt(23);
dos.writeBoolean(true);
dos.writeDouble(3.13);
读取文件中的字节
DataInputStream dis = newDataInputStream(new FileInputStream(“data.txt”);
dis.readInt();
dis.readBoolean();
dis.readDouble();
如果读反,数据出来是错的,如果先读double(8个字节)就把int和boolean一起读了,读出乱码。
IO搞定!
- 感谢本文作者,谢谢http://blog.csdn.net/gongshoudao/article/details/10351343
- IO流常用基类