IO

一、概念

在java.io包中操作文件内容的主要有两大类:字节流、字符流。两类都分为输入和输出操作,输入流基本方法是读,输出流基本方法是写。

二、字节流

字节流处理的基本单元为1个字节(byte),操作字节和字节数组,通常用来处理二进制数据。面向字节流的OutputStream和InputStream是一切的基础,两者均为抽象类,实际使用的是它们的一系列子类。

字节输出流

字节输出流

1.OutputStream

类定义:

public abstract class OutputStream implements Closeable, Flushable {}
//Closeable表示可关闭,Flushable表示刷新,清空内存中的数据

方法:

//将一个字节数据写入数据流
public abstract void write(byte b) throws IOException

//将一个byte数组写入数据流
public void write(byte b[]) throws IOException 

//将指定byte数组中从偏移量off开始的len个字节写入数据流
public void write(byte b[], int off, int len) throws IOException 

//刷新缓冲区
public void flush() throws IOException

//关闭输出流
public void close() throws IOException

要想使用此类及以上方法,必须通过子类实例化对象。

2.FileOutputStream

文件输出流,是向File或FileDescriptor输出数据的一个输出流。
构造方法:

1.创建一个文件输出流,向指定的File对象输出数据
public FileOutputStream(File file) throws FileNotFoundException 
//字节写到文件的开始,输出会进行覆盖

public FileOutputStream(File file, boolean append) throws FileNotFoundException
//如果append设为true,字节将写到文件末尾

2.创建一个文件输出流,向指定名称的文件输出数据
public FileOutputStream(String name) throws FileNotFoundException
 //输出会进行覆盖
  
public FileOutputStream(String name, boolean append) throws FileNotFoundException
 //如果append设为true,字节将写到文件末尾

3.创建一个文件输出流,向指定的文件描述器输出数据,该文件描述符表示文件系统中一个实际文件的现有连接
public FileOutputStream(FileDescriptor fdObj)

3.ObjectOutputStream

对象输出流,将Java对象的原始数据类型和对象写入输出流,只有支持可序列化接口的对象才可以写入到输出流。

4.ByteArrayOutputStream

字节数组输出流,实现了一个以字节数组形式写入数据的输出流,缓冲区会随着数据的写入而自动扩大,可以用toByteArray()和toString()检索数据。
构造方法:

1.创建一个新的字节数组输出流
public ByteArrayOutputStream() {
    this(32);
}
//缓冲区容量最初是32字节,如果需要,大小会增加

2.创建一个新的字节数组输出流,并带有指定大小字节的缓冲区容量
public ByteArrayOutputStream(int size) 

5.PipedOutputStream

管道输出流,可以连接到管道输入流来创建通信管道,它是这个管道的发送端。一个线程通过管道输出流写入数据,另一个线程通过管道输入流读取数据,这样可实现两个线程之间的通信。不建议尝试从单个线程使用这两个管道流对象,因为它可能会造成线程死锁。
构造方法:

1.创建连接到指定管道输入流的管道输出流
public PipedOutputStream(PipedInputStream snk)  throws IOException

2.创建一个管道输出流,该输出流尚未连接到管道输入流
public PipedOutputStream()

6.FilterOutputStream

其子类有DataOutputStream、BufferedOutputStream、PrintStream。

字节输入流

字节输入流

1.InputStream

类定义:

public abstract class InputStream implements Closeable

方法:

1.读取一个字节,返回0到255范围内的int字节值,读取到-1结束
public abstract int read() throws IOException;

2.将当前输入流中b.length个字节读入到byte数组中,实际读取的字节数作为整数返回
public int read(byte b[]) throws IOException 

3.将当前输入流中len个字节数据读入一个字节数组中,从数组的off位置开始存放len长度的数据,实际读取的字节数作为整数返回
public int read(byte b[], int off, int len) throws IOException 

4.从该输入流中跳过或忽略n字节
public long skip(long n) throws IOException 

5.返回这个输入流中可读的字节数估计值,即可取得输入文件的大小
public int available() throws IOException 

6.关闭输入流
public void close() throws IOException

要想使用此类及以上方法,必须通过子类实例化对象。

2.FileInputStream

文件输入流,从文件系统中的文件读取输入字节。
构造方法:

