您的位置:首页 > Web前端

Java I/O流(二)——File,Properties,PrintWriter,IO ,RandomAccessFile,ByteBuffer,nio

2017-04-17 20:57 696 查看

File概述

文件的操作是非常重要的,我们先来看下他的基本概念

•用于将文件或者文件夹封装成对象

•方便对文件和文件夹的操作

•File对象可以作为参数传递给流的构造函数

我们写个小例子先

import java.io.File;

public class HelloJJAVA {
public static void main(String[] args) {
// 创建File对象,不存在也没事
File file = new File("a.txt");
//目录 文件名
File file2 = new File("F:\\isblog\\Demo","a.txt");

//封装什么就打印什么
System.out.println(file);
}
}


其实就是一个类的使用

二.创建删除

是文件肯定有操作方法

•1.创建

•2.删除

•3.判断

•4.获取信息

1.创建

import java.io.File;
import java.io.IOException;

public class HelloJJAVA {
public static void main(String[] args) {
// 创建File对象
File file = new File("a.txt");

try {
//创建
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


在指定的位置创建文件,如果文件已经存在,就不创建,并且返回false,和输出流不一样,输出流对象已建立文件,文件就已经存在,会覆盖

2.删除

删除我就不说了,直接这样

file.delete();

他还有一个方法比较好玩

file.deleteOnExit();

在程序退出之后删除文件

三.判断文件存在

判断文件是否存在

import java.io.File;
import java.io.IOException;

public class HelloJJAVA {
public static void main(String[] args) {
// 创建File对象
File file = new File("a.txt");
// 判断是否存在,不存在则创建
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}


这样我们就可以去判断文件是否存在且不存在就去创建文件了。

四.创建文件夹

我们继续来看怎么去创建文件夹,其实也很简单

import java.io.File;

public class HelloJJAVA {
public static void main(String[] args) {
// 创建File对象
File file = new File("liuguilin");
file.mkdir();
}
}


OK,这样的话,就创建了,这里注意mkdir只能创建一级目录,而mkdirs可以创建多级文件夹目录

五.判断是否为文件/文件夹

有时候还是需要的

import java.io.File;

public class HelloJJAVA {
public static void main(String[] args) {
File file = new File("liuguilin");
//是否为文件
System.out.println(file.isFile());
//是否为文件夹
System.out.println(file.isDirectory());
}
}


他返回的是boolean值来确定是否存在,但是这里也要记住,就是一定要确定这个文件是否存在,所以我们的流程可以这样写

import java.io.File;
import java.io.IOException;

public class HelloJJAVA {
public static void main(String[] args) {
File file = new File("liuguilin");
// 判断文件是否存在
if (file.exists()) {
// 再去判断文件还是文件夹
if (file.isFile()) {
System.out.println("文件");
} else if (file.isDirectory()) {
System.out.println("文件夹");
}
} else {
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}


这样逻辑是比较清晰的

六.获取信息

获取的话,我们是怎么去获取信息的呢?毫无疑问,是get,比如getNmae之类的,我们用代码里的注释来说明是比较好的

import java.io.File;

public class HelloJJAVA {
public static void main(String[] args) {
File file = new File("liuguilin.txt");
File file2 = new File("haha.txt");
// 项目路径下+文件名
System.out.println("路径:" + file.getPath());
// 全路径
System.out.println("绝对路径:" + file.getAbsolutePath());
// 最后一次修改时间
System.out.println("时间:" + file.lastModified());
// 绝对路径中的文件父目录,如果是相对路径,返回的为空
System.out.println("父目录:" + file.getParent());
// 把内容拷贝到另一个文本中并且删除自身
System.out.println(file.renameTo(file2));
}
}


七.文件列表

列出可用的系统目录,我们看代码

import java.io.File;

public class HelloJJAVA {
public static void main(String[] args) {
File[] listRoots = File.listRoots();
for (File f : listRoots) {
// 打印磁盘目录
System.out.println(f);
}
}
}


这样我们就可以得到有效盘符了

我们可以进行改进,我们打印C盘下的所有文件

import java.io.File;

public class HelloJJAVA {
public static void main(String[] args) {
//必须封装了一个目录,该目录还必须存在
File f = new File("c:\\");
String[] list = f.list();
for (String fi : list) {
System.out.println(fi);
}
}
}


得到的肯定就是所有文件的列表咯

八.文件过滤

我们做文件夹的时候经常会用到的一个小知识点,就是过滤文件

import java.io.File;
import java.io.FilenameFilter;

public class HelloJJAVA {
public static void main(String[] args) {
File f = new File("c:\\");
String[] list = f.list(new FilenameFilter() {
// 过滤
@Override
public boolean accept(File dir, String name) {
// 只返回txt后缀的文件
return name.endsWith(".txt");
}
});
for (String fi : list) {
// 过滤
System.out.println(fi);
}
}

}


九.文件递归

import java.io.File;

public class HelloJJAVA {
public static void main(String[] args) {

File dir = new File("E:\\AndroidDelepoer");

showDir(dir);
}

private static void showDir(File dir) {
System.out.println("目录:" + dir);
File[] fils = dir.listFiles();
for (int i = 0; i < fils.length; i++) {
if (fils[i].isDirectory()) {
showDir(fils[i]);
} else {
// 列出根目录
System.out.println("files" + fils);
}
}

}
}


Properties

private static void loadDemo(){
try {
FileInputStream fish = new FileInputStream("info.txt");
Properties properties = new Properties();
//将流中的数据加载进集合
properties.load(fish);
System.out.println(properties);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}


打印流PrintWriter

•该流提供了打印方法,可以将各种数据类型原样打印

◦file对象 File

◦字符串路径 String

◦字节打印流

◦字符打印流

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class HelloJJAVA {
public static void main(String[] args) {

try {
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System.in));

PrintWriter oWriter = new PrintWriter(System.out, true);
String line = null;
while ((line = bufr.readLine()) != null) {
if (line.equals("over")) {
break;
}
oWriter.write(line);
}
oWriter.close();
bufr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


合并流

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

public class HelloJJAVA {
public static void main(String[] args) {
try {
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("1.txt"));
v.add(new FileInputStream("2.txt"));
Enumeration<FileInputStream> elements = v.elements();
SequenceInputStream sis = new SequenceInputStream(elements);

FileOutputStream fos = new FileOutputStream("3.txt");

byte[] buf = new byte[1024];
int len = 0;
while ((len = sis.read(buf)) != -1) {
fos.write(buf, 0, len);
}

fos.close();
sis.close();

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

//把1.txt和2.txt乃至add更多的内容合并到3.txt文件中,这就是流的合并


切割文件

// 切割文件
public static void splitFile() {
try {
FileInputStream fis = new FileInputStream("1.jpg");
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++) + ".patch");
fos.write(buf, 0, len);
fos.close();
}

fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


切割完我们可以合并了

// 合并文件
public static void merge() {
ArrayList<FileInputStream> al = new ArrayList<>();
for (int i = 1; i <= 2; i++) {
try {
al.add(new FileInputStream(i + ".patch"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Iterator<FileInputStream> iterator = al.iterator();
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {

@Override
public boolean hasMoreElements() {
// TODO Auto-generated method stub
return iterator.hasNext();
}

@Override
public FileInputStream nextElement() {
// TODO Auto-generated method stub
return iterator.next();
}

};
try {
SequenceInputStream seq = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("2.jpg");

byte[] buf = new byte[1024];

int len = 0;

while ((len = seq.read(buf)) != -1) {
fos.write(buf, 0, len);
}

fos.close();
seq.close();

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


小结:

1.1

ByteArrayInputStream – 把内存中的一个缓冲区作为 InputStream 使用 .

construct—

(A)ByteArrayInputStream(byte[]) 创建一个新字节数组输入流( ByteArrayInputStream ),它从指定字节数组中读取数据( 使用 byte 作为其缓冲区数组)

(B)—ByteArrayInputStream(byte[], int, int) 创建一个新字节数组输入流,它从指定字节数组中读取数据。

—mark:: 该字节数组未被复制。

1.2

StringBufferInputStream – 把一个 String 对象作为 InputStream .

construct—

StringBufferInputStream(String) 据指定串创建一个读取数据的输入流串。

注释:不推荐使用 StringBufferInputStream 方法。 此类不能将字符正确的转换为字节。

同 JDK 1.1 版中的类似,从一个串创建一个流的最佳方法是采用 StringReader 类。

1.3

FileInputStream – 把一个文件作为 InputStream ,实现对文件的读取操作

construct—

(A)FileInputStream(File name) 创建一个输入文件流,从指定的 File 对象读取数据。

(B)FileInputStream(FileDescriptor) 创建一个输入文件流,从指定的文件描述器读取数据。

(C)-FileInputStream(String name) 创建一个输入文件流,从指定名称的文件读取数据。

method —- read() 从当前输入流中读取一字节数据。

read(byte[]) 将当前输入流中 b.length 个字节数据读到一个字节数组中。

read(byte[], int, int) 将输入流中 len 个字节数据读入一个字节数组中。

1.4

PipedInputStream :实现了 pipe 的概念,主要在线程中使用 . 管道输入流是指一个通讯管道的接收端。

一个线程通过管道输出流发送数据,而另一个线程通过管道输入流读取数据,这样可实现两个线程间的通讯。

construct—

PipedInputStream() 创建一个管道输入流,它还未与一个管道输出流连接。

PipedInputStream(PipedOutputStream) 创建一个管道输入流 , 它已连接到一个管道输出流。

1.5

SequenceInputStream :把多个 InputStream 合并为一个 InputStream . “序列输入流”类允许应用程序把几个输入流连续地合并起来,

并且使它们像单个输入流一样出现。每个输入流依次被读取,直到到达该流的末尾。

然后“序列输入流”类关闭这个流并自动地切换到下一个输入流。

construct—

SequenceInputStream(Enumeration) 创建一个新的序列输入流,并用指定的输入流的枚举值初始化它。

SequenceInputStream(InputStream, InputStream) 创建一个新的序列输入流,初始化为首先 读输入流 s1, 然后读输入流 s2 。

Java IO 的一般使用原则 :

一、按数据来源(去向)分类:

1 、是文件: FileInputStream, FileOutputStream, ( 字节流 )FileReader, FileWriter( 字符 )

2 、是 byte[] : ByteArrayInputStream, ByteArrayOutputStream( 字节流 )

3 、是 Char[]: CharArrayReader, CharArrayWriter( 字符流 )

4 、是 String: StringBufferInputStream, StringBufferOuputStream ( 字节流 )StringReader, StringWriter( 字符流 )

5 、网络数据流: InputStream, OutputStream,( 字节流 ) Reader, Writer( 字符流 )

二、按是否格式化输出分:

1 、要格式化输出: PrintStream, PrintWriter

三、按是否要缓冲:

1 、要缓冲: BufferedInputStream, BufferedOutputStream,( 字节流 ) BufferedReader, BufferedWriter( 字符流 )

四、按数据格式分

1 、二进制格式(只要不能确定是纯文本的) : InputStream, OutputStream 及其所有带 Stream 结束的子类

2 、纯文本格式(含纯英文与汉字或其他编码方式); Reader, Writer 及其所有带 Reader, Writer 的子类

五、按输入输出分:

1 、输入: Reader, InputStream 类型的子类

2 、输出: Writer, OutputStream 类型的子类

六、特殊需要

1 、从 Stream 到 Reader,Writer 的转换类: InputStreamReader, OutputStreamWriter

2 、对象输入输出: ObjectInputStream, ObjectOutputStream

3 、进程间通信: PipeInputStream, PipeOutputStream, PipeReader, PipeWriter

4 、合并输入: SequenceInputStream

5 、更特殊的需要: PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader

RandomAccessFile

利用RandomAccessFile实现文件的多线程下载,即多线程下载一个文件时,将文件分成几块,每块用不同的线程进行下载。下面是一个利用多线程在写文件时的例子,其中预先分配文件所需要的空间,然后在所分配的空间中进行分块,然后写入:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
* 测试利用多线程进行文件的写操作
*/
public class Test {

public static void main(String[] args) throws Exception {
// 预分配文件所占的磁盘空间,磁盘中会创建一个指定大小的文件
RandomAccessFile raf = new RandomAccessFile("D://abc.txt", "rw");
raf.setLength(1024*1024); // 预分配 1M 的文件空间
raf.close();

// 所要写入的文件内容
String s1 = "第一个字符串";
String s2 = "第二个字符串";
String s3 = "第三个字符串";
String s4 = "第四个字符串";
String s5 = "第五个字符串";

// 利用多线程同时写入一个文件
new FileWriteThread(1024*1,s1.getBytes()).start(); // 从文件的1024字节之后开始写入数据
new FileWriteThread(1024*2,s2.getBytes()).start(); // 从文件的2048字节之后开始写入数据
new FileWriteThread(1024*3,s3.getBytes()).start(); // 从文件的3072字节之后开始写入数据
new FileWriteThread(1024*4,s4.getBytes()).start(); // 从文件的4096字节之后开始写入数据
new FileWriteThread(1024*5,s5.getBytes()).start(); // 从文件的5120字节之后开始写入数据
}

// 利用线程在文件的指定位置写入指定数据
static class FileWriteThread extends Thread{
private int skip;
private byte[] content;

public FileWriteThread(int skip,byte[] content){
this.skip = skip;
this.content = content;
}

public void run(){
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile("D://abc.txt", "rw");
raf.seek(skip);
raf.write(content);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
raf.close();
} catch (Exception e) {
}
}
}
}

}


Java IO的RandomAccessFile的使用 :http://blog.csdn.net/czplplp_900725/article/details/37809579

nio

nio 是non-blocking的简称,在jdk1.4 里提供的新api 。Sun 官方标榜的特性如下: 为所有的原始类型提供(Buffer)缓存支持。字符集编码解码解决方案。 Channel :一个新的原始I/O 抽象。 支持锁和内存映射文件的文件访问接口。 提供多路(non-bloking) 非阻塞式的高伸缩性网络I/O 。

Java NIO流 – 缓冲区(Buffer,ByteBuffer):http://www.cnblogs.com/youngKen/p/4923635.html

ByteBuffer

每个Buffer都有以下的属性:

byte[] buff

buff即内部用于缓存的数组。

position

当前读取的位置。

mark

为某一读过的位置做标记,便于某些时候回退到该位置。

capacity

初始化时候的容量。

limit

读写的上限,limit<=capacity。

eg:

public static void main(String [] args)
throws IOException
{
// 创建一个capacity为256的ByteBuffer
ByteBuffer buf = ByteBuffer.allocate(256);
while (true) {
// 从标准输入流读入一个字符
int c = System.in.read();
// 当读到输入流结束时,退出循环
if (c == -1)
break;
// 把读入的字符写入ByteBuffer中
buf.put((byte) c);
// 当读完一行时,输出收集的字符
if (c == '\n') {
// 调用flip()使limit变为当前的position的值,position变为0,
// 为接下来从ByteBuffer读取做准备
buf.flip();
// 构建一个byte数组
byte [] content = new byte[buf.limit()];
// 从ByteBuffer中读取数据到byte数组中
buf.get(content);
// 把byte数组的内容写到标准输出
System.out.print(new String(content));
// 调用clear()使position变为0,limit变为capacity的值,
// 为接下来写入数据到ByteBuffer中做准备
buf.clear();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: