IO流用来处理设备之间的数据传输。
FileReader
File:
按数据分为两种:字节流和字符路。
流向分为:输入流。输出流。
字节流的抽象基类:InputStream,OutputStream。
字符流的抽象基类:Reader,Writer。
FileWriter:创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。而且该文件会被创建到知道目录下,如果该目录下已有同名文件。将被覆盖。该步是明确数据要存放的目的地。
FileWriter fw = new FileWriter("d.txt");
fw.write("abc"); 字符串写入到流中。
fw.flush();刷新流对象中的缓冲数据,将数据刷到目的地中。
fw.close();关闭流资源。关闭之前会刷新一次缓冲数据。
IOException处理方式:
public static void main(String[] args){
FileWriter fw = null;
try
{
fw = new FileWriter();
fw.write("abc");
}
catch(IOException e)
{
System.out.print(e.toSring());
}
finally
{
try
{
if(!fw==null)
fw.close();
}
catch(IOException e)
{
System.out.print(e.toSring());
}
}
}
创建读取流对象,和指定名称文件相关联。如果文件不存在,抛出FileNotFoundException.
其中colse方法不会刷新缓冲区;
对应缓冲类
BufferedWriter 特有方法newLine();
BufferedReader 特有方法readerLine();
import java.io.*;
class byteDemo
{
public static void main(String[] args)
{
FileInputStream is=null ;
FileOutputStream os=null;
try
{
is= new FileInputStream("tupian.gif");
os= new FileOutputStream("tupian_copy.gif");
byte[] buf= new byte[1024];
int len=0;
while((len=is.read(buf))!=-1)
{
os.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("error");
}
finally
{
try
{
if(is!=null)
is.close();
}
catch (IOException e)
{
System.out.print("失败");
}
try
{
if(os!=null)
os.close();
}
catch (IOException e)
{
System.out.print("失败");
}
}
}
}
MyBufferedReader
import java.io.*;
class myBuffer
{
public static void main(String[] args)throws IOException
{
Buffered br = new Buffered(new FileReader("byteDemo.java"));
BufferedWriter bt = new BufferedWriter(new FileWriter("byteDemo_copy.txt"));
String line = null;
br.setNumber(100);
while((line=br.myReadLine())!=null)
{
bt.write(line);
bt.newLine();
bt.flush();
}
bt.close();
br.myClose();
}
}
class Buffered
{
private FileReader r;
private int lineNumber;
Buffered(FileReader r)
{
this.r=r;
}
public String myReadLine()throws IOException
{
lineNumber++;
StringBuilder sb = new StringBuilder();
int num=0;
while((num=r.read())!=-1)
{
if(num=='\r')
continue;
if(num=='\n')
return new String(lineNumber+":"+sb.toString());
//else
sb.append((char)num);
}
if(sb.length()!=0)
return new String(lineNumber+":"+sb.toString());
return null;
}
public void myClose()throws IOException
{
r.close();
}
public void setNumber(int n)
{
lineNumber=n;
}
public int getNumber()
{
return lineNumber;
}
}
字节流
FileOutputStream
FileInputStream
转换流对象:
InputStreamReader
OutputStreamWriter
流对象的操作规律:
1,明确源和目的。
2,操作的数据是否为纯文本。
3,当体系明确后,在明确使用哪个具体的对象。通过设备来区分,源设备:内存,硬盘,键盘。目的设备:内存,硬盘,控制台。
资源分割。读取流读到资源。分别输出到若干个文件中。
资源拼接。
SequenceInputStream(Enumeration<? extends InputStream> e)
SequenceInputStream(InputStream s1, InputStream s2)
首先将需要拼接的输入流对象存到集合当中,然后为了得到
Enumeration对象。建立匿名对象覆盖其中的方法使其与集合相关联。
import java.io.*;
import java.util.*;
class SplitFile
{
public static void main(String[] args) throws IOException
{
//split();
sequence();
}
//切割文件
public static void split() throws IOException
{
FileInputStream fis = new FileInputStream("D:\\java\\test\\day07\\冰河世纪1.RMVB");
FileOutputStream fos = new FileOutputStream("D:\\java\\test\\day07\\1.part");
//定义缓冲区
byte[] buf = new byte[1024*1024*10];
int len = 0;
int num = 1;
long n =0;
while((len=fis.read(buf))!=-1)
{
n++;
fos.write(buf,0,len);
if(n%10==0)
{
fos.close();
fos = new FileOutputStream("D:\\java\\test\\day07\\"+(++num)+".part");
}
}
fis.close();
fos.close();
}
//拼接文件
public static void sequence()throws IOException
{
//SequenceInputStream sis = new SequenceInputStream();
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for(int x=1;x<6;x++)
{
al.add(new FileInputStream("D:\\java\\test\\day07\\"+x+".part"));
}
final Iterator<FileInputStream> it = al.iterator();
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("D:\\java\\test\\day07\\copy.rmvb");
byte[] buf = new byte[1024*1024*10];
int len = 0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
sis.close();
fos.close();
}
}
将已有或者不存在的文件或者文件夹封装成文件对象。
File file=new File(pathname);
File file=new FIle(path,name);
常见方法:
1,创建:createNewFile();如果文件已经存在,则不创建返回false和输出流不同。
2,删除:delete(); deleteOnExit();退出时删除。
3,判断:canExecute() 是否是可执行文件。canRead(),canWrite(); exists()是否存在。mkdir()创建文件夹,创建一级目录。
mkdirs()创建多级目录。isFile(),isDirectory()。 isHidden()是否是隐藏的。isAbsolute()是否是绝对路径。
4,获取信息:getName();getPath(); getParent();返回的是绝对路径中的父目录。如果获取的是相对路径那么返回的是null。(getAbsolutePath();getAbsoluteFile();返回值不同可相互转换) lastModified();最后修改时间。length();
renameTo(),将一个文件改名,并按照路径放置文件。
目录里文件的递归例子
import java.io.*;
class FileDemo
{
public static void main(String[] args)
{
File dir=new File("d:\\java");
showDir(dir,0);
}
public static String getLevel(int level)
{
StringBuilder sb = new StringBuilder();
for(int x=0;x<level;x++)
{
sb.append(" ");
}
return sb.toString();
}
public static void showDir(File dir,int level)
{
System.out.println(getLevel(level)+dir.getName());
level++
File[] files = dir.listFiles();
for(int x=0;x<files.length;x++)
{
if(files[x].isDirectory())
showDir(files[x]);
else
System.out.println(files[x]);
}
}
}
删除目录原理:在windows中,删除目录从里面往外面删除。所以使用递归。
import java.io.*;
class RemoveDir
{
public static void main(String[] args)
{
File dir=new File("d:\\testdir");
removeDir(dir);
}
public static void removeDir(File dir)
{
File[] files=dir.listFiles();
for(int x=0;x<files.length;x++)
{
if(files[x].isDirectory())
removeDir(files[x]);
System.out.println(files[x].toString()+"file"+files[x].delete());
}
System.out.println(dir+":dir:"+dir.delete());
}
}
listRoots()列出根盘符。
list()列出目录中的文件名。封装的对象必须是目录。该目录还必须存在。可以加入文件名过滤器。
FilenameFileter(){
public boolean accept(FIle dir,String name){
return name.endsWith(" ");
}
}
Properties对象:是hashtable的子类。也就是说它具备map集合的特点。而且他里面储存的键值都是字符串。
此对象可以直接和流向关联。
pro.load(is);
是集合中和IO技术想结合的集合容器;
该对象的特点:可以用于键值对形式的配置文件。固定格式键=值。
import java.io.*;
import java.util.*;
class zhuCeDemo //注册表练习
{
public static void main(String[] args)throws IOException
{
File file = new File("peizhi.ini");
if(!file.exists())
file.createNewFile();
Properties pro= new Properties();
BufferedReader br = new BufferedReader(new FileReader(file));
//读取文件
pro.load(br);
String value = pro.getProperty("time");
int num=0;
if(value!=null)
num=Integer.parseInt(value);
num++;
if(num>=6)
{
System.out.print("error");
return;
}
pro.setProperty("time",num+"");
FileOutputStream fos = new FileOutputStream(file);
pro.store(fos,"");//将Properties里的数据通过流写到文件中
br.close();
fos.close();
}
}
对象的序列化:
ObjectInputStream和ObjectOutputStream
被操作的对象要实现Serializable(标记接口:无方法。);
可直接操作基本数据类型。将对象写到一个文件里去。将对象实例化存储。
管道流:
将输入输出管道流封装成2个对象。并且实现Runnable接口。
import java.io.*;
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in=in;
}
public void run()
{
try
{
byte[] buf = new byte[1024];
int len=in.read(buf);
String=new String(buf,0,len);
System.out.println(s);
}
catch (IOException e)
{
throw new RuntimeException("管道读取流失败");
}
}
}
class Write implements Runnable
{
private PipedOutputStream out;
Write(PipedOutputStream out)
{
this.out=out;
}
public void run()
{
try
{
out.write("guandao".getBytes());
out.close();
}
catch (IOException e)
{
throw new RuntimeException("管道输出流失败");
}
}
}
class PipedStreamDemo
{
public static void main(String[] args)throws IOException
{
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);
new Thread(new Read(in)).start();
new Thread(new Write(out)).start();
}
}
RandomAccessFile:随机访问文件
不是IO体系中的子类,而是直接继承自Object,但是他是IO包中的成员,因为他具备读写功能,内部封装了一个数组,而且通过指针对数组的元素进行操作,可以通过getFilePointer获取指针的位置,同时可以通过seek改变指针的位置。
其实读写原理就是内部封装了字节输入和输出流。
通过构造函数可以看出该类只能操作文件。并且可以选择模式。
模式有4种:r只读方式打开,rw打开以便读写 rws对文件内容和元数据每个同步更新的都同步写入到底层设备。rwd只同步内容
如果模式为r,文件没有,不会创建文件。抛出异常。
如果模式为rw,文件不存在,创建文件,如果存在不会覆盖。
名字过长统一用多字节形式存储
import java.io.*;
class RandomAccessFileDemo
{
public static void main(String[] args)thorws IOException
{
readFile();
//writeFile();
}
public static void writeFile()thorws IOException
{
RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
raf.write("java".getBytes());
raf.writeInt(97);
//raf。writeInt(97);默认写出最低8位一个字节
raf.write("java1".getBytes());
raf.writeInt(99);
raf.close();
}
public static void readFile()thorws IOException
{
RandomAccessFile raf=new RandomAccessFile("ran.txt","rw");
raf.seek(8*1);//调整对象指针
raf.write("java3".getBytes());//可在指定位置继续写入数据覆盖原数据
raf.skipBytes(8);//跳过指定的字节,不能往回跳
byte[] buf=new byte[4];
raf.read(buf);
String s=new String(buf);
int age=raf.readInt();
System.out.print(name+":"+age);
raf.close();
}
}
操作基本数据的流对象:
DataOutputStream与
DataInputStream
import java.io.*;
class DateStreamDemo
{
public static void main(String[] args)throws IOException
{
writeData();
readData();
}
public static void readData()throws IOException
{
DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));
//注意:读取一定要数据类型按存储顺序读,否则数据错乱。
int num=dis.readBoolean();
boolean b=dis.readBoolean();
double d=dis.readDouble();
dis.close();
}
public void static void write()throws IOException
{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(230);
dos.writeBoolean(true);
dos.writeDouble(99.323);
dos.close();
}
public static void writeUTFDemo()throws IOException
{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("UTF.txt"));
//通过UTF-8的编码形式写出数据。2格子8字节。只能用readUTF()读取
dos.writeUTF("你好");
dos.close();
}
}
操作字节数组:
ByteArrayInputStream与
ByteArrayOutputStream
ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为对象中已经封装了可变长度的字节数组,这就是数据目的
因为这两个流对象都操作的是数组,并没有使用系统底层资源。所谓不需要使用close关闭
import java.io.*;
class ByteArrayStream
{
public static void main(String[] args)
{
//数据源
ByteArrayInputStream bis =new ByteArrayInputStream("abcd".getBytes());
//数据目的
ByteArrayOutputStream bos=new ByteArrayInputStream();
int by=0;
while((by=bis.read())!-1)
{
bos.write(by);
}
System.out.print(bos.size()+":"bos.toString);
}
}
操作字符数组:
CharArrayReader与
CharArrayWriter
操作字符串:
StringReader与StringWriter