1.创建一个输入文件流,从指定的File对象读取数据
public FileInputStream(File file) throws FileNotFoundException

2.创建一个输入文件流,从指定名称的文件读取数据
public FileInputStream(String name) throws FileNotFoundException

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

3.ObjectInputStream

对象输入流。

4.ByteArrayInputStream

字节数组输入流,把内存的一个缓冲区作为InputStream使用。
构造方法:

1.创建一个字节数组输入流,使用buf作为它的缓冲区数组,从缓冲区数组中读取数据
public ByteArrayInputStream(byte buf[])

2.创建一个字节数组输入流,从指定字节数组中读取数据
public ByteArrayInputStream(byte buf[], int offset, int length)
//offset表示读取缓冲区中第一个字节的偏移
//length表示从缓冲区读取的最大字符数

5.PipedInputStream

管道输入流,是一个通信管道的接收端。
构造方法:

1.创建连接到指定管道输出流的管道输入流
public PipedInputStream(PipedOutputStream src) throws IOException
 
public PipedInputStream(PipedOutputStream src, int pipeSize) throws IOException
//使用指定的管道大小作为管道的缓冲
 
2.创建一个管道输入流,该输出流尚未连接到管道输出流
public PipedInputStream()

public PipedInputStream(int pipeSize)
//使用指定的管道大小

6.SequenceInputStream

序列输入流,把几个输入连续地合并起来,它从一个有序的输入流集合开始,每个输入流依次被读取到文件的末尾,直到到达最后一个输入流的文件末尾。
构造方法:

1.参数中枚举生成运行时类型为输入流的对象,新创建一个序列输入流,通过读取由枚举产生的输入流来初始化它
public SequenceInputStream(Enumeration<? extends InputStream> e) 

2.新创建一个序列输入流,按参数顺序读取输入流s1,s2来初始化它
public SequenceInputStream(InputStream s1, InputStream s2) 

7.StringBufferInputStream

不推荐使用,此类不能将字符正确地转换为字节。从一个串创建一个流的最佳方法是采用StringReader类。

8.FilterInputStream

其子类有LineNumberInputStream(java8中已不建议使用)、DataInputStream、BufferedInputStream、PushbackInputStream。

三、字符流

字符流处理的基本单元为2个字节的Unicode字符,操作字符、字符数组或字符串,它通常用来处理文本数据。

java提供了Writer、Reader两个专门操作字符流的类,表示以Unicode字符为单位往流中写入或读取信息。

字符输出流

字符输出流

1.Writer

类定义:

public abstract class Writer implements Appendable, Closeable, Flushable

方法:

1.写一个字符
public void write(int c) throws IOException

2.写一个字符数组
public void write(char cbuf[]) throws IOException 

abstract public void write(char cbuf[], int off, int len) throws IOException;
//从cbuf[]的off位置开始,写入字符数为len的字符数组

3.写入一个字符串
public void write(String str) throws IOException 

public void write(String str, int off, int len) throws IOException 
//从字符串str的off位置开始,写入的字符数为len

4.将指定的字符序列caq追加到该writer
public Writer append(CharSequence csq) throws IOException 

//追加从指定序列的start位置开始,至end位置的字符序列
public Writer append(CharSequence csq, int start, int end) throws IOException
 
5.将指定字符追加到该writer
public Writer append(char c) throws IOException

6.强制性清空缓存
abstract public void flush() throws IOException;

7.关闭输出流
abstract public void close() throws IOException;

要想使用此类,必须通过子类实例化对象,使用子类。

2.FileWriter

如果是向文件中写入内容,应该使用FileWriter子类,与FileOutputStream对应。
构造方法:

1.构造给定File对象的FileWriter
public FileWriter(File file) throws IOException

//如果apped设为true,数据将写到文件的末尾而不是开始
public FileWriter(File file, boolean append) throws IOException

2.构造给定文件名的FileWriter
public FileWriter(String fileName) throws IOException
 
//如果append设为true,数据将写到文件的末尾
public FileWriter(String fileName, boolean append) throws IOException

3.构造与文件描述器相关联的FileWriter
public FileWriter(FileDescriptor fd) 

3.BufferedWriter

