一、File类
File类主要有两个个作用:
1. 用来将文件或者文件夹封装成对象,方便对其属性信息进行操作
2. File对象可以作为参数传递给IO流的构造函数等。
当我们拿到文件或文件夹的对象时,就可以对这个文件或文件夹进行各种操作,比如:我们可以得到它的名字、大小、上次修改时间,它的绝对路径等,可以对它进行创建、删除获取文件夹中的文件列表等等,非常的方便。
下面我们通过一些例子来学习File类的使用:
1. 创建和删除
//将a.txt封装成对象,a.txt可以是文件或者文件夹
File f= new File("a.txt");
//在指定位置创建文件,若果已经存在,则不创建,返回false,创建成功返回true
boolean b = f.createNewFile();
boolean mkdir():创建文件夹,但是只能创建一级的文件夹
boolean mkdirs():可以创建多级文件夹
boolean delete():删除文件,删除失败返回false
void deleteOnExit():在程序退出时删除指定文件
2. 判断
boolean exits():判断文件是否存在
booleanisFile():判断是否是文件
booleanisDirectory():判断是否是文件夹
booleanisHidden():判断文件是否是隐藏文件
booleanisAbsolute():判断文件的路径是否为绝对路径
3. 获取信息
getName():获取信息
getPath():获取路径
getAbsolutePath():获取绝对路径
getParent():获取父目录
long lastModified():获取上次修改时间
long lenth():获取文件的长度
4. 练习:文件列表
/**
* 打印出文件列表,包括子文件夹下
* @param path
* @param i
*/
public static void listAll(String path,int i){
i++;
File dir = new File(path);
File[] files = dir.listFiles();
for(File f:files){
System.out.println(space(i)+f.getName());
if(f.isDirectory()){
listAll(f.getAbsolutePath(),i);
}
}
}
/**
* 提供空格或分割字符,来让文件或文件夹显示层级
* @param i
* @return
*/
public static String space(int i){
StringBuilder sb = new StringBuilder();
for(int j=0;j
5.练习:复制一个文件夹下的内容到另一个文件夹下
/**
* 把oldPath目录下的文件和文件夹复制到newPath目录下
* @param oldPath
* @param newPath
* @throws IOException
*/
public static void copyDir(String oldPath,String newPath) throws IOException{
//先判断路径是不是带分隔符,如果没有就加上
if(!newPath.endsWith(File.separator)){
newPath = newPath+File.separator;
}
//将文件或文件夹封装成File对象
File oldDir = new File(oldPath);
File newDir;
//当前文件夹下的列表
File[] files = oldDir.listFiles();
for(File f:files){
if(f.isDirectory()){
//如果是文件夹,递归
String dirName = f.getName();
newDir = new File(newPath+f.getName());
newDir.mkdirs();
copyDir(f.getAbsolutePath(),newDir.getAbsolutePath());
}
if(f.isFile()){
//如果是文件,则复制到新的文件夹下
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newPath+f.getName()));
byte[] buf = new byte[1024];
int len = 0;
while((len=bis.read(buf))!=-1){
bos.write(buf, 0, len);
bos.flush();
}
bos.close();
bis.close();
}
}
}
二、Properties
Properties是hashtable的子类。
它具备了map集合的特点。它里面存储的是键值对。
它是集合中和IO相结合的集合容器。
该对象的特点:可以用于存取键值对形式的配置文件。
//输入流关联配置文件,配置文件后缀名必须是properties
InputStream is = new FileInputStream("config.properties");
Properties pp = new Properties();
//加载流中的信息
pp.load(is);
//获取配置文件中的属性
String name = (String) pp.get("name");
System.out.println(name);
//修改配置文件中的内容
OutputStream os = new FileOutputStream("config.properties");
//如果有sex这个键,则修改,如果没有,就创建sex=man这个键值对
pp.setProperty("sex", "man");
//把内存中修改的内同存到文件里面
pp.store(os, null);
三、打印流
该流提供了打印的方法,可以将各种数据类型的数据都原样打印。
字节打印流:PrintStream
构造函数可以接收的参数类型:
1.File对象。File
2.字符串路径。String
3.字节输出流。OutputStream
字符打印流:PrintWriter
构造函数可以接收的参数类型
1.File对象。File
2.字符串路径。String
3.字节输出流。OutputStream
4.字符输出流。Writer
PrintWriter接收的参数类型更多。所以,我们一般使用PrintWriter
Scanner scanner = new Scanner(System.in);
String line = scanner.next();
PrintWriter out = newPrintWriter(System.out,true);
out.println(line);
四、SequenceInputStream
SequenceInputStream
表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
通俗的说就是把多个流对象封装到一个流对象里。
示例代码:三个读取流读取1.txt、2.txt和3.txt中的内容写到4.txt中
public static void main(String[] args) throws IOException {
//用Vector集合是为了用他的遍历方式,枚举
Vector
v = new Vector
();
v.add(new FileInputStream("f:\\1.txt"));
v.add(new FileInputStream("f:\\2.txt"));
v.add(new FileInputStream("f:\\3.txt"));
//获得vector集合中的所有元素,并封装到枚举里
Enumeration en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("f:\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
fos.flush();
}
fos.close();
sis.close();
}
小练习:将一个mp3文件按1M切割。切割后再将其还原(合并成一个)
/**
* 将一个文件按1M切割
* @param f
* @throws IOException
*/
public static void splitFile(File f) throws IOException{
FileInputStream fis = new FileInputStream(f);
FileOutputStream fos = null;
byte[] buf = new byte[1024*1024];
int len = 0;
int count = 1;
while((len = fis.read(buf))!=-1){
fos = new FileOutputStream("f:\\gj\\"+(count++)+".part");
fos.write(buf, 0, len);
fos.close();
}
fis.close();
}
/**
* 将刚才切割的文件合并成一个
* @throws IOException
*/
public static void megeFile() throws IOException{
Vector
v = new Vector
();
for(int i=1;i<=5;i++){
v.add(new FileInputStream("f:\\gj\\"+i+".part"));
}
Enumeration en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("f:\\gj\\gj.mp3");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
fos.flush();
}
fos.close();
sis.close();
}
五、PipedInputStream和PipedOutputStream
管道输入流和管道输出流,IO中和多线程相结合的流
public class PisPos {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//管道输入流
PipedInputStream in = new PipedInputStream();
//管道输出流
PipedOutputStream out = new PipedOutputStream();
//将管道输出和输入流连接起来
in.connect(out);
//定义两个Runnable接口的实现类才操作流
Reader r = new Reader(in);
Write w = new Write(out);
new Thread(r).start();
new Thread(w).start();
}
}
/**
* 负责操作管道输出流
* @author snn
*
*/
class Write implements Runnable{
private PipedOutputStream out;
public Write(PipedOutputStream out) {
super();
this.out = out;
}
@Override
public void run() {
try {
out.write("chi le ma ,shi jie ".getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(out!=null)
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 操作管道输入流
* @author snn
*
*/
class Reader implements Runnable{
private PipedInputStream in;
public Reader(PipedInputStream in) {
super();
this.in = in;
}
@Override
public void run() {
try {
byte[] buf = new byte[1024];
int len = 0;
while((len=in.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(in!=null)
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
六、RandomAccessFile
1.简介
该类不是IO体系中的子类,而是直接继承自Object
但是它是IO包中的成员,因为它具备读和写的功能
内部封装了一个数组,而且通过指针对数组的元素进行操作
可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置
其实完成读写的原理就是内部封装了字节输入流和输出流。
通过构造函数可以看出,该类只能操作文件。
而且操作文件还有模式:只读r,读写rw等
如果模式为只读r,不会创建文件,回去读取一个已存在的文件,如果该文件不存在,则会出异常
如果模式为读写rw,操作的文件不存在,会自动创建,如果存在则会被覆盖。
2.写方法
/**
* 演示RandomAccessFile写入文件
* @throws IOException
*/
public static void writeFile() throws IOException{
RandomAccessFile raf = new RandomAccessFile("ran.txt", "rw");
raf.writeChar(98);
raf.writeInt(97);
raf.writeLong(8L);
raf.writeChars("world");
raf.close();
}
3.读方法
public static void readFile() throws IOException{
RandomAccessFile raf = new RandomAccessFile("ran.txt", "rw");
// int read = raf.readChar();
// System.out.println(read);
raf.seek(2);//可以调整指针的位置
int i = raf.readInt();
System.out.println(i);
}
七、DataInputStream和DataOutputStrea
操作基本数据类型的流对象
1. 写入
/**
* 基本的写方法
* @throws IOException
*/
public static void writeData() throws IOException{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(98);
dos.writeBoolean(true);
dos.writeLong(9L);
dos.close();
}
2.读出
/**
* 基本的读方法
* @throws IOException
*/
public static void readData() throws IOException{
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
int i = dis.readInt();
boolean b = dis.readBoolean();
long l = dis.readLong();
System.out.println(i);
System.out.println(b);
System.out.println(l);
dis.close();
}
3.writeUTF()和readUTF()
以UTF-8的编码写入,这个方法需要特定的读取方法,因为这个UTF-8不同于普通的UTF-8,以普通的方式读取会出错。
/**
* 读取以UTF方式写入的数据
* @throws IOException
*/
public static void readUTF() throws IOException{
DataInputStream dis = new DataInputStream(new FileInputStream("utfdata.txt"));
String str = dis.readUTF();
System.out.println(str);
dis.close();
}
/**
* 以UTF的方式写入,必须用UTF的方式读出,不能用普通的方法
* @throws IOException
*/
public static void writeUTF() throws IOException{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdata.txt"));
dos.writeUTF("hello world!");
dos.close();
}
八、ByteArrayStream
用于操作字节数组的流对象。
ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经封装了一个可变长度的字节数组,这就是数据目的地。
因为这两个流对象都操作数组,并没有使用系统资源。所以,不用进行close关闭。
public static void byteArrayStreamDemo(){
ByteArrayInputStream bis = new ByteArrayInputStream("hello".getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len = 0;
while((len=bis.read())!=-1){
bos.write(len);
}
System.out.println(bos.size());
System.out.println(bos.toString());
}