1. io用来处理设备之间的数据传输。
2. java对数据的操作时通过流的方式
3. 流按照操作数据分为两种:字节流与字符流。
4. 流按流向分为:输入流和输出流。
5. 字节流的抽象基类: inputStream
|--AudioInputStream
|--ByteArrayInputStream
|--FileInputStream
|--FilterInputStream
|--ObjectInputStream
|--PipedInputStream
|--SequenceInputStream
|--StringBufferInputStream
|--InputStream
OutputStream
|--ByteArrayOutputStream
|--FileOutputStream
|--FilterOutputStream
|--ObjectOutputStream
|--OutputStream
|--PipedOutputStream
6. 字符流的抽象基类. Reader
|---- BufferedReader
|---- CharArrayReader
|---- FilterReader
|---- InputStreamReader
|---- PipedReader
|----StringReader
Writer
|---- BufferedWriter
|---- CharArrayWriter
|---- FilterWriter
|---- OutputStreamWriter
|---- PipedWriter
|----PrintWriter
|---- StringWriter
由以上四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
import java.io.*;
/**字符流合字节流
* 字节流两个基类:InputStreamOutpuStream
*
* 字符流的两个基类:ReaderWriter
*
* 需求:在硬盘上,创建一个文件并写入一些文字数据。
*/
public class FileWriterDemo {
public static voidmain(String[] args) throws IOException{
//创建一个FileWriter对象,如果有重名文件,则会覆盖。
FileWriter fw = newFileWriter("d:"+File.separator+"demo.txt");
//调用write()将字符串写入流中
fw.write("测试数据");
//刷新流对象中的缓冲数据,将数据刷到目的地中。
fw.flush();
//关闭流资源,关闭之前会刷新一次流中数据。
fw.close();
}
}
----------------------------------------------------------------------------------------------------------------------------
第三节:IO异常处理方式
import java.io.*;
/**
* IO异常处理
*/
public class FileWriterDemo {
public static voidmain(String[] args) throws IOException{
FileWriter fw= null;
try{
fw= new FileWriter("d:"+File.separator+"demo.txt");
fw.write("测试数据");
fw.flush();
}
catch(IOExceptione){
System.out.println(e.toString());
}
finally{
try{
if(fw!=null)//如果文件没有被创建,则fw为null,所以要加判断
fw.close();
}
catch(IOExceptione){
System.out.println(e.toString());
}
}
}
}
----------------------------------------------------------------------------------------------------------------------------
import java.io.*;
/**
* 续写,回车符
*/
public class FileWriterDemo {
public static voidmain(String[] args) throws IOException{
FileWriter fw= null;
try{
fw = newFileWriter("d:"+File.separator+"demo.txt",true);//不覆盖已有的文件,在文件的末尾处续写
fw.write("你好,\r\n谢谢");//回车符在window下必须是\r\n
fw.flush();
}
catch(IOExceptione){
System.out.println(e.toString());
}
finally{
try{
if(fw!=null)//如果文件没有被创建,则fw为null,所以要加判断
fw.close();
}
catch(IOExceptione){
System.out.println(e.toString());
}
}
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------
1. 方式一
import java.io.*;
public class FileReaderDemo {
public staticvoid main(String[] args)throws IOException{
//创建一个文件读取流对象与文件相关联
//要保证文件存在,不存在报
FileReader fr= new FileReader("d:"+File.separator+"demo.txt");
//调用读取流对象的read方法。
//一次只读一个字符,而且会自动往下读。
int ch = 0;
while((ch=fr.read())!=-1){
System.out.println((char)ch);
}
fr.close();
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------
2. 方式二:通过字符数组读取
import java.io.*;
public class FileReaderDemo2 {
public staticvoid main(String[] args)throws IOException{
FileReader fr= new FileReader("d:"+File.separator+"demo.txt");
//定义一个字符数组
//该read(char[])返回的是读到字符的个数;
char[] buf =newchar[1024];
int num = 0;
while((num=fr.read(buf))!=-1){
Strings = new String(buf,0,num);
System.out.println(s);
}
fr.close();
}
} -----------------------------------------------------------------------------------------------------------------------------------------------
1. 重点掌握
import java.io.*;
public class Copy_1 {
public staticvoid main(String[] args)throws IOException{
FileWriter fw= null;
FileReader fr= null;
try{
fw =new FileWriter("D:"+File.separator+"demo.txt");
fr =new FileReader("D:"+File.separator+"RM_CUST_TMP.sql");
char[] buf =newchar[1024];
int len = 0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);
}
}catch (Exception e) {
throw newRuntimeException("读写错误");
}finally{
if(fw!=null)
try{
fw.close();
}catch(IOException e){
}
if(fr!=null)
try{
fr.close();
}catch(IOException e){
}
}
}
}
----------------------------------------------------------------------------------------------------------------------------------------------
1. 缓冲出的出现提高了对数据的读写效率。
a) 对应类:
<BufferedWriter>
void newLine() 写入一个行分隔符。跨平台的换行符。
<BufferedReader>
public String readLine() 只返回回车符之前的内容,并不返回回车符。
b) 缓冲区要结合流才可以使用。
c) 在流的基础上对流的功能进行了增强。
d) 原理是对象中封装了数组。
import java.io.*;
public class Copy_2 {
/* 缓冲区的出现是为了提高流的操作效率。
* 所以在创建缓冲区之前,必须要先有流对象。
*/
public staticvoid main(String[] args)throws IOException{
FileWriter fw= null;
FileReader fr= null;
BufferedReaderbr = null;
BufferedWriterbw = null;
try{
fw= new FileWriter("d:"+File.separator+"demo.txt");
fr= new FileReader("d:"+File.separator+"RM_CUST_TMP.sql");
//加入缓冲技术
br= new BufferedReader(fr);
bw= new BufferedWriter(fw);
/*
char[]buf = new char[1024];
intlen = 0;
while((len=br.read(buf))!=-1){
bw.write(buf,0,len);
}
*/
//高效写法
Stringline = null;
while((line=br.readLine())!=null){
bw.write(line);
}
bw.newLine();//跨平台的换行符(重要)
bw.write("---------------------写入结束-------------------------------");
bw.flush();
}catch(Exception e){
throw newRuntimeException("执行异常");
}finally{
try {
if(br!=null)
br.close();
} catch (Exception e) {
thrownewRuntimeException("读写失败");
}
try {
if(bw!=null)
bw.close();
} catch (Exception e) {
thrownewRuntimeException("读写失败");
}
}
}
}
----------------------------------------------------------------------------------------------------------------------------------------------
3. readLine()方法原理:
a) 无论是读一行还是读取多个字符,其实都是在硬盘上一个一个读取。所以最终使用的还是read方法。
b) 代码演示:
import java.io.*;
public class BufferedReaderTest {
publicstaticvoidmain(String[] args) throwsIOException {
FileReader fr = new FileReader("D:"+File.separator+"demo.txt");
MyBufferedReader mbr = new MyBufferedReader(fr);
String line = null;
while((line=mbr.myReadLine())!=null){
System.out.println(line);
}
mbr.myClose();
}
}
class MyBufferedReader{//定义一个临时容器,原BufferReader封装的是字符数组。
privateFileReaderfr;
MyBufferedReader(FileReader fr){
this.fr = fr ;
}
publicString myReadLine()throwsIOException{
//为了演示方便,定义一个StringBuilder容器,应为最终还是要将数据变成字符串。
StringBuilder sb = new StringBuilder();
intch = 0;
while((ch=fr.read())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0){
return sb.toString();
}
returnnull;
}
publicvoid myClose()throws IOException{
fr.close();
}
}
----------------------------------------------------------------------------------------------------------------------------------------
a) 当想要对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,并提供加强功能,那么自定义的该类称为装饰类。
b) 代码示例:
public class DecorationDesign {
public staticvoid main(String[] args) {
PersonDD p = new PersonDD();
SuperPersonDDsp = new SuperPersonDD(p);
sp.superEat();
}
}
class PersonDD{
public voideat(){
System.out.println("吃饭");
}
}
classSuperPersonDD{//增强PersonDD类
private PersonDD p;
SuperPersonDD(PersonDDp){
this.p = p;
}
public voidsuperEat(){
System.out.println("开胃酒");
p.eat();
System.out.println("甜点");
System.out.println("来一根");
}
}
----------------------------------------------------------------------------------------------------------------------------------------
a) LineNumberReader:代码示例
import java.io.*;
public class LineNumberReader1 {
public staticvoid main(String[] args) {
FileReader fr= null;
LineNumberReaderlnr = null;
try{
fr =new FileReader("d:"+File.separator+"RM_CUST_TMP.sql");
lnr= new LineNumberReader(fr);
lnr.setLineNumber(0);
Stringline = null;
while((line=lnr.readLine())!=null){
System.out.println(lnr.getLineNumber()+line);
}
}catch(Exception e){
throw newRuntimeException("读取错误");
}finally{
try{
if(lnr!=null)
lnr.close();
}catch(Exception e){
thrownewRuntimeException("关闭资源错误");
}
}
}
}
----------------------------------------------------------------------------------------------------------------------------------------
b) MyineNumberReader:代码示例
import java.io.*;
public class MyineNumberReaderDemo {
public staticvoid main(String[] args) {
FileReader fr= null;
MyineNumberReadermnr = null;
try {
fr =new FileReader("d:"+File.separator+"RM_CUST_TMP.sql");
mnr= new MyineNumberReader(fr);
Stringline = null;
mnr.setLineNumber(100);
while((line=mnr.myReaderLine())!=null){
System.out.println(mnr.getLineNumber()+line);
}
} catch (Exception e) {
}finally{
try {
if(mnr!=null)
mnr.myClose();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
classMyineNumberReader{
private Reader r;
private intlineNumber;
MyineNumberReader(Readerr){
this.r = r;
}
public String myReaderLine()throws IOException{
lineNumber++;
StringBuildersb = new StringBuilder();
int ch = 0;
while((ch=r.read())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0){
return sb.toString();
}
return null;
}
public voidmyClose() throws IOException{
r.close();
}
public voidsetLineNumber(int lineNumber){
this.lineNumber= lineNumber;
}
public intgetLineNumber(){
return lineNumber;
}
}
----------------------------------------------------------------------------------------------------------------------------------------
第十节:字节流File读写操作
a) FileInputStream中的一个方法
int available() 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。(可识别\r\n)
import java.io.*;
public class FileStream {
public staticvoid main(String[] args)throws IOException {
readFile_3();
}
//方法一:一个一个读
public staticvoid readFile_1() throws IOException{
FileInputStreamfis = new FileInputStream("D:"+File.separator+"RM_CUST_TMP.sql");
int ch = 0;
while((ch=fis.read())!=-1){
System.out.println((char)ch);
}
fis.close();
}
//方法二:带有缓冲区的,且在开发中以这种方法为主
public staticvoid readFile_2() throws IOException{
FileInputStreamfis = new FileInputStream("D:"+File.separator+"RM_CUST_TMP.sql");
byte[] buf =newbyte[1024];//建立缓冲区
int len = 0;
while((len=fis.read(buf))!=-1){
System.out.println(newString(buf,0,len));
}
fis.close();
}
//方法三:字节流特有的available()应用
public staticvoid readFile_3() throws IOException{
FileInputStreamfis = new FileInputStream("D:"+File.separator+"RM_CUST_TMP.sql");
byte[] buf =newbyte[fis.available()];//读取数据大小通过available()得到,所以不用循环读取
fis.read(buf);
System.out.println(newString(buf));
fis.close();
}
public staticvoid writeFile(byte[] buf,intstart,int len){
FileOutputStream fos = null;
try {
fos= new FileOutputStream("D:"+File.separator+"demo.txt");
fos.write(buf,start,len);
fos.flush();
} catch (IOException e) {
throw newRuntimeException("写入错误");
}finally{
try {
if(fos!=null)
fos.close();
} catch (IOException e) {
thrownewRuntimeException("关闭写入资源出错");
}
}
}
}
----------------------------------------------------------------------------------------------------------------------------------------
b) 需求:复制一个图片(不能用字符流)
c) 思路:用字节读取流对象和图片关联。
1. 用字节读取流对象和图片关联。
2. 用字节写入流对戏那个创建一个图片文件。
3. 通过循环读写,完成数据的存储。
4. 关闭资源。
import java.io.*;
public class Copy_3 {
public staticvoid main(String[] args)throws IOException{
FileInputStreamfis = null;
FileOutputStreamfos = null;
try {
fis= new FileInputStream("D:"+File.separator+"demo.jpg");
fos= new FileOutputStream("D:"+File.separator+"1.jpg");
byte[] buf =newbyte[1024];
int len = 0;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
} catch (Exception e) {
throw newRuntimeException("读写发生错误");
}finally{
try {
if(fis!=null)
fis.close();
} catch (Exception e2) {
thrownewRuntimeException("读取资源关闭发生错误");
}
try {
if(fos!=null)
fos.close();
} catch (Exception e2) {
thrownewRuntimeException("写入资源关闭发生错误");
}
}
}
}
----------------------------------------------------------------------------------------------------------------------------------------
1. BufferedInputStream和BufferedOutputStream代码示例:
import java.io.*;
public class Copy_4 {
public staticvoid main(String[] args)throws IOException{
long start = System.currentTimeMillis();
myCopy_1();
long end = System.currentTimeMillis();
System.out.println((end-start));
}
public staticvoid myCopy_1() throws IOException{
FileInputStreamfis = new FileInputStream("E:\\电影.音乐.照片\\音乐\\如果这都不算爱-张学友.mp3");
FileOutputStreamfos = new FileOutputStream("D:\\1.mp3");
BufferedInputStreambis = new BufferedInputStream(fis);
BufferedOutputStreambos = new BufferedOutputStream(fos);
byte[] buf =newbyte[1024];
int len = 0;
while((len=bis.read(buf))!=-1){
bos.write(buf,0,len);
}
bis.close();
bos.close();
}
}
----------------------------------------------------------------------------------------------------------------------------------------
2. 自定义字节流的缓冲区-read和write的特点:
import java.io.*;
public class Copy_5 {
publicstaticvoidmain(String[] args) throwsIOException{
long start = System.currentTimeMillis();
myCopy_1();
long end = System.currentTimeMillis();
System.out.println((end-start)) ;
}
publicstaticvoidmyCopy_1() throws IOException{
FileInputStream fis = new FileInputStream("E:\\电影.音乐.照片\\音乐\\如果这都不算爱-张学友.mp3");
FileOutputStream fos = new FileOutputStream("D:\\1.mp3");
MyBufferedInputStream bis = new MyBufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
intdate = 0;
while((date=bis.myRead())!=-1){
bos.write(date);
}
bis.myClose();
bos.close();
}
}
class MyBufferedInputStream{
privateInputStreamin;
privatebyte[]buf= newbyte[1024*4];
privateintpos= 0,count = 0;
MyBufferedInputStream(InputStream in){
this.in = in;
}
//一次读一个字节,从缓冲区(字节数组)获取
publicint myRead()throws IOException{
//通过in对象读取硬盘上的数据,并存储在buf中。
if(count==0){//
count = in.read(buf);
if(count<0)
return -1;
pos = 0;
byte b =buf[pos];
count--;
pos++;
return b&255;
}elseif(count>0){
byte b =buf[pos];
count--;
pos++;
return b&0xff;
}
return-1;
}
publicvoid myClose()throws IOException{
in.close();
}
}
----------------------------------------------------------------------------------------------------------------------------------------
1. 自定义字节流的缓冲区-read和write的特点:
a) System.out:对应的是标准输出设备,控制台。
b) System.in:对应的标准输入设别,键盘。
代码示例(键盘基本读入操作):
import java.io.*;
public class ReadIn {
publicstaticvoidmain(String[] args) throwsIOException {
InputStream in = System.in;
StringBuilder sb = new StringBuilder();
while(true){
intch = 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);
}
}
}
}
----------------------------------------------------------------------------------------------------------------------------------------
2. 读取转换流和写入转换流:
a) readLine方法是字符流BufferedReader类中的方法,而键盘录入的read方法是字节流InputStream的方法。
b) InputStreamReader字节流转换成字符流
c) OutputStreamWriter字符流转换成字节流
代码示例:
import java.io.*;
public class ReadIn_2 {
publicstaticvoidmain(String[] args) throwsIOException {
//将字节流转换成字符流,并且用字符流的装饰类BufferedReader的readLine方法
//常用的界面录入
BufferedReaderbr =
newBufferedReader(new InputStreamReader(System.in));
//输出流转换并且为了使用newLine方法所以使用BufferedWrite装饰类
BufferedWriterbw =
newBufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while((line= br.readLine())!=null){
if("over".equals(line))
break;
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
}
----------------------------------------------------------------------------------------------------------------------------------------
1. 明确源和目的。
a) 源:输入流。InputStreamReader
b) 目的:输出流。OutputStreamWrite
2. 操作的数据是否是纯文本的。
a) 是:字符流。
b) 不是:字节流。
3. 当体系明确后,再明确要使用哪个具体的对象。
a) 通过设备来进行区分。
源设备:内存,硬盘,键盘.
目的设备:内存,硬盘,控制台.
4. 是否需要提高效率。
a) 字符流:BufferedReader,BufferedWriter
b) 字节流:BufferedInputStream,BufferedOutputStream
5. 通常涉及到字符编码转换时需要用到转换流:
a) BufferedWriter bw =
newBufferedWriter(new OutputStreamWriter(new FileOutputStream(),” UTF-8”));
b) BufferedReader br =
new BufferedReader(new InputStreamReader(newFileInputStream(),”UTF-8”));
6. 改变标准输入输出设备:
a) static voidsetIn(InputStream in) 重新分配“标准”输入流。
b) static voidsetOut(PrintStream out) 重新分配“标准”输出流。
7. 异常的日志信息:最好用log4j
import java.io.*;
importjava.text.SimpleDateFormat;
importjava.util.Date;
public class ExceptionInfo {
public staticvoid main(String[] args) {
try {
int[] arr =newint[2];
System.out.println(arr[3]);
} catch (Exception e) {
try {
Dated = new Date();
SimpleDateFormatsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
PrintStreamps = new PrintStream("D:\\demo.txt");
ps.println(d);
System.setOut(ps);
} catch (Exception e2) {
thrownewRuntimeException("记录日志错误");
}
e.printStackTrace(System.out);
}
}
} ----------------------------------------------------------------------------------------------------------------------------------------
1. File概述
l 用来将文件或者文件夹封装成对象。
l 方便对文件与文件夹的属性信息进行操作。
l File对象可以作为参数传递给流的构造函数。
l 了解File类中的常用方法。
2. 创建File对象:
a) //将a.txt封装成file对象,可以将已有的和未出项的文件或者目录封装成对象。
File f1 = new File("D:\\a.txt");
b) //将目录和文件分开作为两个参数,好处是可以对目录下的不同文件进行操作.
File f2 = new File("D:","a.txt");
3. File对象功能:
a) 创建:
1. boolean createNewFile() 如果已经存在,则不创建并返回false。输出流则是若果存在,就覆盖源文件.
2. boolean mkdir() 创建此抽象路径名指定的目录。
3. boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
b) 删除:
1. booleandelete() 删除此抽象路径名表示的文件或目录。
2. voiddeleteOnExit() 虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
c) 判断:
1. booleanexists() 测试此抽象路径名表示的文件或目录是否存在。
2. boolean isDirectory()测试此抽象路径名表示的文件是否是一个目录。
3. boolean isFile()测试此抽象路径名表示的文件是否是一个标准文件。
4. boolean isHidden()测试此抽象路径名指定的文件是否是一个隐藏文件。
5. boolean isAbsolute()测试此抽象路径名是否为绝对路径名。
d) 获取:
1. String getName() 返回由此抽象路径名表示的文件或目录的名称。
2. String getPath() 将此抽象路径名转换为一个路径名字符串。
3. String getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回null。
4. String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。
5. long lastModified() 返回此抽象路径名表示的文件最后一次被修改的时间。
6. long length() 返回由此抽象路径名表示的文件的长度。
7. booleanrenameTo(File dest) 具有剪切重命名的功能。
8. static File[] listRoots() 列出可用的文件系统根。
9. String[] list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
10. File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
需求:显示目录中后缀为.sql的文件。
思路:1) 使用listFiles的过滤器.
2)在过滤器中用endWith()判断是否以XX结尾.
3)循环遍历此目录。
示例:
import java.io.*;
public class FileDemo2 {
public staticvoid main(String[] args)throws IOException {
consMethod();
}
public staticvoid consMethod() throws IOException{
//将a.txt封装成file对象,可以将已有的和未出项的文件或者目录封装成对象。
File f1 = new File("D:\\");
File[] file =f1.listFiles(new FilenameFilter() {
public booleanaccept(File dir, String name) {
if(name.endsWith(".sql")){
returntrue;
}else{
returnfalse;
}
}
});
for(File s1 : file){
System.out.println(s1.getName());
}
}
}
------------------------------------------------------------------------------------------------------------------------
11. 需求:遍历目录,显示目录和文件。
思路:1)listFiles列出目录内子文件。
2)for循环遍历判断子文件是否为目录,是则打印目录名并递归调用,不是则打印文件名。
示例:
import java.io.*;
public class FileDemo3 {
private staticint count= 0;
public staticvoid main(String[] args){
File file = new File("D:\\123");
getList(file,0);
System.out.println("文件总数:"+count);
}
public staticString getLevel(int level){
StringBuildersb = new StringBuilder();
sb.append("|--");
for(intx=0;x<level;x++){
sb.insert(0,"| ");
}
return sb.toString();
}
public staticvoid getList(File file,int level){
int thisLevel = level;
File[] f =file.listFiles();
for(intx=0;x<f.length;x++){
if(f[x].isDirectory()){
System.out.println(getLevel(thisLevel)+f[x].getName());
getList(f[x],(thisLevel+2));
}else{
System.out.println(getLevel(thisLevel)+f[x].getName());
count++;
}
}
}
}
------------------------------------------------------------------------------------------------------------------------
4. 删除带内容的目录:
需求:删除带内容的目录
思路: 1) 遍历目录里面所有文件。
2)判断,是目录则递归调用本函数,不是目录,就删除。
3) 遍历完成之后删除本目录。
示例:
import java.io.*;
public class FileDemo4 {
public staticvoid main(String[] args){
File f = new File("D:\\Tomcat6.0");
doDelete(f);
}
public staticvoid doDelete(File f){
File[] files= f.listFiles();
for(intx=0; x<files.length ;x++){
if(!files[x].isHidden() &&files[x].isDirectory()){
doDelete(files[x]);
}else{
System.out.println(files[x]+"--[File]--"+files[x].delete());
}
}
System.out.println(f+"--[dir]--"+f.delete());
}
}
------------------------------------------------------------------------------------------------------------------------
5. 创建java文件列表
需求:将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。建立一个java文件列表文件。
思路: 1) 对指定的目录进行递归。
2)获取递归过程所有饿java文件路径。
3) 将这些路径存储到集合中。
4) 将集合中的数据斜日到一个文件中。
示例:
import java.io.*;
importjava.util.*;
public class FileDemo5 {
public staticvoid main(String[] args)throws IOException{
File f1 = new File("F:\\Teach\\黑马\\第1阶段\\1.J2SE\\传智播客_Java培训_毕向东_Java基础源代码Codes");
List<File>list = new ArrayList<File>();
doList(f1,list);
File f2 = new File("D:\\a.txt");
writeToFile(list,f2.toString());
}
public staticvoid writeToFile(List<File>list,String fileAdd){
BufferedWriterbw = null;
try {
bw =new BufferedWriter(new FileWriter(fileAdd));
for(Iterator<File>it=list.iterator();it.hasNext();){
FilefileName = it.next();
bw.write(fileName.getAbsolutePath());
bw.newLine();
bw.flush();
}
} catch (Exception e) {
throw newRuntimeException("写入错误");
}finally{
try {
if(bw!=null)
bw.close();
} catch (Exception e2) {
thrownewRuntimeException("写入资源关闭错误");
}
}
}
public staticList<File> doList(File f,List<File> list){
File[] files= f.listFiles();
for(intx=0 ;x<files.length; x++){
if(files[x].isDirectory()){
doList(files[x],list);
}else if(files[x].getName().endsWith(".java")){
list.add(files[x].getAbsoluteFile());
}
}
return list;
}
}
------------------------------------------------------------------------------------------------------------------------
第十五节:Properties
1. Properties简述
l Properties是hashtable的子类。具备map集合的特点,存储的是键值都是字符串。
l 是集合中和IO技术相结合的集合容器。
l 该对象的特点:可以用于键值对形式的配置文件。
l 配置文件中带以#开头的为注释信息,不会被Properteis加载。
l 在加载时有固定格式:key=value
l 配置文件要么是XXX.Properties或者是XXX.xml
2. Properties的方法
a) Object setProperty(Stringkey, String value) 调用Hashtable 的方法put。
b) String getProperty(Stringkey) 用指定的键在此属性列表中搜索属性。
c) String getProperty(Stringkey, String defaultValue)用指定的键在属性列表中搜索属性。
d) Set<String> stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。
1.6版本出现此方法。
e) void list(PrintStream out) 将属性列表输出到指定的输出流。
f) void list(PrintWriter out) 将属性列表输出到指定的输出流。
使用示例:
importjava.util.*;
public class PropertiesDemo1 {
public staticvoid main(String[] args) {
Properties p= new Properties();
p.put("张三","30");
p.put("李四","31");
//已知key张三,获取value
String s =p.getProperty("张三");
System.out.println(s);
//遍历获取
Set<String>set = p.stringPropertyNames();
for(Iterator<String>it=set.iterator();it.hasNext();){
Stringname = it.next();
System.out.println(p.getProperty(name));
}
}
}
------------------------------------------------------------------------------------------------------------------------
3. Properties存取配置文件
需求:用Properties读取一个配置文件信息
思路:1)用一个流和info.txt文件关联。
2)读取一行数据,将该行数据用“=”进行切割。
3)等号左边作为键,右边作为值,存入到Properties中。
示例:
import java.io.*;
importjava.util.*;
public class PropertiesDemo2 {
public staticvoid main(String[] args)throws IOException {
File f = new File("d:"+File.separator+"info.txt");
setProperties_2(f);
}
public staticvoid setProperties_1(File file){//Properties方法原理
BufferedReaderbr = null;
Properties p= new Properties();
try {
br =new BufferedReader(new FileReader(file));
Stringline =null;
while((line=br.readLine())!=null){
String[]s = line.split("=");
p.put(s[0],s[1]);
}
} catch (Exception e) {
throw newRuntimeException("读取流错误");
}finally{
try {
if(br!=null)
br.close();
} catch (Exception e2) {
thrownewRuntimeException("流资源关闭错误");
}
}
}
public staticvoid setProperties_2(File file)throws IOException{//运用Properties的load方法
FileInputStreamfis= new FileInputStream(file);
Properties p= new Properties();
p.load(fis);
Setset = p.keySet();
for(Iteratorit=set.iterator();it.hasNext();){
Stringname = (String)it.next();
System.out.println(name+p.getProperty(name));
}
fis.close();
//list方法使用
p.list(System.out);
p.setProperty("李四","30");
FileOutputStreamfos = new FileOutputStream("d:"+File.separator+"info.txt");
p.store(fos, "注释");
}
}
----------------------------------------------------------------------------------------------------------------------------------------
4. Properties练习
需求:用于记录应用程序运行次数,如果使用次数已到,那么给出注册提示。
思路:1)开始想到的是计数器,但是计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。可随着程序退出,该计数器也在内存中消失了。下一次启动该程序,又重新开始从0计数。
2)所以要建立一个配置文件,用于记录该软件的使用次数。
3)该配置文件使用键值对的形式,这样便于阅读数据,并操作数据。
4)键值对是map集合,并使用io技术,那么及使用Properties.
示例:
import java.io.*;
importjava.util.*;
public class RunCount {
public staticvoid main(String[] args)throws IOException{
Properties prop= new Properties();
File file = new File("d:\\info.txt");
if(!file.exists())
file.createNewFile();
FileInputStreamfis = new FileInputStream(file);
prop.load(fis);
int count = 0;
String value =prop.getProperty("useTimes");
if(value!=null){
count =Integer.parseInt(value);
if(count>=5){
System.out.println("使用次数已到,拿钱!");
return ;
}
}
count ++;
prop.setProperty("useTimes", String.valueOf(count));
fis.close();
FileOutputStreamfos = new FileOutputStream(file);
prop.store(fos, "使用次数存储");
fos.close();
}
}
--------------------------------------------------------------------------------------------------------------------------------
1. 特点:
l 为其它输出流添加功能,使他们能够方便的打印各种数据值表示形式。
l 该流提供了打印方法,可以将各种数据类型的数据都原样打印。
2. PrintStream构造函数接受的参数类型
public PrintStream(OutputStream out,boolean autoFlush) autoFlush- 、boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区
l file对象。File
l 字符串路径。String
l 字节输出流。OutputStream
3. PrintWriter构造函数接受的参数类型
public PrintWriter(OutputStream out, boolean autoFlush) autoFlush - 、boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区
l file对象。File
l 字符串路径。String
l 字节输出流。OutputStream
l 字符输出流。Writer
使用示例:键盘录入操作输出控制台。
import java.io.*;
public class PrintStreamDemo {
public staticvoid main(String[] args)throws IOException {
BufferedReaderbr =
new BufferedReader(newInputStreamReader(System.in));
PrintWriter pw = new PrintWriter(System.out,true);//刷新参数只对流作用
String line= null;
while((line=br.readLine())!=null){
if("over".equals(line))
break;
pw.println(line.toUpperCase());//PrintWriter构造方法第二个参数为true,//println有flush()刷新作用
//pw.flush();
}
br.close();
pw.close();
}
}
----------------------------------------------------------------------------------------------------------------------------
1. 特点:
l 没有对应的OutputStream
l 表示其他输入流的逻辑串联
2. 使用示例:
import java.io.*;
import java.util.*;
public class SequenceInputStreamDemo {
public static voidmain(String[] args) throws IOException{
Vector<FileInputStream>v = new Vector<FileInputStream>();
v.add(newFileInputStream("D:\\1.txt"));
v.add(newFileInputStream("D:\\2.txt"));
v.add(newFileInputStream("D:\\3.txt"));
Enumeration<FileInputStream>en = v.elements();
SequenceInputStreamsis = new SequenceInputStream(en);
FileOutputStreamfos = new FileOutputStream("D:\\4.txt");
byte[] buf =new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
---------------------------------------------------------------------------------------------------------------------------
需求:D盘下存在一个大小为1G电影文件,切割此文件,切割后每个文件为100M,
然后恢复此文件
思路:分割文件
1)建立读取流对象,读取文件
2)在while循环外建立文件对象与输出流对象,文件对象是用来控制每个分割文件的大小,在while循环中,通过文件对象的length判断如果超过设定单个文件的大小后,就关闭原来的输出流对象,建立新的文件和输出流对象。
3)while循环结束后刷新和关闭输出流.
合并文件
1) 创建Arraylist集合用于存储输入流对象。
2) 新建Enumeration对象,复写nextElement和hasMoreElements方法,分别返回迭代器的it.next()和it.hasNext()。
3) 新建序列流传入Enumeration对象作为参数,并建立缓存读取数据。
4) 新建字节输出流,并输出序列流读取的数据.
示例:
import java.io.*;
import java.util.*;
public class SplitFile {
publicstatic void main(String[] args) throws IOException{
//splitFile();
mergeFile();
}
publicstatic void mergeFile() throws IOException{
//使用list集合存储读取流对象
ArrayList<FileInputStream>al = new ArrayList<FileInputStream>();
//新建存储分割文件的目录对象
Filedfile = new File("D:\\分割文件目录");
File[]f = dfile.listFiles();
for(intx=0; x<f.length;x++){
System.out.println(f[x]);
al.add(newFileInputStream(f[x]));
}
//通过Iterator和复写Enumeration对象方法获得枚举
finalIterator<FileInputStream> it = al.iterator();
Enumeration<FileInputStream>e = new Enumeration<FileInputStream>() {
public FileInputStream nextElement() {
returnit.next();
}
publicboolean hasMoreElements() {
returnit.hasNext();
}
};
//新建SequenceInputStream对象并读取各个流中的数据
SequenceInputStreamsis = new SequenceInputStream(e);
//建立字节输出流
FileOutputStreamfos = new FileOutputStream("D:\\分割文件目录\\0.rmvb");
//缓存
byte[]buf = new byte[1024];
intlen = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.flush();
fos.close();
}
publicstatic void splitFile()throws IOException{
//文件对象先写死,演示
Filefile = new File("d:\\1.rmvb");
//建立输入流对象
BufferedInputStreambis = new BufferedInputStream(new FileInputStream(file));
FileOutputStreamfos = null;
//缓存
byte[]buf = new byte[1024*1024];
intlen = 0;
//目录名计数器,从1.part开始命名
intcount = 1;
//在本目录下建立分割后文件存储目录
Filef = new File(file.getParentFile().toString()+File.separator+"分割文件目录");
if(!f.exists())
f.mkdirs();
//新建文件对象和输出流对象
FiledFile = new File(f+File.separator+(count)+".part");
fos= new FileOutputStream(dFile);
while((len=bis.read(buf))!=-1){
fos.write(buf,0,len);
fos.flush();
//关键点,当一个输出流输出数据超过100M后,就新建立新的文件对象和输出流对象
if(dFile.length()>=100000000){
count++;
fos.close();
System.out.println("count:"+count+"f1:"+dFile);
dFile = newFile(f+File.separator+(count)+".part");
fos= new FileOutputStream(dFile);
}
}
fos.flush();
fos.close();
}
}
---------------------------------------------------------------------------------------------------------------------------
1. 特点:
l PipedinputStream和PipedOutputStream
l 表示其他输入流的逻辑串联
2. 连接方式:
l 1) PipedInputStream(PipedOutputStreamsrc)
创建 PipedInputStream,使其连接到管道输出流 src
l 2) PipedOutputStream(PipedInputStreamsnk)
创建连接到指定管道输入流的管道输出流。
l 3) voidconnect(PipedOutputStream src)
使此管道输入流连接到管道输出流 src。
需求:管道流的使用
思路:自定义一个输入类
1)自定义一个输入类,实现Runnamle接口并覆盖run方法
2)在自定义类中定义成员输入管道流以及自定义类的构造函数。
3)在run方法中,定义缓存,然后用PipedInputStream管道流读取数据,并存入缓存入。
自定义一个输出类
1)自定义一个输出类,实现Runnamle接口并覆盖run方法
2)在自定义类中定义成员输出管道流以及自定义类的构造函数。
3)在run方法中,定义缓存,然后用PipedOutputStream管道流写出数据。
示例:
import java.io.*;
public class PipedIDemo {
public staticvoid main(String[] args)throws Exception{
PipedInputStreampis = new PipedInputStream();
PipedOutputStreampos = new PipedOutputStream();
pis.connect(pos);
Reader r = new Reader(pis);
Writer w = new Writer(pos);
new Thread(r).start();
new Thread(w).start();
}
}
class Reader implements Runnable{
private PipedInputStreampis;
Reader(PipedInputStreampis){
this.pis =pis;
}
public voidrun() {
try {
byte[] buf =newbyte[1024];
int len = 0;
while((len=pis.read(buf))!=-1){
Strings = new String(buf, 0, len);
System.out.println(s);
}
pis.close();
} catch (Exception e) {
throw newRuntimeException("管道读取流失败");
}
}
}
class Writer implements Runnable{
private PipedOutputStreampos;
Writer(PipedOutputStreampos){
this.pos =pos;
}
public voidrun() {
try {
pos.write("管道来了".getBytes());
pos.close();
}catch (Exception e) {
throw newRuntimeException("管道写入流失败");
}
}
} ---------------------------------------------------------------------------------------------------------------------------
第十九节:RandomAccessFile(重点,下载工具的多线程下载)
1. 基本概述:
l 如果模式为“r”,不会创建新文件,会去读取一个已经存在的文件,如果文件不存在,会报异常,如果模式为“rw”,文件存在,不会覆盖,会修改源文件。文件不存在,创建新文件。
l 随机访问文件,自身具备读写的方法。
l 通过skipBytes(intx),seek(int x)来达到随机访问。
l 该类不算是IO体系中子类,而是直接继承Object,内部封装一个数组,而且通过指针对数组的元素进行操作,同时可以通过seek改变指针的位置。
l 通过构造函数看,此类只能操作文件。
2. 原理:
l 完成读写的原理就是内部封装了字节输入流和字节输出流。
3. 注意点:
l write方法只写最低8位,所用writeInt写4字节,32位。
l 如果构造函数的参数为“r” 则write方法不能用。要注意模式的选择。
l 通过seek方法改变指针的位置,来进行指定的数据读取和写入。
示例:
import java.io.*;
public class RandomAccessFileDemo {
publicstaticvoidmain(String[] args) throws Exception{
//writeFile_1();
writeFile_2();
}
publicstaticvoidreadFile() throws Exception{
RandomAccessFileraf = new RandomAccessFile("d:\\1.txt","rw");
//调整对象中的指针
raf.seek(8*1);
//跳过指定的字节数,不能往回跳
raf.skipBytes(8);
byte[] buf = newbyte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();
System.out.println(name+":"+age);
raf.close();
}
publicstaticvoidwriteFile_1() throws Exception{
RandomAccessFileraf = new RandomAccessFile("d:\\1.txt","rw");
raf.write("李四".getBytes());
raf.write(97);
raf.write("王五".getBytes());
raf.write(99);
raf.close();
}
publicstaticvoidwriteFile_2() throws Exception{
RandomAccessFileraf = new RandomAccessFile("d:\\1.txt","rw");
raf.seek(8*3);
//第四个位置时周期
raf.write("周期".getBytes());
raf.write(103);
raf.close();
}
}
---------------------------------------------------------------------------------------------------------------------------
第二十节:操作基本数据类型的流对象DataStream(不算重点,开发时知道在哪就行)
1. 基本概述:
l DataInputStream。
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型
l DataOutputStream。
数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。
2. 注意点:
l writeUTF(String str)所写的数据必须用readUTF(DataInput in)读。
示例:
import java.io.*;
public class DataStreamDemo {
publicstaticvoidmain(String[] args) throwsIOException{
//writeData();
readeDate();
}
publicstaticvoidreadeDate()throws IOException {
FileInputStream fis= new FileInputStream("D:\\data.txt");
DataInputStream dis= new DataInputStream(fis);
int num = dis.readInt();
boolean b = dis.readBoolean();
double d = dis.readDouble();
System.out.println("num:"+num);
System.out.println("b:"+b);
System.out.println("d:"+d);
}
publicstaticvoidwriteData() throws IOException{
FileOutputStreamfos = new FileOutputStream("D:\\data.txt");
DataOutputStreamdos = new DataOutputStream(fos);
dos.writeInt(234);//写入4个字节
dos.writeBoolean(true);//一个字节
dos.writeDouble(9888.543);//
dos.close();
}
}
-----------------------------------------------------------------------------------------------------------------------------------
第二十一节:操作字节数组 (不算重点,开发时知道在哪就行)
1. 特点:
l ByteArrayInputStream:在构造的时候,需要接手数据源,而且数据源是一个字节数组。
l ByteArrayOutputStream:在构造时:不用定义数据目的,应为该对象中已经内部封装了可变长度的字节数组。这就是数据目的地。
l 因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭。
2. 示例:
import java.io.*;
public class ByteArrayStreamDemo {
public staticvoid main(String[] args)throws IOException {
//数据源.
ByteArrayInputStreambais = new ByteArrayInputStream("内存数据".getBytes());
//数据目的
ByteArrayOutputStreambaos = new ByteArrayOutputStream();
int by = 0;
while((by=bais.read())!=-1){
baos.write(by);
}
System.out.println(baos.size());
System.out.println(baos.toString());
//可以通过writeTo写入文件
FileOutputStreamfos = new FileOutputStream("D:\\1.txt");
baos.writeTo(fos);
}
}
---------------------------------------------------------------------------------------------------------------------------------
第二十二节:字符编码 (重点)
1. 概述:
l 字符流的出现为了方便操作字符。
l 通过转换流来完成InputStreamReader和OutputStreamWriter。在新建对象时可以加入字符参数。
2. 什么是编码表?
l 用1010二进制组合排列代表各个国家的文字,这个对应关系就形成了编码表。
3. 常见的编码表
l ASCII:美国标准信息交换码
i. 用一个字节的7位可以表示。
l ISO8859:拉丁码表。欧洲码表。
i. 用一个字节的8为表示。
l GB2312:中国的中文编码表。
l GBK:(1个中文2字节)中的中文编码表升级,融合了更多的中文文字字符号。(2万多)
l Unicode:国际标准码,融合了多种文字。
i. 所有文字都用两个字节来表示,JAVA语言使用的就是Unicode
l UTF-8:最多用三个字节来表示一个字符。(全世界通用,在每个字节加入标识头,区分什么编码是UTF编码)
4. 重点掌握问题:编码转换
l UTF-8和GBK都能识别中文,但是同一个汉字对应数字不相同,就需要转换.
l 编码:字符串à字节数组
Stringàbyte[]; str.getByte()
String(byte[] bytes,Charset charset)
byte[] getBytes(Charset charset)
l 解码:字节数组à字符串
byte[]àString; newString(byte[])
l 乱码已经产生,怎么解决?(产生情况:客户游览器”UTF-8”àTOMCAT服务器端解码用” ISO8859-1”造成乱码)
解决方法:如果乱码已经产生,则用乱码用解码的字符集重新编码一次,然后然找正确的字符集进行解码即可.
示例:
import java.io.*;
importjava.util.*;
public class EncodeStream {
public staticvoid main(String[] args)throws IOException {
useShow_2();
}
public staticvoid useShow_1() throws IOException{
InputStreamReaderisr =
new InputStreamReader(new FileInputStream("D:\\1.txt"),"gbk");
OutputStreamWriterosw =
new OutputStreamWriter(new FileOutputStream("D:\\2.doc"),"UTF-8");
char[] cbuf =newchar[1024];
int len = 0;
while((len=isr.read(cbuf))!=-1){
System.out.println(newString(cbuf, 0, len));
osw.write(cbuf,0, len);
osw.flush();
}
isr.close();
osw.close();
}
public staticvoid useShow_2() throws IOException{
String s = "你好";
System.out.println("原字符数据: "+s);
byte[] b1 = s.getBytes("GBK");
System.out.println("数组数据: "+Arrays.toString(b1));
String s1 = new String(b1,"ISO8859-1");
System.out.println("产生乱码: "+s1);
//如果乱码已经产生,则用乱码用解码的字符集重新编码一次,然后然找正确的字符集进行解码即可
byte[] b2 = s1.getBytes("ISO8859-1");
String s2 = new String(b2,"GBK");
System.out.println("重新编码后: "+s2);
}
}
---------------------------------------------------------------------------------------------------------------------------------
5. 重点练习:
l 需求:有5个学生有3门课成绩,从键盘输入以上数据(包括姓名,三门课成绩),
l 思路:自定义一个输入类
1)描述学生对象。
2)定义一个可操作的学生对象的工具类。
l 示例:
import java.io.*;
importjava.util.*;
public class StudentInfoDemo {
public staticvoid main(String[] args)throws IOException {
Comparator<cStudent>comp = Collections.reverseOrder();
StudentInfoToolsit = new StudentInfoTool();
Set<cStudent>set = sit.getStudent(comp);
sit.writeToFile(set);
}
}
class cStudent implements Comparable<cStudent>{
private String name;
private intma, cn, en, sum;
cStudent(String name, int ma,intcn, int en){
this.name =name;
this.ma =ma;
this.cn =cn;
this.en =en;
sum = ma + cn + en;
}
public String getName(){
return name;
}
public intgetSum(){
return sum;
}
public inthasCode(){
return this.name.hashCode()+sum*78;
}
public booleanequals(Object obj){
if(!(objinstanceofcStudent)){
throw newClassCastException("类型转换异常");
}
cStudent s =(cStudent)obj;
return this.name.equals(s.name)&&this.sum==s.sum;
}
public intcompareTo(cStudent s) {
int num =newInteger(this.sum).compareTo(new Integer(s.sum));
if(num==0){
return this.name.compareTo(s.name);
}
return num;
}
public String toString(){
return "Student["+name+", "+ma+", "+cn+", "+en+", "+"]";
}
}
classStudentInfoTool{
public Set<cStudent> getStudent()throws IOException{
return getStudent(null);
}
public Set<cStudent>getStudent(Comparator<cStudent> comp)throwsIOException{
Set<cStudent>set = null;
if(comp==null){
set= new TreeSet<cStudent>();
}else{
set= new TreeSet<cStudent>(comp);
System.out.println("a");
}
BufferedReaderbr =
new BufferedReader(newInputStreamReader(System.in));
String line= null;
while((line=br.readLine())!=null){
if("over".equals(line))
break;
String[]Info = line.split(",");
cStudents = new cStudent(Info[0],
newInteger(Info[1]),
newInteger(Info[2]),
newInteger(Info[3]));
set.add(s);
}
br.close();
return set;
}
public voidwriteToFile(Set<cStudent> set) throwsIOException{
BufferedWriterbw = new BufferedWriter(new FileWriter("D:\\StudentIofo.txt"));
for(Iterator<cStudent>it=set.iterator();it.hasNext();){
cStudents = it.next();
bw.write(s.toString()+"\t");
bw.write(s.getSum()+" ");
bw.newLine();
bw.flush();
}
bw.close();
}
}
----------------------------------------------------------------------------------------------------------------------------