拥有8192字符的缓冲区,使用BufferedWriter时,写入的数据不会先输出到目的地,而是先存储至缓冲区中,如果缓冲区满了,才会一次对目的地进行写出。

4.CharArrayWriter

与ByteArrayOutputStream对应。

5.PipedWriter

与PipedOutputStream对应。

6.FilterWriter

7.StringWriter

字符输入流

字符输入流

1.Reader

类定义:

public abstract class Reader implements Readable, Closeable

方法:

1.读取单个字符
public int read() throws IOException

2.将内容读入字符数组,返回读入的长度,如果到达输入流末端,返回-1
public int read(char cbuf[]) throws IOException 

//len表示要读取的最大字符数
//将输入流中len个字符数据读入一个字符数组中,从数组的off位置开始存放len长度的数据
abstract public int read(char cbuf[], int off, int len) throws IOException

3.关闭输入流,并释放与之关联的任何系统资源
abstract public void close() throws IOException

要想使用此类,必须通过子类实例化对象,使用子类。

2.FileReader

如果要从文件中读取内容,可以直接使用FileReader子类,与FileInputStream对应。
构造方法:

1.创建一个新的FileReader,从指定的File对象读取数据
public FileReader(File file) throws FileNotFoundException

2.创建一个新的FileReader,从指定名称的文件中读取数据
public FileReader(String fileName) throws FileNotFoundException

3.创建一个新的FileReader,从指定的文件描述器读取数据
public FileReader(FileDescriptor fd)

3.BufferedReader

拥有8192字符的缓冲区,使用BufferedReader读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,之后若使用read()方法,会先从缓冲区中进行读取,如果缓冲区数据不足,才会从文件中读取。

4.CharArrayReader

与ByteArrayInputStream对应。

5.PipedReader

与PipedInputStream对应。

6.FilterReader

子类有PushbackReader。

7.StringReader

四、字节流与字符流转换

OutputStreamWriter和InputStreamReader是字节流与字符流的转换类。
OutputStreamWriter是Writer的子类,将输出的字符流转换成字节流。
InputStreamReader是Reader的子类,将输入的字节流转换成字符流。

1.OutputStreamWriter

OutputStreamWriter类是从字符流到字节流的桥梁,在OutputStreamWriter类中需要一个字节流的对象(OutputStream out)。OutputStreamWriter将多个字符写入到一个输出流,根据指定的字符编码将写入的字符编码成字节,实际负责编码的是StreamEncoder类,过程中必须使用指定的编码集。
类定义:

public class OutputStreamWriter extends Writer

构造方法:

1.可以通过名称指定支持的字符编码集
public OutputStreamWriter(OutputStream out, String charsetName) throws UnsupportedEncodingException

2.构造器中指定Charset类型
public OutputStreamWriter(OutputStream out, Charset cs)

3.接受平台的默认编码集
public OutputStreamWriter(OutputStream out)

4.使用指定charset encoder
public OutputStreamWriter(OutputStream out, CharsetEncoder enc) 

write()方法的每次调用都会在给定字符(或字符串)上调用编码转换器,在写入底层输出流之前,将在缓冲区中积累产生的字节。为了提高效率,可以考虑将OutputStreamWriter包装在一个BufferedWriter中,以避免频繁的转换。
例如:

Writer out  = new BufferedWriter(new OutputStreamWriter(System.out));

2.InputStreamReader

InputStreamReader类是从字节流到字符流的桥梁,在InputStreamReader类中需要一个字节流的对象,它使用的字符集可以通过名称指定,也可以明确Charset类型,也可以接受平台的默认字符集,与OutputStreamWriter类似。
类定义:

public class InputStreamReader extends Reader

构造方法:

public InputStreamReader(InputStream in, String charsetName)
public InputStreamReader(InputStream in, Charset cs)
public InputStreamReader(InputStream in)

每次调用InputStreamReader的read()方法,都可能导致从底层字节输入流中读取一个或多个字节,为了能有效地将字节转化为字符,可从底层输入流中读取更多字节,而不只是满足当前读取操作所需的字节。为了提高效率,可以考虑将InputStreamReader包装在一个BufferedReader中。
例如:

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

五、例子

缓冲输入文件:

