标签 : Java编程思想
对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统一项艰难的任务。
I/O系统不仅要与各种终端打交道,比如输入输出终端,网络连接,文件系统等,并且还需要多种方式,比如顺序,缓冲,二进制等。
Java中提供了大量的类来实现文件操作。
如果缺乏历史的眼光,很快我就会对什么时候该使用哪些类,以及什么时候不该使用他们而搞到迷惑。
File这个名字并非指代文件,它既能代表一个特定的文件,又能代表一个目录下的文件集合。如果指代的是文件集合的话,可以调用list()方法得到一个包含该目录下文件集合的数组。
查看一个目录列表,可以有两种方法使用File对象:
* 调用不带参数的list()方法获取全部文件集合;
* 使用“过滤器”获得特定类型文件的文件集合。
package com.io;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;
/**
* @author [email protected]
* @since 13:34 2018/7/18
*/
public class DirList {
public static void main(String[] args) {
File path = new File(".");
String[] list;
if (args.length == 0) {
list = path.list();
} else {
list = path.list(new DirFilter(args[0]));
}
assert list != null;
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
for (String dir : list) {
System.out.println(dir);
}
}
}
class DirFilter implements FilenameFilter {
private Pattern pattern;
public DirFilter(String regex) {
pattern = Pattern.compile(regex);
}
@Override
public boolean accept(File dir, String name) {
return pattern.matcher(name).matches();
}
}
output:
.idea
.vscode
out
ThinkInJavaDemo
Process finished with exit code 0
匿名内部类改写:
package com.io;
import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.Pattern;
/**
* @author [email protected]
* @since 13:53 2018/7/18
*/
public class DirListA {
public static FilenameFilter filenameFilter(final String regex) {
return new FilenameFilter() {
private Pattern pattern = Pattern.compile(regex);
@Override
public boolean accept(File dir, String name) {
return pattern.matcher(name).matches();
}
};
}
public static void main(String[] args) {
/**
* do something.
*/
}
}
为了减少DirList类与FilenameFilter类之间的耦合,可以改写如下:
package com.io;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;
/**
* @author [email protected]
* @since 13:58 2018/7/18
*/
public class DirListB {
public static void main(String[] args) {
File path = new File(".");
String[] list;
if (args.length == 0) {
list = path.list();
} else {
list = path.list((dir, name) -> {
Pattern pattern = Pattern.compile(args[0]);
return pattern.matcher(name).matches();
});
}
assert list != null;
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
for (String dir : list) {
System.out.println(dir);
}
}
}
文件操作在实际开发中是非常常用的,有一个实用的文件工具类会大大提高开发效率。
下面的方法通过一个特定的正则表达式使用local()方法和walk()方法产生特定目录下的整个目录书中的所有文件构成List。
File.listFiles()产生File数组。
可以使用File对象来表示已经存在的文件或者路径,也可以用来创建新的目录或文件。一些File类的常用方法:
Java中“流”类库让人迷惑的主要原因就在于:创建单一的结果流,却需要创建多个对象。
InputStream的作用是用来表示那些从不同数据源产生的输入的类。
InputStream类型:
类 | 功能 | 构造参数及使用 |
---|---|---|
ByteArrayInputStream | 允许将内存的缓冲区当做InputStream使用 | 缓冲区,字节将从中取出,作为一种数据源,将其与FilterInputStream对象相连以提供有用接口 |
StringBufferInputStream | 将String转换成InputStream | 底层实际使用StringBuffer作为数据源,将其与FilterInputStream对象相连以提供有用接口 |
FileInputStream | 用于从文件读取信息 | 字符串表示文件名,文件或FileDescriptor对象 |
PipedInputStream | 产生用于写入相关PipedOutputStream的数据 | PipedOutputStream作为多线程数据源,将其与FilterInputStream对象相连以提供有用接口 |
FilterInputStream | 抽象类,作为“装饰器”的接口,为其他InputStream类提供有用功能 | 。。 |
OutputStream类型:
类 | 功能 | 构造参数及使用 |
---|---|---|
ByteOutputStream | 在内存中创建缓冲区,数据的暂时存储区域 | 缓冲区初始化大小,制定数据的目的地,将其与FilterOutputStream对象相连以提供有用接口 |
FileOutputStream | 用于将信息写至文件 | 字符串表示文件名,文件或者FileDescriptor对象,将其与FilterOutputStream对象相连以提供有用接口 |
FilterOutputStream | 抽象类,作为“装饰器”的接口,为其他OutputStream提供有用功能 | 。。 |
FilterInputStream类型:
类 | 功能 | 构造器和参数 |
---|---|---|
DataInputStream | 与DataOutputStream搭配使用 | InputStream包含用于读取本类型数据的全部接口 |
BufferedInputStream | 可以防止每次读取时都进行实际写操作,代表使用“缓冲区” | InputStream,可以指定缓冲区大小 |
LineNumberInputStream | 跟踪输入流中的行号,可调用getLineNumber()和setLineNumber(int) | 仅增加了行号 |
PushbackInputStream | 具有“能弹出一个字节的缓冲区”因此可以将读到的最后一个字节回退 | 通常作为编译器的扫描器,存在的原因是因为Java编译器的需要,极不常用 |
FilterOutputStream类型:
类型 | 功能 | 构造参数及使用 |
---|---|---|
DataOutputStream | 与DataInputStream搭配使用 | OutputStream包含用于写入基本类型数据的全部接口 |
PrintStream | 用于产生格式化输出,其中DataOutputStream处理数据的存储,PrintStream处理显示 | OutputStream,可以用boolean值只是是否在每次换行时都清空缓冲区应该是对OutputStream对象的final封装,可能会经常使用到他 |
BufferedOutputStream | 使用它以避免每次发送数据时都要进行实际的写操作,代表“使用缓冲区”,可以调用flush()清空缓冲区 | OutputStream可以指定缓冲区大小,本质上不提供接口,只不过是向进程中添加缓冲区所必须的,与接口对象搭配 |
来源 | 去处 |
---|---|
InputStream | OutputStream |
FileInputStream | FileOutputStream |
StringBufferInputStream | StringBufferOutputStream |
ByteArrayInputStream | ByteOutputStream |
PipedInputStream | PipedOutputStream |
package com.io;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
* @author [email protected]
* @since 21:22 2018/7/18
*/
public class BufferedInputFile {
public static String read(String fileName) throws IOException {
BufferedReader in = new BufferedReader(new FileReader(fileName));
String s;
StringBuilder stringBuilder = new StringBuilder();
while ((s = in.readLine()) != null) {
stringBuilder.append(s).append("\n");
}
in.close();
return stringBuilder.toString();
}
public static void main(String[] args) throws IOException {
System.out.println(read("BufferedInputFile.java"));
}
}
package com.io;
import java.io.IOException;
import java.io.StringReader;
/**
* @author [email protected]
* @since 21:28 2018/7/18
*/
public class FormattedMemoryInput {
public static void main(String[] args) throws IOException {
StringReader in = new StringReader(BufferedInputFile.read("demo.java"));
int c;
while ((c = in.read()) != -1) {
System.out.println((char) c);
}
}
}
package com.io;
import java.io.*;
/**
* @author [email protected]
* @since 21:32 2018/7/18
*/
public class TestEOF {
public static void main(String[] args) throws IOException {
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("")));
while (in.available() != 0) {
System.out.println((char) in.readByte());
}
}
}
package com.io;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
/**
* @author [email protected]
* @since 21:35 2018/7/18
*/
public class BasicFileOutput {
static String file = "BasicFileOutput.out";
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new StringReader(BufferedInputFile.read("")));
PrintWriter out = new PrintWriter(file);
int lineCount = 1;
String s;
while ((s = in.readLine()) != null) {
out.println(lineCount++ + ":" + s);
}
out.close();
System.out.println(BufferedInputFile.read(file));
}
}