流
1.流的分类
按照方向分类
输入流:从外部设备流向程序的流成为
输出流:程序流向外部设备的流
按照数据单元分类
字节流:以字节为单位,可以读写任意资源 InputStream,OutputStream
字符流:方便处理以unicode形式存储的信息,读写操作是基于两字节的unicode码元。Reader,Writer
按照功能分
节点流
FileInputStream 文件流
ByteArrayInputStream 字节数组流
PipedInputStream 管道流
处理流
InputStreamReader 桥梁流
BufferedReader 缓冲流
DataInputStream 数据流
ObjectInputStream 对象流
SequenceInputStream 合并流
2java中的流类型
操作文件
1.File类
1.构造file对象
/**
* File 文件/文件夹的操作
* 构造File 四种方式
*
*/
static void file() throws URISyntaxException {
File f = new File("D:\\");//传入路径
File f2 = new File(f, "test");//以f为父级路径构建,相当于D:\\test
File f3 = new File("D:\\","test");//与f2类似,只是将路径换成String型
URI uri = new URI("http://docs.oracle.com/javase/9/docs/api/java/io/File.html");
File f4 = new File(uri);//通过uri构建,通常用于网络操作
}
常用的方法
创建方法
(1)boolean createNewFile() //用来创建标准文件的方法
使用File file = new File(path)只是指定了文件创建的路径,但是文件还没有生成,另外如果路径不存在,那么文件将不会创建成功
(2)boolean mkdir() //创建目录:根据File对象的名字(路径)创建一个目录(文件夹),如果是相对目录,则新建的目录在当前目录下
(3)boolean mkdirs() //创建多级目录:如果File对象名字有多级目录,则可以调用该方法一次性创建多级目录
mkdirs()可以建立多级文件夹(目录), mkdir()只能创建一层目录
如:
Filefile = new File("c:/aa");
file.mkdir(); //这样可以在c:/下创建aa目录
假如有多层目录,则不能用mkdir创建,如:
Filefile = new File("c:/aa/bb");
file.mkdir() //这样创建不了.
这样不会建立任何目录, 因为找不到/tmp/one/two目录, 结果返回false
应该改为:mkdirs()
删除方法
(1)boolean delete()
(2)boolean deleteOnExit() //文件使用完成后删除
判断方法
(1)boolean canExecute() //判断文件是否可执行
(2)boolean canRead() //判断文件是否可读
(3)boolean canWrite() //判断文件是否可写
(4)boolean exists() //判断文件是否存在
(5)boolean isDirectory() //判断File对象指向的文件是否为目录,返回一个boolean类型的值,true或者false
(6)boolean isFile() //判断File对象指向的文件是否是标准文件,返回一个boolean类型的值,true或者false
(7)boolean isHidden()
(8)boolean isAbsolute() //判断是否是绝对路径 文件不存在也能判断
获取方法
(1)StringgetName() //获取文件的名字(不带文件的路径),返回的是String类型的值
(2)String getPath()
(3)String getAbsolutePath()
(4)String getParent() //如果没有父目录返回null
(5)long lastModified() //获取最后一次修改的时间
(6)long length() //得到File对象指向文件的长度,以字节计算,返回一个长整形的值(long)
注意:在系统中,文件夹(目录)的大小为零,也就是不占用空间,使用length()时返回的是0
(7)boolean renameTo(File f) //重新命名此抽象名称指定的文件
f-- 新抽象路径名的抽象路径名,如果重命名成功此方法返回true,否则返回false
(8)File[] listRoots() //返回抽象路径名数组,表示在目录中此抽象路径名表示,满足指定过滤器的文件和目录。
(9)String[] list()
(10)String[] list(FilenameFilter filter)
示例
/**
* 需求1:遍历D:\\test下所有文件包括子文件夹
* 方法1----使用递归
* 如果是文件夹就递归调用
*/
static void traverseFolder1(String path) {
File file = new File(path);
if (file.exists()) {//判断file是否存在
File[] files = file.listFiles();//获取file下文件和文件夹,存储到file数组中
if (files.length == 0) {
System.out.println("文件夹是空的!");
return;
} else {
for (File f : files) { //遍历file数组
if (f.isDirectory()) { //判断是否为文件夹
System.out.println("文件夹:" + f.getAbsolutePath());//获取file的绝对路径
traverseFolder1(f.getAbsolutePath());
} else {
System.out.println("文件:" + f.getAbsolutePath());
}
}
}
} else {
System.out.println("文件不存在!");
}
}
/**
* 方法二----不使用递归
* 定义一个linkendlist,保存遍历结果是文件夹的file,到空为止
*/
static void traverseFolder2(String path) {
int fileNum = 0, folderNum = 0;
File file = new File(path);
if (file.exists()) {
LinkedList<File> list = new LinkedList<File>();
File[] files = file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
System.out.println("文件夹 :" + file2.getAbsolutePath());
list.add(file2);
fileNum++;
} else {
System.out.println("文件:" + file2.getAbsolutePath());
folderNum++;
}
}
File temp_file;
while (!list.isEmpty()) {
temp_file = list.removeFirst();
files = temp_file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
System.out.println("文件夹:" + file2.getAbsolutePath());
list.add(file2);
fileNum++;
} else {
System.out.println("文件:" + file2.getAbsolutePath());
folderNum++;
}
}
}
} else {
System.out.println("文件不存在!");
}
System.out.println("文件夹共有:" + folderNum + ",文件共有:" + fileNum);
}
2.文件的简单读写
流是一种资源,我们操作完之后需要自行关闭
public static void main(String[] args) {
try {
// read("D:\\a.txt");
write("D:\\b.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读文件--从文件读到程序
* 1.构造输入流
* 2.定义暂存数组
* 3.读取
* 读取文本类的可用FileReader,二进制文件可用FileInputStream
*/
static void read(String src) throws IOException {
//方法1----------------
FileReader fr = new FileReader(src);
char[] buf = new char[1024];
int c;//用来判断是否可读
String s = "";
while ((c = fr.read(buf)) != -1) {
//做一些处理如复制操作,这里只是打印
s = s + new String(buf);
}
fr.close();
System.out.println("通过字符流:" + s);
//方法2----------------------
FileInputStream fis = new FileInputStream(src);
byte[] b = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = fis.read(b)) != -1) {
sb.append(new String(b, 0, len));
}
fis.close();
System.out.println("通过字节流:" + sb);
}
/**
* 写文件--从程序写到文件
* 构造输出流即可
*/
static void write(String tar) throws IOException {
String str = "哈哈哈";
//方法1--------通过字节写出
FileOutputStream fos = new FileOutputStream(tar);
fos.write(str.getBytes());//还可以自己指定编码Charset.forName("utf-8")
fos.close();
//方法2--------通过字符写出,ture表示在原有内容上添加
FileWriter fw = new FileWriter(tar, true);
fw.write(str);
fw.close();
}
3.包装流
包装流是为了让某种流的功能更强大,可分成两类
1. 主要以过滤器流为主
如BufferedInputStream,BufferedOuputStream
DataInputStream,DataOutputStream
CheckedOutputStream
CipherOutputStream
DataOutputStream
DeflaterOutputStream
DigestOutputStream
PrintStream
…
2 对象流、管道流、扫描器等其他流
//流的包装
FileOutputStream fos=new FileOutputStream("D:\\test.txt");
BufferedOutputStream bos=new BufferedOutputStream(fos);
DataOutputStream dos=new DataOutputStream(bos);
4.RandomAccessFile 随机访问文件
创建该类对象时传入模型(mode r表示只读模式,rw表示读写模式,rws表示每次更新都对数据和元数据的写操作进行同步的读/写模式,rwd每次更新时只对数据写操作进行同步的读/写模式)
该类的几个方法
seek(long pos) ———-将文件指针设置到距文件开头的pos字节处,参数是0-文件的字节长度
getFilePointer ———-返回文件指针位置
length()———————-返回文件长度
做个恰当的比喻,文件转换成流后,就像我们很多人排成了一队然后报数,正常情况依次进行。有了seek方法后,就可以指定从谁开始,到谁结束。
这样就可以实现文件的断点续传,暂停时只需要将位置保留下来,再次读取时从该位置开始即可。
public static void main(String[] args) {
try {
random("D:\\a.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* RandomAccessFile 随机访问文件
*
*/
static void random(String src) throws IOException {
RandomAccessFile raf=new RandomAccessFile( src, "rw");
long l=raf.length();//文件长度
//读操作------
raf.seek(3);//从第三个字节开始读
byte[] b = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while((len=raf.read(b))!=-1){
sb.append(new String(b, 0, len));
System.out.println("当前指针位置:"+raf.getFilePointer());
}
System.out.println(sb.toString());
//写操作-------
String str= "123来";
raf.seek(0);//将内容写在最前面
raf.write(str.getBytes(Charset.forName("utf-8")));//可以指定编码
raf.close();
}
5.zip的操作
/**
* ZIP的操作----解压缩
*/
static void unZip(String srcpath, String tarsrc) throws IOException {
byte[] buffer = new byte[1024];
//create output directory is not exists
File folder = new File(tarsrc);
if (!folder.exists()) {
folder.mkdir();
}
//get the zip file content
ZipInputStream zis =
new ZipInputStream(new FileInputStream(srcpath));
//get the zipped file list entry
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
String fileName = ze.getName();
File newFile = new File(tarsrc + File.separator + fileName);
System.out.println("file unzip : " + newFile.getAbsoluteFile());
//create all non exists folders
//else you will hit FileNotFoundException for compressed folder
new File(newFile.getParent()).mkdirs();
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
System.out.println("Done");
}
/**
* ZIP的操作----压缩
*/
static void zipped(String srcpath, String tarsrc) throws IOException {
File file = new File(srcpath);// 要被压缩的文件夹
File zipFile = new File(tarsrc);//压缩后的位置
InputStream input = null;
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
if(file.isDirectory()){
File[] files = file.listFiles();
for(int i = 0; i < files.length; ++i){
input = new FileInputStream(files[i]);
zipOut.putNextEntry(new ZipEntry(file.getName() + File.separator + files[i].getName()));
int temp = 0;
while((temp = input.read()) != -1){
zipOut.write(temp);
}
input.close();
}
}
zipOut.close();
}
6.对象的序列化和反序列化
序列化是以特殊的文件格式存储对象数据,它包含所有对象的类型和数据域,每个对象都赋予一个序列号;当相同对象重复出现将被存储为对这个对象序列号的引用。
例如字符串对象存为:
74 两字节表示的字符串长度 所有字符
hello ————74 00 05 hello
public static void main(String[] args) {
Tests t = new Tests();
//测试序列化
// Book bk = new Book();
// bk.setId(3);
// bk.setName("8");
// try {
// t.writeobj("D:\\c.txt", bk);
// } catch (IOException e) {
// e.printStackTrace();
// }
//测试反序列化
try {
Book bk1 = (Book) t.readobj("D:\\c.txt", Class.forName("com.xxx.Book"));//或者Book.class
System.out.println(bk1.getName());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 对象流与序列化
* 可以将一个对象写入流中,然后读回
* tarpath 保存的路径如 D:\b.txt
* obj 需要序列化的对象引用 该类需实现Serializable接口
*/
<T> void writeobj(String tarpath, T t) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(tarpath));
oos.writeObject(t);
oos.close();
}
/**
* 反序列化
* 将文件转换成对象
* srcpath 序列化文件的路径
* t 反序列化后的类型
* 改方法是一个泛型方法
*/
<T> T readobj(String srcpath, T t) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(srcpath));
t = (T) ois.readObject();
ois.close();
return t;
}
Book类
import java.io.Serializable;
public class Book implements Serializable{
private int id;
private String name;
//省略get,set...
}
本文示例源码:http://download.csdn.net/download/qq_29423883/10001011