Java IO 流详解
概述流是一个抽象的概念,代表了数据的无结构化通报。流的本质是数据在不同设备之间的传输。在 Java 中,数据的读取和写入都是以流的方式进行的
在 Java 中,根据数据流向的不同,可以将流分为输入(Input)流和输出(Output)流。根据单元的不同,可以将流分为字节省和字符流。根据等级的不同,可以将流分为节点流和处置惩罚流
输入流和输出流
输入流用于将数据从控制台、文件、网络等外部设备输入应用程序历程中
输出流用于将应用程序历程中的数据输出到控制台、文件、显示器等中
字节省和字符流
字节省:字节省是以字节(1byte=8bit)为单元对数据进行读写操作的,也就是说,字节省进行一次读取或者写入都是以 8bit 为单元进行的,因此重要用于处置惩罚二进制据。在 Java 中利用 InputStream、OutputStream 处置惩罚字节数据,其中 InputStream 用于字节省输入,OutputStream 用于字节省输出
字符流:字符流以字符为单元对数据进行读写操作,一次读取或写入都是以 16bit 为单元进行的。Java 中的字符采用 Unicode 编码,一个字符占用 2 字节。字符流重要用于处置惩罚文本数据的读写,在处置惩罚过程中须要进行字符集的转化。在 Java 中利用 Reader、Writer 处置惩罚字符数据,其中 Reader 用于字符流输入,Writer 用于字符流输出
InputStream 字节输入流是一个抽象类,其子类包罗:
[*]FileInputStream(文件输入流)
[*]ObjectInputStream(对象输入流)
[*]ByteArrayInputStream(字节数组输入流)
[*]PipedInputStream(管道输入流)
[*]FilterInputStream(过滤器输入流)
[*]BufferedInputStream(缓冲输入流)
[*]PushbackInputStream(回牙输入流)
[*]DataInputStream(数据输入流)
[*]SequenceInputStream(顺序输人流)
[*]StringBufferedInputStream(缓冲字符串流)
InputStream 类的所有方法在碰到错误时都会抛出 IOExcepiion 异常。InputStream 用于以字节情势将数据读入应用程序中,常用的方法及其作用如表所示
方法作用int read()从输入流读取8字节数据并将其转换成一个0-255的整数,返回值为读取的总字节数,碰到数据流的末尾则返回-1int read(byte[] b)从输入流中读取最大长度为len字节的数据并保存到b字节数组中,碰到数据流的末尾则返回-1int read(byte[] b, int off, int len)以输入流中的off位置为开始位置读取最大长度为len字节的数据,并将其保存到b字节数组中void close()关闭输入流int available()返回可以从输入流中读取的位数skip(long n)从输入流跳过n字节一段基于 FileInputStream 读取文件的代码如下:
public static void main(string[] args) throws IoException {
String path = "file_dir/";
String fileName = "File-Test.txt";
// 1:定义待读取的文件
File file = new File(path, fileName);
// 2:从文件中读取数据到 FileInputStream
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte;
int n = 0;
// 3:从FileInputstream中不断循环读取字节数据并写入bytes,直到遇到数据流结尾时
while ((n = fileInputstream.read(bytes)) != -1) {
// 4:将byte[]转化为字符串
String s = new String(bytes);
System.out.printIn(s);
}
// 5:关闭输入文件流
fileInputStream.close();
} OutputStream 字节输出流是一个抽象类,其子类包罗:
[*]FileOutputStream(文件输出流)
[*]ByteArrayOutputStream(字节数组输出流)
[*]FilterOutputStream(过滤器输出流)
[*]BufferedOutputStream(缓冲输出流)
[*]DataOutputStream(数据输出流)
[*]PrintOutputStream(打印输出流)
[*]ObjectOutputStream(对象输出流)
[*]PipedOutputStream(管道输出流)
OutputStream 类的所有方法在碰到错误时都会抛出 IOException 异常。OutputStream 用于以字节情势将数据输出到目的设备,常用的方法及其作用如表所示
方法作用int write()将指定字节的数据写入输出流int write(byte[] b)将指定字节数组的内容写入输出流int write(byte[] b, int off, int len)将指定的字节数组从off位置开始的len字节的内容写入输出流close()关闭数据流flush()革新输出流,强行将缓冲区的内容写入输出流基于 FileOutputStream 读取文件的一段代码如下
public static void main(String[] args) throws IOException {
String path = "file_dir/";
String fileName = "File-Test.txt";
// 1:定义待写入的文件
File file = new File(path, fileName);
// 2:定义FileOutputStream
FileOutputStream fileOutputStream = new FileOutputStream(file, false);
// 3:将数据写入FileOutputStream
fileOutputStream.write("hello FileOutputStream new " .getBytes());
// 4:关闭FileOutputStream
fileOutputStream.close();
}Reader 类是所有字符流输入类的父类,用于以字符情势将数据读取到应用程序中,其子类包罗:
[*]CharArrayReader:将字符数组转换为字符输入流并从中读取字符
[*]StringReader:将字符串转换为字符输入流并从中读取字符
[*]BufferedReader:为其他字符输入流提供读缓冲区
[*]PipedReader:毗连到一个 PipedWriter
[*]FilterReader:Reader 类的子类,用于丰富 Reader 类的功能
[*]InputStreamReader:将字节输入流转换为字符输入流,可以指定字符编码
Reader 类常用方法如下
方法作用int read()从输入流中读取一个字符并转化为 0-65535 的整数,当读取到流的末尾时返回-1int read(char[] buf)从输入流中读取多少个字符并保存到参数buf指定的字符数组中,当读取到流的末尾时返回-1int read(char[] buf, int off, int len)以输入流中的off位置为开始位置读取最大长度为len字节的数据并将其保存到buf字符数组中,当读取到流的末尾时返回-1基于 BufferedReader 读取文件的一段代码如下:
public static void main(string[] args) throws Exception {
String path = "file_dir.mov";
//1:创建FileReader
FileReader fileReader = new FileReader(path);
//2:基于FileReader创建BufferedReader
BufferedReader bufferedReader = new BufferedReader(fileReader);
//3:定义一个strLine,表示BufferedReader读取的结果
String strLine = "";
//4:调用readLine方法将缓冲区中的数据读取为字符串
//当readLine返回-1时,表示已经读取到文件末尾了
while((strLine = bufferedReader.readLine()) != null) {
System.out.println(strLine);
}
//5:关团fileReader
fileReader.close();
//6:关闭bufferedReader
bufferedReader.close();
}Writer 类是所有字符流输出类的父类,用于以字符情势将数据写出到外部设备,其子类包罗:
[*]CharArrayWriter:用于向内存缓冲区的字符数组写数据
[*]StringWriter:用于向内存缓冲区的字符串(StringBuffer)写数据
[*]BufferedWriter:用于为其他字符输出流提供写缓冲区
[*]PipedWriter:用于毗连到一个 PipedReader
[*]OutputStreamReader:用于将字节输出流转换为字符输出流,可以指定字符编码
[*]FilterWriter:过滤器字符输出流
Writer 类常用方法如下
方法作用void write(int c)向输出流中写入一个字符void write(char[] cbuf)将字符数组cbuf中的字符写入输出流中void write(char[] cbuf,int off, int len)将字符数组cbuf中从off位置开始获取长度为len的字符并写入输出流中void write(String str)将字符串写入输出流void write(String str,int off, int len)将字符串中的部分字符写入输出流append(char c)将字符c追加到输出流append(charSequence csq)将参数csq指定的字符序列追加到输出流append(charSequence csq, int start, int end)将参数csq指定的字符序列的子序列追加到输出流基于 BufferedWriter 将字符串写入文件中的一段代码如下:
public static void main(String[] args) throws Exception {
//1:定义一个FileWriter
String path = "File-Test.txt";
FileWriter writer = new FileWriter(path);
//2:基于FileWriter定义一个BufferWriter
BufferedWriter bufferedWriter = new BufferedWriter(writer)
//3:调用BufferedWriter的write方法将字符串写入BufferedWriter
bufferedWriter.write("write by str");
//4:关闭BufferedWriter
bufferedWriter.close();
//5:关闭FileWriter
writer.close();
}
节点流和处置惩罚流
节点流是低级流,直接与数据源相接,对数据源上的流进行读写。
处置惩罚流是高级流,采用修饰器模式对节点流进行了封装,不直接与数据源相连,主用于消除不同节点流的实现差异,提供更方便的方法来完成数据的输入和输出。
例如,FileInputStream、FileOutputStream、FileReader、FileWriter 属于节点流;BufferInputStream、BufferOutputStream、BufferReader、BufferWriter 属于处置惩罚流。
相对于节点流,处置惩罚流有如下特性:
[*]性能高:处置惩罚流通过增加缓存的方式提高数据的输入和输出效率。
[*]操作方便:处置惩罚流封装了一系列高级方法来完成一次性大批量数据的输入和输出。
内存映射文件技能
操作系统可以利用虚拟内存实现将一个文件或者文件的一部分“映射”到内存中。然后,这个文件就可被当作内存数据来访问,比传统的文件要快得多,这种技能就是内存映射文件技能。
内存映射文件技能的一个关键上风是操作系统负责真正的文件读写,应用程序只需处置惩罚内存数据,就可以实现非常快速的 IO 操作。在写入过程中,即使应用程序在将数据写人内存后历程出错退出,操作系统仍旧会将内存映射文件中的数据写入文件系统。另一个更突出的上风是共享内存,即内存映射文件可被多个历程同时访问,起到低时延共享内存的作用。
Java 中的 java.nio 包支持内存映射文件,具体利用方式是通过 MappedByteBuffer 读写内存,而且内存映射文件技能涉及的内存在 Java 的堆空间之外,这也是其效率高的一个原因。
在 Java 中将一个文件映射到内存并操作共分为如下三步:
从文件中获得一个通道(channel)
RandomAccessFile raf = new RandomAccessFile(filePath, "rw");
FileChannel fc= raf.getChannel();调用 FileChannel 的 map 方法将文件映射到虚拟内存
MappedByteBuffer buffer = channel.map(mode, 0, length);mode 参数用于指定映射模式,支持的模式有如下三种:
[*]FileChannel.MapMode.READ_ONLY:所产生的缓冲区是只读的
[*]FileChannel.MapMode.READ_WRITE:所产生的缓冲区是可写的,任何修改在某个时刻写回到文件中。注意,其他映射同一个文件的程序大概不能立即看到这些修改,多个程序同时进行文件映射的最终行为是依靠于操作系统的
[*]FileChanncl.MapMode.PRIVATE:所产生的缓冲区是可写的,但任何修改对该缓冲区来说都是私有的,不会传播到文件中
调用 MappedByteBuffer 的 put(byte[] src) 向内存映射文件中写入数据,调用 get(int index) 获取文件中对应索引的数据,以字节情势返回
public static void main(String[] args) throws Exception {
//1:定义文件流
String path = "file_path/File-Test.txt";
RandomAccessFile raf = new RandomAccessFile(path,"rw");
//2:获取FileChannel
FileChannel fc = raf.getChannel();
//3:定义MappedByteBuffer
int start = 0:
int len = 1024;
//调用map函数的过程其实就是磁盘文件到内存数据的映射过程
//对Filechannel调用map函数后,应用程序可以像使用内存一样使用该文件
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.PRIVATE, start, len);
//4:进行MappedByteBuffer数据的输入,分别在内存映射文件中写入如下字符串
mbb.put("12345".getBytes());
mbb.put("6789".getBytes());
mbb,put("wanglei".getBytes());
//读取第9个字符,结果为"w"
System.out.println((char)mbb.get(9));
//5:MappedByteBuffer数据的读取:读取所有数据
for (int i = start; i < mbb.position(); i++) {
System.out.println((char)mbb.get(i));
}
}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]