private String read(String filePath) {
    try {
        BufferedReader in = new BufferedReader(new FileReader(filePath));
        String s;
        StringBuilder sb = new StringBuilder();
        while((s = in.readLine()) != null) {
            sb.append(s + "\n");
        }
        in.close();
        return sb.toString();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}


//测试代码
String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

String read = read(filePath);
Log.d(TAG, "zwm, read: \n" + read);

//IOTest.txt
12345
ABCDE

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, read: 
12345
ABCDE

从内存输入:

private String read(String filePath) {
    try {
        BufferedReader in = new BufferedReader(new FileReader(filePath));
        String s;
        StringBuilder sb = new StringBuilder();
        while((s = in.readLine()) != null) {
            sb.append(s + "\n");
        }
        in.close();
        return sb.toString();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}


//测试代码
String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

String read = read(filePath);
StringReader in = new StringReader(read);
int c;
try {
    while((c = in.read()) != -1) {
        Log.d(TAG, "zwm, c: " + c);
    }
} catch (IOException e) {
    e.printStackTrace();
}

//IOTest.txt
12345
ABCDE

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, c: 49
zwm, c: 50
zwm, c: 51
zwm, c: 52
zwm, c: 53
zwm, c: 10
zwm, c: 65
zwm, c: 66
zwm, c: 67
zwm, c: 68
zwm, c: 69
zwm, c: 10

格式化的内存输入:

private String read(String filePath) {
    try {
        BufferedReader in = new BufferedReader(new FileReader(filePath));
        String s;
        StringBuilder sb = new StringBuilder();
        while((s = in.readLine()) != null) {
            sb.append(s + "\n");
        }
        in.close();
        return sb.toString();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}


//测试代码
String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

String read = read(filePath);
DataInputStream in = new DataInputStream(new ByteArrayInputStream(read.getBytes()));
try {
    while(true) {
        Log.d(TAG, "zwm, char: " + (char)in.readByte());
    }
} catch (IOException e) {
    e.printStackTrace();
    Log.d(TAG, "zwm, IOException");
}

//IOTest.txt
12345
ABCDE

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, char: 1
zwm, char: 2
zwm, char: 3
zwm, char: 4
zwm, char: 5
zwm, char: 
zwm, char: A
zwm, char: B
zwm, char: C
zwm, char: D
zwm, char: E
zwm, char: 
zwm, IOException
String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

try {
    DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
    while(in.available() != 0) {
        Log.d(TAG, "zwm, char: " + (char)in.readByte());
    }
} catch (IOException e) {
    e.printStackTrace();
    Log.d(TAG, "zwm, IOException");
}

//IOTest.txt
12345
ABCDE

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, char: 1
zwm, char: 2
zwm, char: 3
zwm, char: 4
zwm, char: 5
zwm, char: 
zwm, char: 
zwm, char: A
zwm, char: B
zwm, char: C
zwm, char: D
zwm, char: E

基本的文件输出:

private String read(String filePath) {
    try {
        BufferedReader in = new BufferedReader(new FileReader(filePath));
        String s;
        StringBuilder sb = new StringBuilder();
        while((s = in.readLine()) != null) {
            sb.append(s + "\n");
        }
        in.close();
        return sb.toString();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}


//测试代码
String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

try {
    BufferedReader in = new BufferedReader(new StringReader(read(filePath)));
    PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(filePathOutput)));
    int lineCount = 1;
    String s;
    while((s = in.readLine()) != null) {
        out.println(lineCount++ + ": " + s);
    }
    out.close();
} catch (IOException e) {
    e.printStackTrace();
}

//IOTest.txt
12345
ABCDE

//IOTestOutput.txt
1:12345
2:ABCDE
private String read(String filePath) {
    try {
        BufferedReader in = new BufferedReader(new FileReader(filePath));
        String s;
        StringBuilder sb = new StringBuilder();
        while((s = in.readLine()) != null) {
            sb.append(s + "\n");
        }
        in.close();
        return sb.toString();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}


//测试代码 
String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

try {
    BufferedReader in = new BufferedReader(new StringReader(read(filePath)));
    PrintWriter out = new PrintWriter(filePathOutput);
    int lineCount = 1;
    String s;
    while((s = in.readLine()) != null) {
        out.println(lineCount++ + ": " + s);
    }
    out.close();
} catch (IOException e) {
    e.printStackTrace();
}

//IOTest.txt
12345
ABCDE

//IOTestOutput.txt
1:12345
2:ABCDE

读写随机访问文件:

String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

try {
    RandomAccessFile rf = new RandomAccessFile(filePathOutput, "rw");
    for(int i=0; i<7; i++) {
        rf.writeDouble(i*1.414);
    }
    rf.writeUTF("Then end of the file");
    rf.close();

    RandomAccessFile rf2 = new RandomAccessFile(filePathOutput, "r");
    for(int i=0; i<7; i++) {
        Log.d(TAG, "zwm, readDouble: " + rf2.readDouble());
    }
    Log.d(TAG, "zwm, readUTF: " + rf2.readUTF());
    rf2.close();

    RandomAccessFile rf3 = new RandomAccessFile(filePathOutput, "rw");
    rf3.seek(5*8);
    rf3.writeDouble(47.0001);
    rf3.close();
} catch (IOException e) {
    e.printStackTrace();
}

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, readDouble: 0.0
zwm, readDouble: 1.414
zwm, readDouble: 2.828
zwm, readDouble: 4.242
zwm, readDouble: 5.656
zwm, readDouble: 7.069999999999999
zwm, readDouble: 8.484
zwm, readUTF: Then end of the file

读取二进制文件:

private byte[] read(String filePath) {
    BufferedInputStream bf = null;
    try {
        bf = new BufferedInputStream(new FileInputStream(filePath));
        byte[] data = new byte[bf.available()];
        bf.read(data);
        return data;
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            bf.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return null;
}


//测试代码
String fileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

byte[] readByte = read(filePath);
for(int i=0; i<readByte.length; i++) {
    Log.d(TAG, "zwm, readByte: " + (char) readByte[i]);
}

//输出
zwm, filePath: /storage/emulated/0/IOTest.txt, fileExist: true
zwm, readByte: 1
zwm, readByte: 2
zwm, readByte: 3
zwm, readByte: 4
zwm, readByte: 5
zwm, readByte: 
zwm, readByte: 
zwm, readByte: A
zwm, readByte: B
zwm, readByte: C
zwm, readByte: D
zwm, readByte: E

压缩:
Java I/O类库中的类支持读写压缩格式的数据流,最常用的压缩算法有Zip和GZIP。
压缩类的使用非常直观,直接将输出流封装成GZIPOutputStream或ZipOutputStream,并将输入流封装成GZIPInputStream或ZipInputStream即可。

用GZIP进行简单压缩:

File fileDir = getExternalCacheDir();
Log.d(TAG, "zwm, fileDir exists: " + fileDir.exists());
if(!fileDir.exists()) {
    fileDir.mkdir();
    Log.d(TAG, "zwm, fileDir exists: " + fileDir.exists());
}
String fileName = "IOTest.txt";
final String filePath = fileDir + File.separator + fileName;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
boolean fileExist = new File(filePath).exists();
String fileNameGZ = "IOTest.gz";
String filePathGZ = fileDir + File.separator + fileNameGZ;
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);

try {
    //写文件
    //字符输入流
    BufferedReader in = new BufferedReader(new FileReader(filePath));
    //字节输出流
    BufferedOutputStream out = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(filePathGZ)));
    int c;
    while ((c = in.read()) != -1) {
        out.write(c);
    }
    out.close();
    in.close();

    //读文件
    //字节输入流转字符输入流
    BufferedReader in2 = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(filePathGZ))));
    String s;
    while ((s = in2.readLine()) != null) {
        Log.d(TAG, "zwm, output: " + s);
    }
} catch (IOException e) {
    e.printStackTrace();
}

