概述
- 将文件或者文件夹封装成对象。
- 方便对文件与文件夹的属性信息进行操作。
- File对象可以作为参数传递给流的构造函数使用。
package com.sergio.File;
import java.io.File;
/**
* 三种创建文件对象的方式
* Created by Sergio on 2015-04-14.
*/
public class IntroductionFile {
public static void main(String[] args) {
consMethod();
}
//创建file对象,file对象打印为文件的目录,是相对打印相对,是绝对打印绝对
public static void consMethod() {
//将a.txt封装成file对象,可以将已有的和未出现的文件或者文件夹封装成对象
File f = new File("a.txt");
//指定目录下的文件
File f2 = new File("c:\\abc", "b.txt");
//另一种写法
File d = new File("c:\\txt");
File f3 = new File(d, "c.txt");
//根据系统的不同使用不同的分隔符,跨平台分隔符。相当于c:\\abc\\a.txt
File f4 = new File("c:" + File.separator + "abc" + File.separator + "a.txt");
}
}
File对象功能
1.创建
public static void createFile() throws IOException {
File f1 = new File("file.txt");
sop("创建新文件" + f1.createNewFile());
//只能创建一级文件夹。创建多级文件夹为mkdirs()
File f2 = new File("abc");
sop("创建文件夹" + f2.mkdir());
}
public static void sop(Object o)
{
System.out.println(o);
}
2.删除文件
//2。删除文件
public static void deleteFile()
{
File f = new File("file.txt");
//程序退出的时候删除文件,当文件在操作时被删除时会有提示,可以使用此方法在程序退出后删除不管异常等信息
f.deleteOnExit();
sop("删除文件" + f.delete());
}
public static void sop(Object o)
{
System.out.println(o);
}
3.判断
//判断文件是否可执行、可以度、可写等属性
public static void determineFile()
{
File f = new File("ImageHelper.java");
sop("文件是否存在:" + f.exists());
sop("判断文件是否可以执行" + f.canExecute());
//在判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是否存在,通过exists()判断
//sop("判断文件是否存在:" + f.exists());
sop("判断是否是目录" + f.isDirectory());
sop("判断是否是文件" + f.isFile());
sop("判断文件是否隐藏" + f.isHidden());
}
4.获取文件信息
//获取文件信息
public static void getInfo()
{
File f = new File("F:\\01.jpg");
sop("路径" + f.getPath());//获取路径的信息是文件是什么位置信息(绝对或者相对)获取什么信息
sop("绝对路径" + f.getAbsolutePath());
//返回的是绝对路径中的父目录,如果是相对路径返回null。如果相对路径中有上一层目录,那么该目录就是返回结果
sop("本文件的上一次文件目录" + f.getParent());
}
5.获取文件列表
//获取文件列表
public static void getFileList() {
//返回操作系统的盘符
File[] files = File.listRoots();
for (File f : files) {
System.out.println(f);
}
//获取c盘下的文件列表信息
File f = new File("c:\\");
//调用list方法的file对象必须是封装了一个目录,该目录还必须存在
String[] name = f.list();
for (String names : name) {
System.out.println(names);
}
//返回指定目录下的过滤过的文件名字
File dir = new File("f:\\");
String[] arr = dir.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".jpg");
}
});
for (String jpgname : arr) {
System.out.println(jpgname);
}
//返回指定目录下的文件的file对象
File dir1 = new File("f:\\");
File[] files1 = dir.listFiles();
for (File f1 : files1) {
System.out.println(f1.getName() + "::" + f1.length());
}
}
6.递归列出文件列表
- 注意:1.限定条件、2.要注意递归的次数,尽量避免内存溢出。
//递归列出指定目录下及目录下的所有的文件
public static void showDir(File dir) {
System.out.println(dir);
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]);
}
}
//按层级列出目录下的所有文件
public static String getLevel(int level) {
StringBuilder sb = new StringBuilder();
sb.append("|--");
for (int x = 0; x < level; x++) {
sb.insert(0, "--");
}
return sb.toString();
}
public static void showdir1(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())
showdir1(files[x], level);
else
System.out.println(getLevel(level) + files[x]);
}
}
7.删除带内容的目录
- 删除原理:Windows中,删除目录从里面往外删除(先删除文件夹里的文件在删除文件夹)。
package com.sergio.File;
import java.io.File;
/**
* 删除带内容的目录
* Created by Sergio on 2015-04-19.
*/
public class RemoveDir {
public static void main(String[] args) {
File file = new File("e:testdir");
removeDir(file);
}
//删除带内容的目录
public static void removeDir(File dir) {
File[] files = dir.listFiles();
//循环删除文件
for (int i = 0; i < files.length; i++) {
//判断隐藏属性为循环遍历准备。删除只需要判断目录即可
if (files[i].isHidden() && files[i].isDirectory())
removeDir(files[i]);
else
System.out.println(files[i].toString() + "文件" + files[i].delete());
}
//删除完文件后最后删除文件夹
System.out.println(dir + "目录" + dir.delete());
}
}
8.练习
- 将指定目录下的java文件绝对路径,存储到一个文本文件中。
package com.sergio.File;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 将指定目录下的java文件绝对路径,存储到一个文本文件中。
* Created by Sergio on 2015-04-19.
*/
public class JavaFileList {
public static void main(String[] args) {
File dir = new File("E:\\Projects\\IntellijIDEA\\okhttp-2.3.0");
List<File> list = new ArrayList<File>();
fileToList(dir, list);
File file = new File(dir, "java.txt");
writeToFile(list, file);
}
public static void fileToList(File dir, List<File> list) {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory())
fileToList(file, list);
else {
if (file.getName().endsWith(".java"))
list.add(file);
}
}
}
public static void writeToFile(List<File> list, File javaListFile) {
BufferedWriter bufw = null;
try {
bufw = new BufferedWriter(new FileWriter(javaListFile));
for (File f : list) {
//绝对路径
String path = f.getAbsolutePath();
bufw.write(path);
bufw.newLine();
bufw.flush();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (bufw != null)
bufw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
Prperties集合
1.概述
- 是hashtable的子类。
- 具备map集合的特点,存储的键值对都是字符串。
- 常用语键值对形式的配置文件。
2.存取
package com.sergio.Prperties;
import java.io.*;
import java.util.Properties;
import java.util.Set;
/**
* Created by Sergio on 2015-04-19.
*/
public class IntroductionProp {
public static void main(String[] args) {
setAndGet();
}
//设置和获取元素
public static void setAndGet() {
Properties prop = new Properties();
//设置
prop.setProperty("zhangsan", "30");
prop.setProperty("wangwu", "21");
System.out.println(prop.getProperty("wangwu"));
prop.setProperty("wangwu", "35");
//获取
Set<String> name = prop.stringPropertyNames();
for (String s : name) {
System.out.println(s + "::" + prop.getProperty(s));
}
}
}
3.操作存储键值对文件
package com.sergio.Prperties;
import java.io.*;
import java.util.Properties;
/**
* 操作键值存储文件
* Created by Sergio on 2015-04-20.
*/
public class ConfigProperties {
public static void main(String[] args) {
saveConfigFile();
loadDemo();
}
//将info.txt中的键值数据存储到集合并进行操作
public static void saveConfigFile() {
BufferedReader bufr = null;
try {
bufr = new BufferedReader(new FileReader("info.txt"));
String line = null;Properties prop = new Properties();
while ((line = bufr.readLine()) != null) {
String[] arr = line.split("=");
prop.setProperty(arr[0], arr[1]);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufr != null)
bufr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//load方法原理演示
public static void loadDemo() {
Properties prop = new Properties();
FileInputStream fis = null;
//FileOutputStream fos = null;
try {
fis = new FileInputStream("info.txt");
//fos = new FileOutputStream("info.txt");
prop.load(fis);
//改变内存结果,跟流有关,将流中的数据写入到文件中
prop.setProperty("mawu", "32");
//存储数据到文件中,备注信息一般不写中文,编码不支持,加载的数据有固定格式:键=值
//prop.store(fos, "备注信息");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
// try {
// if (fos != null)
// fos.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
}
prop.list(System.out);
System.out.println(prop);
}
}
其他流
1.打印流(PrintStream、PrinterWriter)
- 打印流:可将各种数据类型的数据都原样打印。
- PrintStream:用于接收的参数类型(File对象、字符串路径:String、字节输出流:OutputStream)。
- PrintWriter:用于输出的参数类型(File对象、字符串路径:String、字节输出流:OutputStream、字符输出流:Writer)。
package com.sergio.Prperties;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
/**
* 打印输出流的基本功能使用
* Created by Sergio on 2015-04-21.
*/
public class PrintStreamDemo {
public static void main(String[] args) throws Exception{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//可以传字符跟字节流的数据,也可以自动刷新
PrintWriter out = new PrintWriter(new FileWriter("test.txt"), true);
String line = null;
while ((line = bufr.readLine()) != null)
{
out.println(line.toUpperCase());
}
out.close();
bufr.close();
}
}
2.序列流(SequeenceInputStream)
- 对多个流进行合并
package com.sergio.Prperties;
import java.io.*;
import java.util.Enumeration;
import java.util.Vector;
/**
* 合并流使用
* Created by Sergio on 2015-04-21.
*/
public class SequenceDemo {
public static void main(String[] args) throws Exception {
//Vector对象只有Enumeration的功能
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("1.mp3"));
v.add(new FileInputStream("2.mp3"));
v.add(new FileInputStream("3.mp3"));
//获取元素
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
//输出流操作
FileOutputStream fos = new FileOutputStream("4.mp3");
byte[] buf = new byte[1024 * 1024 * 10];
int len = 0;
while ((len = sis.read()) != -1) {
fos.write(buf, 0, len);
}
fos.close();
sis.close();
}
}
3.切割流
- 对一个流进行分割
package com.sergio.Prperties;
import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
/**
* 切割流和合并流
* Created by Sergio on 2015-04-21.
*/
public class SplitFile {
public static void main(String[] args) throws Exception {
splitFile();
mergeFile();
}
//拆分文件
public static void splitFile() throws IOException {
FileInputStream fis = new FileInputStream("4.mp3");
FileOutputStream fos = null;
byte[] buf = new byte[1024 * 1024];
int len = 0;
int count = 1;
while ((len = fis.read(buf)) != -1) {
fos = new FileOutputStream((count++) + ".part");
fos.write(buf, 0, len);
fos.close();
}
fis.close();
}
//合并文件
public static void mergeFile() throws IOException {
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
//4个分拆文件
for (int x = 1; x <= 4; x++) {
al.add(new FileInputStream(x + ".part"));
}
final Iterator<FileInputStream> it = al.iterator();
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {
@Override
public boolean hasMoreElements() {
return it.hasNext();
}
@Override
public FileInputStream nextElement() {
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("test.mp3");
byte[] buf = new byte[1024 * 1024 * 5];
int len = 0;
while ((len = sis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
sis.close();
}
}
4.对象流
- ObjectInputStream与ObjectOutputStream:可以操作对象。
- 将堆内存中的对象数据存储到硬盘上,需要用到的时候再从硬盘上读取即可。此种操作方式为对象的序列化或者对象的持久化。
- 被操作的对象需要实现Serializable(标记接口(一般没有方法))。
- 静态变量不能被序列化。
package com.sergio.IOOther;
import java.io.Serializable;
/**
* 被序列化对象类
* Created by Sergio on 2015-04-23.
*/
public class Person implements Serializable {
public static final long serialVersionUID = 42L;
String name;
//关键字transient标记age变量不能被序列化
transient int age;
//静态变量不能被序列化
static String country = "cn";
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.sergio.IOOther;
import java.io.*;
/**
* 对象流操作动作
* Created by Sergio on 2015-04-23.
*/
public class ObjectStreamDemo {
public static void main(String[] args) throws Exception {
//writeObject();
readObject();
}
//序列化写入
public static void writeObject() throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
oos.writeObject(new Person("lisi", 24));
oos.close();
}
//序列化读取
public static void readObject() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
Person p = (Person) ois.readObject();
System.out.println(p);
ois.close();
}
}
5.管道流
- PipedInputStream和PipedOutputStream。输入输出可以直接进行连接,通过结合线程使用(不建议使用单线程,容易死锁)。
- 作用:将输入输出流对接在一起使用。
package com.sergio.IOOther;
import com.sergio.lianxi.ExceptionDemo;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
/**
* 管道流操作方式方法
* Created by Sergio on 2015-04-23.
*/
public class PipedStreamDemo {
public static void main(String[] args) throws IOException {
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
pis.connect(pos);
Read r = new Read(pis);
Write w = new Write(pos);
new Thread(r).start();
new Thread(w).start();
}
}
//读取线程
class Read implements Runnable {
private PipedInputStream in;
Read(PipedInputStream in) {
this.in = in;
}
@Override
public void run() {
try {
byte[] buf = new byte[1024];
int len = in.read(buf);
String s = new String(buf, 0, len);
System.out.println(s);
in.close();
} catch (IOException e) {
throw new RuntimeException("管道读取流失败");
}
}
}
//写入线程
class Write implements Runnable {
private PipedOutputStream out;
Write(PipedOutputStream out) {
this.out = out;
}
@Override
public void run() {
try {
Thread.sleep(6000);
out.write("管道流线程测试".getBytes());
} catch (Exception e) {
throw new RuntimeException("管道写入失败");
}
}
}
6.RandomAccessFile
- 具备随机访问文件功能,自身具备读写的方法。
- 该类不算是IO体系中的子类,而是直接继承之Object。但是它是IO包中的成员,因为具备读和写的功能。
- 方法的实现:内部封装了一个数组,通过指针对数组的元素进行操作,可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。
- 读写原理:内部封装了字节输入流和输出流。
- 缺点:从构造函数看只能操作文件。而且操作文件还有模式规定:r,rw,rws,rwd四种。
- 注意:此对象的构造函数药操作的文件不存在,会自动创建,如果存在会覆盖。如果模式为只读r,不会创建文件,会去读取一个已存在的文件,如果该文件不存在,则会出现异常。如果模式为rw,操作的文件不存在,会自动创建,如果存在则不会覆盖。
package com.sergio.IOOther;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 随机访问文件
* Created by Sergio on 2015-04-24.
*/
public class RandomAccessFileDemo {
public static void main(String[] args) throws Exception {
writeFile();
writeFile_2();
readFile();
}
public static void writeFile() throws Exception {
RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");
//写入一个字节数值
raf.write("wangwu".getBytes());
raf.write(23);
//写入32位数值
raf.writeInt(234);
raf.close();
}
public static void writeFile_2() throws Exception {
RandomAccessFile raf = new RandomAccessFile("test.txt", "r");
//跳过8位开始写入数据
raf.seek(8 * 0);
raf.write("maliu".getBytes());
raf.writeInt(234);
raf.close();
}
public static void readFile() throws IOException {
RandomAccessFile raf = new RandomAccessFile("test.txt", "r");
//调整对象中的指针,从第八个字节处取数据,可以自由位置获取
raf.seek(8);
//跳过指定的字节数,只能向前走,不能往后跳
//raf.skipBytes(8);
byte[] buf = new byte[4];
raf.read(buf);
//获取文件中的姓名跟年龄数据
String name = new String(buf);
int age = raf.readInt();
System.out.println("name" + name);
System.out.println("age" + age);
raf.close();
}
}
7.基本数据类型流
- DataInputStream和DataOutputStream
package com.sergio.IOOther;
import java.io.*;
/**
* 操作基本数据类型的流对象
* Created by Sergio on 2015-05-12.
*/
public class DataStreamDemo {
public static void main(String[] args) throws IOException {
writeUTFDemo();
readUTFDemo();
readData();
writeData();
}
//特殊UTF-8编码对应的读取方式
public static void readUTFDemo() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("utfdata.txt"));
String s = dis.readUTF();
System.out.println(s);
dis.close();
}
//特殊版UTF-8编码写入数据
public static void writeUTFDemo() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdata.txt"));
dos.writeUTF("你好");
dos.close();
}
//读取数据
public static void readData() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
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);
dis.close();
}
//写入数据
public static void writeData() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(23);
dos.writeBoolean(true);
dos.writeDouble(238.34);
dos.close();
}
}
8.ByteArrayStream流
- 操作字节数组的流对象。
- ByteArrayInputStream:在构造的时候,需要接受数据源,而且数据源是一个字节数组。
- ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组,缓冲区会随着数据的不断写入而自动增长,这就是数据目的地。
- 特点:这两个流对象都不需要进行关闭,因为操作的是数组,而不是系统资源,可以继续被调用,不会产生任何IO异常。
- InputStreamReader和OutputStreamWriter:两个转换流构造的时候加入了字符集。
package com.sergio.IOOther;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
/**
* 用流的读写四项来操作数组
* Created by Sergio on 2015-05-13.
*/
public class ByteArrayInputStreamDemo {
public static void main(String[] args) {
//数据源
ByteArrayInputStream bis = new ByteArrayInputStream("abc".getBytes());
//数据目的
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int b = 0;
while ((b = bis.read()) != -1) {
bos.write(b);
}
System.out.println(bos.size());
System.out.println(bos.toString());
}
}
转换流的字符编码
- 因为计算机智能识别二进制数据,为了方便应用计算机就将各个国家的文字用数字表示,并一一对应,形成了一张编码表。
- 常见编码表:ASCII(美国标准信息交换码)、ISO8859-1(拉丁码表)、GB2312(中国的中文编码表)、GBK(中文编码的升级版,融合了更多的中文字符号)、Unicode(国际标准码,所有文字都用两个字节表示,Java语言用就是这个)、UTF-8(最多三个字节来表示一个字符)。
package com.sergio.IOOther;
import java.io.*;
/**
* 字符编码简单介绍
* Created by Sergio on 2015-05-13.
*/
public class EncodeStream {
public static void main(String[] args) throws IOException {
writeText();
readText();
}
//指定解码的编码表.解码要跟编码相同才可解码准确。
public static void readText() throws IOException {
//转换流
InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"), "UTF-8");
char[] buf = new char[10];
int len = isr.read(buf);
String s = new String(buf, 0, len);
System.out.println(s);
}
//指定编码的编码表
public static void writeText() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"), "UTF-8");
osw.write("测试");
osw.close();
}
}
字符编码
- 编码:字符串变字节数组。
str.getBytes();
- 解码:字节数组变字符串。
new String(byte[])
package com.sergio.IOOther;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/**
* 编码示例
* Created by Sergio on 2015-05-13.
*/
public class EncodeDemo {
public static void main(String[] args) throws Exception {
String s = "你好!";
//编码
byte[] b1 = s.getBytes("GBK");
System.out.println(Arrays.toString(b1));
//解码
String s1 = new String(b1, "GBK");
System.out.println("s1 = " + s1);
}
//乱码演示和解决
public static void encodeDemo() throws UnsupportedEncodingException {
String s = "测试";
//使用GBK编码
byte[] b = s.getBytes("GBK");
//使用ISO8859-1进行解码,就会发生乱码
String s1 = new String(b, "ISO-8859-1");
System.out.println(s1);
//对以上乱码解决方式如下。先获得编解码的字节码数组,然后再对字节数组进行正确的编码和解码,通用方法
//注意:当第一次编码和解码的编码表(GBK和UTF-8)都包含对这个字的对应字节数组值,那么如果再用以下的方式重新编码和解码
// 也还是乱码,因为以上两个编码表(GBK和UTF-8)都包含对这个字的对应数值,当第二次在编码解码,而又他们的对应数值又不
// 一样,所以解码出来还是乱码。所示例子ISO8859-1不包含对汉字的编码和解码。
byte[] b2 = s1.getBytes("ISO8859-1");
System.out.println(Arrays.toString(b2));
String s2 = new String(b2, "GBK");
System.out.println("s2 = " + s2);
}
}