IO就是输入流输出流的意思。之内存为基准,分为输入input
和输出output
,即流向内存是输入流,流出内存的输出流。java
上方的表格是顶级父类数组
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时同样如此。app
因此,字节流能够传输任意文件数据。在操做流的时候,咱们要时刻明确,不管使用什么样的流对象,底层传输的始终为二进制数据。优化
java.io.InputStream ``抽象类
是表示字节输入流的全部类的超类,能够读取字节信息到内存中。编码
它定义了字节输入流的基本共性功能方法。操作系统
public abstract int read()
: 从输入流读取数据的下一个字节。public int read(byte[] b)
: 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。public void close()
:关闭此输入流并释放与此流相关联的任何系统资源。java.io.FileInputStream
类是文件输入流,继承InputStream抽象类。publicclass FileInputStream extends InputStream
3d
做用是把硬盘文件中的数据,读取到内存中使用。code
读取数据的原理(硬盘->内存):Java程序-->JVM-->操做系统-->调用本地方法-->读取文件内容视频
Constructor | Description |
---|---|
FileInputStream(File file) * |
经过打开与实际文件的链接建立一个 FileInputStream ,该文件由文件系统中的 File 对象 file 命名。 |
FileInputStream(String name) |
经过打开与实际文件的链接来建立一个 FileInputStream ,该文件由文件系统中的路径名 name 命名。 |
FileInputStream(FileDescriptor fdObj) |
建立 FileInputStream 经过使用文件描述符 fdObj ,其表示在文件系统中的现有链接到一个实际的文件。 |
当你建立一个流对象时,必须传入一个文件路径。该路径下,若是没有该文件,会抛出FileNotFoundException
。对象
方法 | 描述 |
---|---|
int read() | 今后输入流中读取一个数据字节。 |
int read(byte[] b) | 今后输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 |
int read(byte[] b, int off, int len) | 今后输入流中将最多 len 个字节的数据读入一个 byte 数组中。 |
void close() | 关闭此文件输入流并释放与此流有关的全部系统资源。 |
long skip(long n) | 从输入流中跳过并丢弃 n 个字节的数据。 |
protected void finalize() | 确保在再也不引用文件输入流时调用其 close 方法。 |
int available() | 返回下一次对此输入流调用的方法能够不受阻塞地今后输入流读取(或跳过)的估计剩余字节数。 |
FileChannel getChannel() | 返回与此文件输入流有关的惟一 FileChannel 对象。 |
FileDescriptor getFD() | 返回表示到文件系统中实际文件的链接的 FileDescriptor 对象,该文件系统正被此 FileInputStream 使用。 |
*在文件字节输入流中,read()底层调用本地方法read0()
其余两个read方法调用本地方法readBytes(byte b[], int off, int len)
package IO; import java.io.FileInputStream; import java.io.IOException; public class FileInputStream_in { public static void main(String args[]) throws IOException{ //read("1.txt"); //readMore("1.txt"); readAll("1.txt"); } public static void read(String path) throws IOException{ FileInputStream fis = new FileInputStream(path); int len =0; while((len = fis.read())!=-1) System.out.print((char)len); fis.close(); } public static void readMore(String path) throws IOException{ FileInputStream fis = new FileInputStream(path); int len =0; byte[] bytes = new byte[2]; while((len = fis.read(bytes))!=-1) System.out.println(new String(bytes)); fis.close(); } //优化上一个方法 public static void readAll(String path) throws IOException{ FileInputStream fis = new FileInputStream(path); int len =0; byte[] bytes = new byte[1024]; while((len = fis.read(bytes))!=-1) System.out.print(new String(bytes,0,len));//只取有效部分 fis.close(); } }
java.io.OutputStream
抽象类是表示字节输出流的全部类的超类,将指定的字节信息写出到目的地。
它定义了字节输出流的基本共性功能方法。
public void close()
:关闭此输出流并释放与此流相关联的任何系统资源。public void flush()
:刷新此输出流并强制任何缓冲的输出字节被写出。public void write(byte[] b)
:将 b.length字节从指定的字节数组写入此输出流。public void write(byte[] b, int off, int len)
:从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。public abstract void write(int b)
:将指定的字节输出流。方法 | 描述 |
---|---|
void close() | 关闭此输出流并释放与此流有关的全部系统资源。 |
void flush() | 刷新此输出流并强制写出全部缓冲的输出字节。 |
void write(byte[] b) | 将 b.length 个字节从指定的 byte 数组写入此输出流。 |
void write(byte[] b, int off, int len) | 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 |
abstract void write(int b) | 将指定的字节写入此输出流。 |
*在字节输出流中,write的重载方法都调用write(int b) 方法
java.io.FileInputStream
类是文件输入流,从文件中读取字节。
写入数据的原理(内存->硬盘):Java程序-->JVM-->操做系统-->调用本地方法-->把数据写入文件
FileInputStream(File file)
: 经过打开与实际文件的链接来建立一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。FileInputStream(String name)
: 经过打开与实际文件的链接来建立一个 FileInputStream ,该文件由文件系统中的路径名 name命名。当你建立一个流对象时,必须传入一个文件路径。该路径下,若是没有该文件,会抛出FileNotFoundException
。
Constructor | Description |
---|---|
FileOutputStream(File file, boolean append) ** |
建立文件输出流以写入由指定的 File 对象表示的文件。 |
FileOutputStream(String name, boolean append) |
建立文件输出流以指定的名称写入文件。append是追加开关,默认false(关)。 |
FileOutputStream(String name) |
建立文件输出流以指定的名称写入文件。 |
FileOutputStream(File file) |
建立文件输出流以写入由指定的 File 对象表示的文件。 |
FileOutputStream(FileDescriptor fdObj) * |
建立文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有链接。 |
其实无论哪一个构造器都转成FileOutputStream(File file, boolean append)
形式
方法 | 描述 |
---|---|
void write(int b) **核心 | 将指定字节写入此文件输出流。 |
void write(byte[] b) | 将 b.length 个字节从指定 byte 数组写入此文件输出流中。 |
void write(byte[] b, int off, int len) | 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 |
void close() | 关闭此文件输出流并释放与此流有关的全部系统资源。 |
protected void finalize() | 清理到文件的链接,并确保在再也不引用此文件输出流时调用此流的 close 方法。 |
FileChannel getChannel() | 返回与此文件输出流有关的惟一FileChannel 对象。 |
FileDescriptor getFD() | 返回与此流有关的文件描述符。 |
底层调用本地(native)方法write(int b, boolean append)
和writeBytes(byte b[], int off, int len, boolean append)
在文件字节输出流中,write重载方法调用不一样的本地方法。
//用文件字节输出流向文件写入一个字节 import java.io.*; public class fileIO { public static void main(String args[]) throws IOException{ FileOutputStream fos = new FileOutputStream("1.txt"); fos.write(97);//输入一个字节 97的二进制1100001 fos.close();//打开记事本默认读字符97对应的ASCII表是a } }
package IO; import java.io.*; import java.util.Arrays; public class FileOutputStream_ { public static void main(String args[]) throws IOException{ fileOutOne("1.txt",97);//向1文件写入1个字节(8位)01100001 byte[] t = "你好".getBytes(); System.out.println(Arrays.toString(t)); //gdk中英都占两个字节。 utf-8 英文一字节,中文三字节 fileOutMore("2.txt",t);//向2文件写入你好字符串转化的字节数组。 byte[] b = {97,98,49,48,48}; fileOutMore1("3.txt",b);//向3文件写入一个规定字节数组。 } //使用字节输出流向文件写入一个字节 public static void fileOutOne(String path,int num) throws IOException{ FileOutputStream fos = new FileOutputStream(path);//指向路径的文件 fos.write(num);//输入一个字节 97的二进制1100001 fos.close();//打开记事本默认读字符97对应的ASCII表是a } //使用字节输出流向文件写入多个字节 public static void fileOutMore(String path,byte[] bytes) throws IOException{ File f = new File(path); FileOutputStream fos = new FileOutputStream(f);//指向具体文件 fos.write(bytes);//写入一个字节数组 fos.close(); } //使用字节输出流向文件写入偏移的多个字节 public static void fileOutMore1(String path,byte[] bytes) throws IOException{ File f = new File(path); FileOutputStream fos = new FileOutputStream(f);//指向具体文件 //byte[] b = {97,98,49,48,48}; 本应该是 ab100 偏移两位,写入三位得100 fos.write(bytes,2,3);//输入一个字节数组 fos.close(); } }
package IO; import java.io.FileOutputStream; import java.io.IOException; public class FileOutputStrean_append { public static void main(String args[]) throws IOException{ fileOutAppend("1.txt","append".getBytes());//向1文件追加换行和写入一个单词 } public static void fileOutAppend(String path,byte[] bytes) throws IOException{ FileOutputStream fos = new FileOutputStream(path,true);//true 标记追加 fos.write("\r\n".getBytes());//window系统下文件的换行符号 fos.write(bytes);//写入一个字节数组 fos.close(); } }
package bytestream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class CopyFile { public static void main(String[] args) throws IOException { // 1. 建立一个字节输入流对象,构造方法中绑定要读取的数据源 FileInputStream fis = new FileInputStream("test.txt"); // 2. 建立一个字节输出流对象,构造方法中绑定要写入的目的地 FileOutputStream fos = new FileOutputStream("test2.txt"); // 3. 使用字节输入流对象的read方法读取数据 byte[] bytes = new byte[1024]; int len = 0; while ((len = fis.read(bytes)) != -1) { // 4. 使用直接输出流对象的write方法将读取到的数据写入目的地文件 fos.write(bytes, 0, len); } // 5. 释放资源(栈顺序,先进后出) fos.close(); fis.close(); } }
中文字符的编码
package bytestream; import java.io.FileInputStream; import java.io.IOException; public class ByteStreamTest { public static void main(String[] args) throws IOException { // 当使用字节流读取字符时,存在一些问题 FileInputStream fis = new FileInputStream("test.txt"); int len = 0; while ((len = fis.read()) != -1) { System.out.println((char)len); } fis.close(); } }
test.txt
123789456你好
运行结果
1 2 3 7 8 9 4 5 6 ä ½ å ¥ ½
使用字节流读取字符数据出现乱码!
字节流存在的问题:当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,
那是由于一个中文字符可能占用多个字节存储。因此Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。