//IOTest.txt
Hello! My name is TomyZhang.
I an Android App developer.
I want to be a professional engineer.
I think my dream will come true soon.
Thank you~

//输出
zwm, fileDir exists: true
zwm, filePath: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest.txt, fileExist: true
zwm, output: Hello! My name is TomyZhang.
zwm, output: I an Android App developer.
zwm, output: I want to be a professional engineer.
zwm, output: I think my dream will come true soon.
zwm, output: Thank you~

用Zip进行多文件保存:
用Checksum类来计算和校验文件的校验和,一共两种Checksum类型:Adler32(快一些)和CRC32(慢一些)。

File fileDir = getExternalCacheDir();
Log.d(TAG, "zwm, fileDir exists: " + fileDir.exists());
if(!fileDir.exists()) {
    fileDir.mkdir();
    Log.d(TAG, "zwm, fileDir exists: " + fileDir.exists());
}
String fileName = "IOTest.txt";
String filePath = fileDir + File.separator + fileName;
String fileName2 = "IOTest2.txt";
String filePath2 = fileDir + File.separator + fileName2;
String fileName3 = "IOTest3.txt";
String filePath3 = fileDir + File.separator + fileName3;
String fileNameOutput = "IOTestOutput.txt";
String filePathOutput = fileDir + File.separator + fileNameOutput;
String fileNameGZ = "IOTest.gz";
String filePathGZ = fileDir + File.separator + fileNameGZ;
String fileNameZip = "IOTest.zip";
String filePathZip = fileDir + File.separator + fileNameZip;
boolean fileExist = new File(filePath).exists();
boolean file2Exist = new File(filePath2).exists();
boolean file3Exist = new File(filePath3).exists();
Log.d(TAG, "zwm, filePath: " + filePath + ", fileExist: " + fileExist);
Log.d(TAG, "zwm, filePath2: " + filePath2 + ", file2Exist: " + file2Exist);
Log.d(TAG, "zwm, filePath3: " + filePath3 + ", file3Exist: " + file3Exist);
try {
    //写文件
    FileOutputStream f = new FileOutputStream(filePathZip);
    CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());
    ZipOutputStream zos = new ZipOutputStream(csum);
    BufferedOutputStream out = new BufferedOutputStream(zos);
    zos.setComment("A test of Java Zipping");
    String[] args = {filePath, filePath2, filePath3};
    for (String arg : args) {
        Log.d(TAG, "zwm, zip: " + arg);
        BufferedReader in = new BufferedReader(new FileReader(arg));
        zos.putNextEntry(new ZipEntry(arg));
        int c;
        while ((c = in.read()) != -1) {
            out.write(c);
        }
        in.close();
        out.flush();
    }
    out.close();

    //读文件,方法1
    FileInputStream fi = new FileInputStream(filePathZip);
    CheckedInputStream csumi = new CheckedInputStream(fi, new Adler32());
    ZipInputStream in2 = new ZipInputStream(csumi);
    BufferedReader br = new BufferedReader(new InputStreamReader(in2));
    ZipEntry ze;
    while ((ze = in2.getNextEntry()) != null) {
        Log.d(TAG, "zwm, Reading file: " + ze);
        int x;
        String s;
        while ((s = br.readLine()) != null) {
            Log.d(TAG, "zwm, output: " + s);
        }
    }
    br.close();

    //读文件,方法2
    ZipFile zf = new ZipFile(filePathZip);
    Enumeration e = zf.entries();
    while (e.hasMoreElements()) {
        ZipEntry ze2 = (ZipEntry) e.nextElement();
        // 同上
    }
} catch (IOException e) {
    e.printStackTrace();
    Log.d(TAG, "zwm, IOException");
}

//IOTest.txt
Hello! My name is TomyZhang.

//IOTest2.txt
I an Android App developer.

//IOTest3.txt
I want to be a professional engineer.

//输出
zwm, fileDir exists: true
zwm, filePath: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest.txt, fileExist: true
zwm, filePath2: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest2.txt, file2Exist: true
zwm, filePath3: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest3.txt, file3Exist: true
zwm, zip: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest.txt
zwm, zip: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest2.txt
zwm, zip: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest3.txt
zwm, Reading file: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest.txt
zwm, output: Hello! My name is TomyZhang.
zwm, Reading file: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest2.txt
zwm, output: I an Android App developer.
zwm, Reading file: /storage/emulated/0/Android/data/com.tomorrow.bustest/cache/IOTest3.txt
zwm, output: I want to be a professional engineer.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,797评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,179评论 3 414
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,628评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,642评论 1 309
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,444评论 6 405
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,948评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,040评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,185评论 0 287
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,717评论 1 333
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,602评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,794评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,316评论 5 358
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,045评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,418评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,671评论 1 281
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,414评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,750评论 2 370

推荐阅读更多精彩内容