File
相关类
- RandomAccessFile:独立的随机访问文件读写类。
示例:列出文件夹中的目录
public static void main(String[] args) {
final String reg = "W.*";
File path = new File("C:\\Software\\");
String[] list = path.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return Pattern.compile(reg).matcher(name).matches();
}
});
assert list != null;
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
for (String dirItem : list) {
System.out.println(dirItem);
}
}
InputStream和OutputStream
-
InputStream和OutputStream
面向字节 (二进制)。
InputStream
-
ByteArrayInputStream
:内存缓冲区作为InputStream
-
StringBufferInputStream
(弃用):String作为InputStream
-
FileInputStream
:文件作为InputStream
-
PipedInputStream
:管道,用于多线程
-
SequenceInputStream
:组合多个InputStream
-
ObjectInputStream
:用于对象序列化
-
FilterInputStream
(修饰器,可同时组合多个修饰器)包含:
-
DataInputStream
:其中的readLine方法已弃用
BufferedInputStream
-
LineNumberInputStream
:针对Java编写编译器
-
PushbackInputStream
:针对Java编写编译器
OutputStream
-
ByteArrayOutputStream
:内存缓冲区作为OutputStream
-
FileOutputStream
:文件作为OutputStream
-
PipedOutputStream
:管道,用于多线程
-
ObjectOutputStream
:用于对象序列化
-
FilterOutputStream
(修饰器,可同时组合多个修饰器)包含:
DataOutputStream
PrintStream
BufferedOutputStream
Stream适配器
-
InputStreamReader
:将InputStream转换成Reader。
-
OutputStreamWriter
:将OutputStream转换成Writer。
注意事项
- 要使用
readLine()
时,选择BufferedReader
而不是DataOutputStream
。
Reader和Writer
Reader
FileReader
StringReader
-
PipedReader
:管道,用于多线程
CharArrayReader
-
FilterReader
(修饰器,可同时组合多个修饰器)包含:
BufferedReader
LineNumberReader
PushbackReader
Writer
FileWriter
-
PrintWriter
:构造器接受一个String类型文件名。
StringWriter
-
PipedWriter
:管道,用于多线程
CharArrayWriter
-
FilterWriter
(修饰器,可同时组合多个修饰器)包含:
BufferedWriter
PrintWriter
文件读写示例
1. 字符串 to 文件
public class BufferedInputFile {
private static String read(String filename) throws IOException {
BufferedReader in = new BufferedReader(new FileReader(filename));
String s;
StringBuilder sb = new StringBuilder();
while ((s = in.readLine()) != null) {
sb.append(s).append("\n");
}
in.close();
return sb.toString();
}
public static void main(String[] args) throws IOException {
System.out.print(read("src\\BufferedInputFile.java"));
}
}
2. 文件 to 字符串
public class BasicFileOutput {
public static void main(String[] args) throws IOException {
String file = "src\\BasicFileOutput.out";
BufferedReader in = new BufferedReader(
new StringReader(BufferedInputFile.read("src\\BasiclileOutput.java")));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
int lineCount = 1;
String s;
while ((s = in.readLine()) != null) {
out.println(lineCount++ + ": " + s);
}
out.close();
}
}
3. 内存读写
public class MemoryInput {
public static void main(String[] args) throws IOException {
StringReader in = new StringReader("我是内存中的数据! ");
int c;
while ((c = in.read()) != -1) {
System.out.print((char) c);
}
}
}
4. 格式化读写
public class StoringAndRecoveringData {
public static void main(String[] args) throws IOException {
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("Data.txt")));
out.writeDouble(3.14159);
out.writeUTF("That was pi");
out.writeDouble(1.41413);
out.writeUTF("Square root of 2");
out.close();
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("Data.txt")));
System.out.println(in.readDouble());
System.out.println(in.readUTF());
System.out.println(in.readDouble());
System.out.println(in.readUTF());
}
}
5. 随机读写
public class UsineandsmAccessFile {
private static String file = "src\\rtest.dat";
private static void display() throws IOException {
RandomAccessFile rf = new RandomAccessFile(file, "r");
for (int i = 0; i < 7; i++) {
System.out.println("Value " + i + ": " + rf.readDouble());
}
System.out.println(rf.readUTF());
rf.close();
}
public static void main(String[] args) throws IOException {
// 写入并输出文件
RandomAccessFile rf = new RandomAccessFile(file, "rw");
for (int i = 0; i < 7; i++) {
rf.writeDouble(i * 1.414);
}
rf.writeUTF("The end of the file");
rf.close();
display();
// 修改并输出文件
rf = new RandomAccessFile(file, "rw");
// 跳过5个8字节(double)的数据
rf.seek(5 * 8);
rf.writeDouble(333.0001);
rf.close();
display();
}
}
6. 检查文件结尾
public class TestEOF {
public static void main(String[] args) throws IOException {
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("src\\TestEOF.java")));
while (in.available() != 0) {
System.out.print((char) in.readByte());
}
}
}
标准I/O
主要内容
- 标准I/O包括:System.in、System.out、System.err。
- System类的三个重定向静态方法:
setIn(InputStream)
、setOut(PrintStream)
、setErr(PrintStream)
标准I/O重定向示例
public class Redirecting {
public static void main(String[] args) throws IOException {
// 存储标准I/O
InputStream sIn = System.in;
PrintStream sOut = System.out;
PrintStream sErr = System.err;
BufferedInputStream in = new BufferedInputStream(new FileInputStream("src//Redirecting.java"));
PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream("test.out")));
// 重定向标准I/O
System.setIn(in);
System.setOut(out);
System.setErr(out);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s;
while ((s = br.readLine()) != null) {
System.out.println(s);
}
out.close();
// 恢复标准I/O
System.setIn(sIn);
System.setOut(sOut);
System.setErr(sErr);
}
}
启动进程示例
public class OSExecute {
public static void main(String[] args) {
try {
String command = "C:\\Software\\WeChat\\WeChat.exe";
new ProcessBuilder(command.split(" ")).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
通道
简介
简单示例
public class GetChannel {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
FileChannel fc = new FileOutputStream("data.txt").getChannel();
fc.write(ByteBuffer.wrap("Some text ".getBytes()));
fc.close();
fc = new RandomAccessFile("data.txt", "rw").getChannel();
fc.position(fc.size());
fc.write(ByteBuffer.wrap("Some more".getBytes()));
fc.close();
fc = new FileInputStream("data.txt").getChannel();
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
fc.read(buff);
// 调用ByteBuffer.flip(),让ByteBuffer从写模式转变为读模式(读变写不需要调用)
buff.flip();
while (buff.hasRemaining()) {
System.out.print((char) buff.get());
}
buff.clear();
}
}
使用通道复制文件
方式一
public class ChannelCopy {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.out.println("arguments: sourcefile destfile");
System.exit(1);
}
FileChannel in = new FileInputStream(args[0]).getChannel();
FileChannel out = new FileOutputStream(args[1]).getChannel();
ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
while (in.read(buffer) != -1) {
buffer.flip();
out.write(buffer);
buffer.clear();
}
}
}
方式二
public class TransferTo {
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.out.println("arguments: sourcefile destfile");
System.exit(1);
}
FileChannel in = new FileInputStream(args[0]).getChannel();
FileChannel out = new FileOutputStream(args[1]).getChannel();
in.transferTo(0, in.size(), out);
// or:
// out.transferFrom(in, 0, in.size());
}
}
文件通道加锁
描述
-
FileChannel.tryLock()
:非阻塞,不一定能获取到。
-
FileChannel.lock()
:阻塞,阻塞直至获取到。
-
SocketChannel
、DatagramChannel
、ServerSocketChannel
不需要加锁。
简单示例
public class FileLocking {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("file.txt");
FileLock fileLock = fos.getChannel().tryLock();
if (fileLock != null) {
TimeUnit.MILLISECONDS.sleep(100);
fileLock.release();
}
fos.close();
}
}
字符编码
字符编解码
public class BufferToText {
private static final int BSIZE = 1024;
public static void main(String[] args) throws Exception {
// 使用UTF-8编码输入(因为源代码是UTF-8)
FileChannel fc = new FileOutputStream("data2.txt").getChannel();
fc.write(ByteBuffer.wrap("Some text".getBytes()));
fc.close();
// 使用UTF-16编码输出(因为ByteBuffer.asCharBuffer()用的是Java原生编码UTF-16)
fc = new FileInputStream("data2.txt").getChannel();
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
fc.read(buff);
buff.flip();
System.out.println("1: " + buff.asCharBuffer());
buff.rewind();
// 使用UTF-8编码输出
String encoding = System.getProperty("file.encoding");
System.out.println("2: Decoded using " + encoding + ": "
+ Charset.forName(encoding).decode(buff));
buff.clear();
// ======================================================================
// 使用UTF-16编码字符串
fc = new FileOutputStream("data2.txt").getChannel();
fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16")));
fc.close();
// 使用UTF-16编码输出(因为ByteBuffer.asCharBuffer()用的是Java原生编码UTF-16)
fc = new FileInputStream("data2.txt").getChannel();
fc.read(buff);
buff.flip();
System.out.println("3:" + buff.asCharBuffer());
// ======================================================================
// 使用UTF-16编码输入(因为ByteBuffer.asCharBuffer()用的是Java原生编码UTF-16)
fc = new FileOutputStream("data2.txt").getChannel();
buff = ByteBuffer.allocate(24);
buff.asCharBuffer().put("Some text");
fc.write(buff);
fc.close();
// 使用UTF-16编码输出(因为ByteBuffer.asCharBuffer()用的是Java原生编码UTF-16)
fc = new FileInputStream("data2.txt").getChannel();
buff.clear();
fc.read(buff);
buff.flip();
System.out.println("4:" + buff.asCharBuffer());
}
}
输出所有的字符编码
public class AvailableCharSets {
public static void main(String[] args) {
SortedMap charSets = Charset.availableCharsets();
for (String csName : charSets.keySet()) {
System.out.print(csName);
// 输出别名
Iterator aliases = charSets.get(csName).aliases().iterator();
if (aliases.hasNext()) {
System.out.print(": ");
}
while (aliases.hasNext()) {
System.out.print(aliases.next());
if (aliases.hasNext()) {
System.out.print(", ");
}
}
System.out.println();
}
}
}
Buffer
ByteBuffer
简单示例
public class ByteBufferDemo {
private static final int BSIZE = 1024;
public static void main(String[] args) {
ByteBuffer bb = ByteBuffer.allocate(BSIZE);
// 使用UTF-16编码
bb.asCharBuffer().put("Howdy!");
char c;
while ((c = bb.getChar()) != 0) {
System.out.print(c + " ");
}
System.out.println();
bb.rewind();
bb.asShortBuffer().put((short) 471142);
System.out.println(bb.getShort());
bb.rewind();
bb.asIntBuffer().put(99471142);
System.out.println(bb.getInt());
bb.rewind();
bb.asLongBuffer().put(99471142);
System.out.println(bb.getLong());
bb.rewind();
bb.asFloatBuffer().put(99471142);
System.out.println(bb.getFloat());
bb.rewind();
bb.asDoubleBuffer().put(99471142);
System.out.println(bb.getDouble());
}
}
注意事项
其他Buffer
public class IntBufferDemo {
private static final int BSIZE = 1024;
public static void main(String[] args) {
ByteBuffer bb = ByteBuffer.allocate(BSIZE);
IntBuffer ib = bb.asIntBuffer();
ib.put(new int[]{11, 42, 47, 99, 143, 811, 1016});
// 获取索引为3的元素
System.out.println(ib.get(3));
// 用1811的覆盖索引为3的元素
ib.put(3, 1811);
ib.flip();
while (ib.hasRemaining()) {
int i = ib.get();
System.out.println(i);
}
}
}
MappedByteBuffer
-
MappedByteBuffer
:用于内存映射,可以将原来太大放不进内存的数据放进内存。
public class MappedByteBufferDemo {
private static final int length = 100000;
public static void main(String[] args) throws Exception {
FileChannel fileChannel = new RandomAccessFile("test.dat", "rw").getChannel();
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, length);
for (int i = 0; i < length; i++) {
mappedByteBuffer.put((byte) 'x');
}
System.out.println("Finished writing");
for (int i = length / 2; i < length / 2 + 6; i++) {
System.out.println((char) mappedByteBuffer.get(i));
}
}
}
压缩
相关的类
-
CheckedInputStream
:为InputStream产生校检。
-
CheckedOutputStream
:为OutputStream产生校检。
-
DeflaterOutputStream
:压缩类的基类。
-
ZipOutputStream
:压缩为Zip格式。
-
GZIPOutputStream
:压缩为GZIP格式。
-
InflaterInputStream
:解压缩类的基类。
-
ZipInputStream
:解压缩为Zip格式。
-
GZIPInputStream
:解压缩为GZIP格式。
GZIP示例
public class GZIPCompress {
public static void main(String[] args) throws IOException {
if (args.length == 0) {
System.out.println("Usage: \nGZlPcompress file\n" + "\tUses GZIP compression to compress " + "the file to test.gz");
System.exit(1);
}
// 写入到GZIPOutputStream就是压缩
BufferedReader in = new BufferedReader(new FileReader(args[0]));
BufferedOutputStream out = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream("test.gz")));
System.out.println("Writing file");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
in.close();
out.close();
// 从GZIPOutputStream读取就是解压缩
System.out.println("Reading file");
BufferedReader in2 = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream("test.gz"))));
String s;
while ((s = in2.readLine()) != null) {
System.out.println(s);
}
}
}
Zip示例
public class ZipCompress {
public static void main(String[] args) throws IOException {
// ============================压缩============================
// 构建输出流
FileOutputStream fileOut = new FileOutputStream("test.zip");
CheckedOutputStream checkedOut = new CheckedOutputStream(fileOut, new Adler32());
ZipOutputStream zipOut = new ZipOutputStream(checkedOut);
BufferedOutputStream buffOut = new BufferedOutputStream(zipOut);
// 设置zip的注释
zipOut.setComment("A test of Java Zipping");
// 压缩多个文件
for (String arg : args) {
System.out.println("Writing file " + arg);
BufferedReader in = new BufferedReader(new FileReader(arg));
// 每压缩一个文件调用ZipOutputStream.putNextEntry()一次
zipOut.putNextEntry(new ZipEntry(arg));
int c;
while ((c = in.read()) != -1) {
buffOut.write(c);
}
in.close();
buffOut.flush();
}
buffOut.close();
// 获取校检码
System.out.println("Checksum: " + checkedOut.getChecksum().getValue());
System.out.println();
// ===========================解压缩===========================
// 构建输入流
FileInputStream fileIn = new FileInputStream("test.zip");
CheckedInputStream checkedIn = new CheckedInputStream(fileIn, new Adler32());
ZipInputStream zipIn = new ZipInputStream(checkedIn);
BufferedInputStream buffIn = new BufferedInputStream(zipIn);
FileOutputStream fileOut2 = new FileOutputStream("123.txt");
// 获取每一个文件并解压到标准输出
ZipEntry zipEntry;
while ((zipEntry = zipIn.getNextEntry()) != null) {
System.out.println("\nReading file " + zipEntry);
int x;
while ((x = buffIn.read()) != -1) {
System.out.write(x);
}
System.out.flush();
}
if (args.length == 1) {
System.out.println("\nChecksum: " + checkedIn.getChecksum().getValue());
}
buffIn.close();
// 另一个获取ZipEntry的方式
ZipFile zipFile = new ZipFile("test.zip");
Enumeration enumeration = zipFile.entries();
while (enumeration.hasMoreElements()) {
ZipEntry ze2 = (ZipEntry) enumeration.nextElement();
System.out.println("\nFile: " + ze2);
}
}
}
序列化
自动序列化
描述
- 自动对象序列化条件:
- 所有想要序列化的对象及其数据成员都要继承Serializable。
- 对于不想要序列化的字段可以在前面加入transient关键字,将其排除。
- 不会序列化或反序列化static字段。
- 自动序列化对于两个对象引用指向相同内存的情况处理方式:只要它们序列化到同一个流中,还原时它们仍然会指向相同内存。
简单示例
class Worm implements Serializable {}
public class WormSerializer {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Worm worm1 = new Worm();
// 方式1:序列化到文件
ObjectOutputStream objOut1 = new ObjectOutputStream(new FileOutputStream("worm.out"));
objOut1.writeObject("Worm storage\n");
objOut1.writeObject(worm1);
objOut1.close();
ObjectInputStream objIn1 = new ObjectInputStream(new FileInputStream("worm.out"));
String s1 = (String) objIn1.readObject();
Worm worm2 = (Worm) objIn1.readObject();
System.out.println(s1 + "w2 = " + worm2);
// 方式2:序列化到内存(可用于对象深拷贝)
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
ObjectOutputStream objOut2 = new ObjectOutputStream(bytesOut);
objOut2.writeObject("Worm storage\n");
objOut2.writeObject(worm1);
objOut2.flush();
ObjectInputStream objIn2 = new ObjectInputStream(new ByteArrayInputStream(bytesOut.toByteArray()));
String s2 = (String) objIn2.readObject();
Worm worm3 = (Worm) objIn2.readObject();
System.out.println(s2 + "w3 = " + worm3);
}
}
手动序列化
描述
- 手动对象序列化条件:
- 要序列化的对象及其数据成员必须继承Externalizable。
- 在Externalizable接口中的两个方法:writeExternal和readExternal中逐个成员调用writeObject和readObject。
- 要序列化的对象的类及其数据成员必须有public默认构造函数。
简单示例
public class A implements Externalizable {
public static void main(String[] args) throws IOException, ClassNotFoundException {
A a = new A("A String ", 47);
ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("A.out"));
objOut.writeObject(a);
objOut.close();
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("A.out"));
a = (A) objIn.readObject();
System.out.println(a);
}
public A(String x, int a) {
s = x;
i = a;
}
public String toString() {
return s + i;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(s);
out.writeInt(i);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
s = (String) in.readObject();
i = in.readInt();
}
private int i;
private String s;
}