2021-08-13
Java输入输出流
5. FileInputStream流和FileOutputStream的应用
利用程序将文件file1.txt 拷贝到file2.txt中。import java.io.File; import java.io.IOException; import java.io.FileOutputStream; import java.io.FileInputStream; public class TestFile { public static void main(String args[]) throws IOException { try { File inFile = new File("copy.java"); File outFile = new File("copy2.java"); FileInputStream finS = new FileInputStream(inFile); FileOutputStream foutS = new FileOutputStream(outFile); int c; while ((c = finS.read()) != -1) { foutS.write(c); } finS.close(); foutS.close(); } catch (IOException e) { System.err.println("FileStreamsTest: " + e); } } }
6. 缓冲输入输出流 BufferedInputStream/ BufferedOutputStream
计算机访问外部设备非常耗时。访问外存的频率越高,造成CPU闲置的概率就越大。为了减少访问外存的次数,
应该在一次对外设的访问中,读写更多的数据。为此,除了程序和流节点间交换数据必需的读写机制外,
还应该增加缓冲机制。缓冲流就是每一个数据流分配一个缓冲区,一个缓冲区就是一个临时存储数据的内存。这样可以减少访问硬盘的次数,提高传输效率。
BufferedInputStream: BufferedInputStream比FileInputStream多了一个缓冲区。它提供了一个缓冲数组,
每次调用read方法的时候,它首先尝试从缓冲区里读取数据,若读取失败(缓冲区无可读数据),则选择从物理数据源
(譬如文件)读取新数据(这里会尝试尽可能读取多的字节)放入到缓冲区中,最后再将缓冲区中的内容部分或全部返回给用户.
由于从缓冲区里读取数据远比直接从物理数据源(譬如文件)读取速度快。BufferedInputStream的默认缓冲区大小是8192字节。
当每次读取的数据量很小时,FileInputStream每次都是从硬盘读入,而BufferedInputStream大部分是从缓冲区读入。
读取内存速度比读取硬盘速度快得多,因此BufferedInputStream效率高。
例如:BUFFER_SIZE < 8192时候,BufferedInputStream性能是很高。
BufferedInputStream bufferedInput = new BufferedInputStream(new FileInputStream(fileA));
byte[] buffer = new byte[BUFFER_SIZE];
int len;
while ((len = bufferedInput.read(buffer)) > 0){
System.out.println(new String(buffer, 0, len));
}
BUFFER_SIZE > 8192时候, FileInputStream和BufferedInputStream两者效率就没有明显差别了。
BufferedOutputStream :执行wirte时先写入缓冲区,待缓冲区写满后,系统再写入输出设备。
1)将文件读入内存:
将BufferedInputStream与FileInputStream相接
FileInputStream in = new FileInputStream( “file1.txt ” );
BufferedInputStream bin = new BufferedInputStream( in);
2)将内存写入文件:
将BufferedOutputStream 与 FileOutputStream相接:
String fileB = "/Users/huangguisu/b.txt";
FileOutputStream out = new FileOutputStream(fileB);
BufferedOutputStream bOut = new BufferedOutputStream(out);
byte[] buffer = {0x1,0x2,0x3};
bOut.write(buffer);
bOut.flush();
bOut.close();
3)键盘输入流读到内存
将 BufferedReader 与 标准的数据流 相接
InputStreamReader sin = new InputStreamReader ( System.in) ;
BufferedReader bin = new BufferedReader( sin);
import java.io.*; public class ReadWriteToFile { public static void main(String args[]) throws IOException { InputStreamReader sin = new InputStreamReader(System.in); BufferedReader bin = new BufferedReader(sin); FileWriter out = new FileWriter("myfile.txt"); BufferedWriter bout = new BufferedWriter(out); String s; while ((s = bin.readLine()).length() > 0) { bout.write(s, 0, s.length()); } } }
程序说明:
从键盘读入字符,并写入到文件中BufferedReader类的方法:String readLine()
作用:读一行字符串,以回车符为结束。
BufferedWriter类的方法:bout.write(String s,offset,len)
作用:从缓冲区将字符串s从offset开始,len长度的字符串写到某处。
八. 字符流Writer/Reader
Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。
1. Reader抽象类
用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,
多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。
1) FileReader :与FileInputStream对应
主要用来读取字符文件,使用缺省的字符编码,有三种构造函数:
(1)将文件名作为字符串 :FileReader f = new FileReader(“c:/temp.txt”);
(2)构造函数将File对象作为其参数。
File f=new file(“c:/temp.txt”);
FileReader f1=new FileReader(f);
(3) 构造函数将FileDescriptor对象作为参数
FileDescriptor() fd = new FileDescriptor()
FileReader f2=new FileReader(fd);
(1) 用指定字符数组作为参数:CharArrayReader(char[])
(2) 将字符数组作为输入流:CharArrayReader(char[], int, int)
读取字符串,构造函数如下: public StringReader(String s);
2) CharArrayReader:与ByteArrayInputStream对应
3) StringReader : 与StringBufferInputStream对应
4) InputStreamReader
从输入流读取字节,在将它们转换成字符:Public inputstreamReader(inputstream is);
5) FilterReader: 允许过滤字符流
protected filterReader(Reader r);
6) BufferReader :接受Reader对象作为参数,并对其添加字符缓冲器,使用readline()方法可以读取一行。
Public BufferReader(Reader r);
主要方法:
(1) public int read() throws IOException; //读取一个字符,返回值为读取的字符
(2) public int read(char cbuf[]) throws IOException; /*读取一系列字符到数组cbuf[]中,返回值为实际读取的字符的数量*/
(3) public abstract int read(char cbuf[],int off,int len) throws IOException;
/*读取len个字符,从数组cbuf[]的下标off处开始存放,返回值为实际读取的字符数量,该方法必须由子类实现*/
2. Writer抽象类
写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。但是,
多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。 其子类如下:
1) FileWrite: 与FileOutputStream对应
将字符类型数据写入文件,使用缺省字符编码和缓冲器大小。
Public FileWrite(file f);
2) chararrayWrite:与ByteArrayOutputStream对应 ,将字符缓冲器用作输出。
Public CharArrayWrite();
3) PrintWrite:生成格式化输出
public PrintWriter(outputstream os);
4) filterWriter:用于写入过滤字符流
protected FilterWriter(Writer w);
5) PipedWriter:与PipedOutputStream对应
6) StringWriter:无与之对应的以字节为导向的stream
主要方法:
(1) public void write(int c) throws IOException; //将整型值c的低16位写入输出流
(2) public void write(char cbuf[]) throws IOException; //将字符数组cbuf[]写入输出流
(3) public abstract void write(char cbuf[],int off,int len) throws IOException; //将字符数组cbuf[]中的从索引为off的位置处开始的len个字符写入输出流
(4) public void write(String str) throws IOException; //将字符串str中的字符写入输出流
(5) public void write(String str,int off,int len) throws IOException; //将字符串str 中从索引off开始处的len个字符写入输出流
(6) flush( ) //刷空输出流,并输出所有被缓存的字节。
(7)close() 关闭流 public abstract void close() throws IOException
3 .InputStream与Reader差别 OutputStream与Writer差别
InputStream和OutputStream类处理的是字节流,数据流中的最小单位是字节(8个bit)
Reader与Writer处理的是字符流,在处理字符流时涉及了字符编码的转换问题
import java.io.*; public class EncodeTest { private static void readBuff(byte [] buff) throws IOException { ByteArrayInputStream in =new ByteArrayInputStream(buff); int data; while((data=in.read())!=-1) System.out.print(data+" "); System.out.println(); in.close(); } public static void main(String args[]) throws IOException { System.out.println("内存中采用unicode字符编码:" ); char c='好'; int lowBit=c&0xFF; int highBit=(c&0xFF00)>>8; System.out.println(""+lowBit+" "+highBit); String s="好"; System.out.println("本地操作系统默认字符编码:"); readBuff(s.getBytes()); System.out.println("采用GBK字符编码:"); readBuff(s.getBytes("GBK")); System.out.println("采用UTF-8字符编码:"); readBuff(s.getBytes("UTF-8")); } }
Reader类能够将输入流中采用其他编码类型的字符转换为Unicode字符,然后在内存中为其分配内存
Writer类能够将内存中的Unicode字符转换为其他编码类型的字符,再写到输出流中。
4、BufferedInputStream 和BufferedReader区别
首先虽然都作为一个包装类,但是BufferedReader针对字符流,BufferedInputStream针对字节流
BufferedInputStream在实现的时候是在自身read方法中提供缓存,是一次取1024或更多字节然后再慢慢读,一个个的返回,它并没有实现读一行的方法
BufferedReader在实现时通过提供一个readLine方法,使用数组或者stringBuilder存储一行数据,并一次性返回
---------------------------------------------------------------------------------------------------------------------------------
下周继续