JavaI/O基础———File类,节点流,内存数组节点,内存字串流,过滤流类型,桥接转换流,缓冲流,数据流,打印流

目录

 节点流

文件节点流

内存数组节点 

内存字串流 

总结  

过滤流类型 

 过滤流

 加密算法:

 桥接转换流

 InputStreamReader构造器

 缓冲流

构造方法  

缓冲输入流的方法  

 键盘录入

 数据流

打印流  


 节点流

类型字符型字节流
File文件
FileReader FileWriter
FileInputStream FileOutputStream
内存数
CharArrayReader
CharArrayWriter
ByteArrayInputStream
ByteArrayOutputStream
内存字
StringReader StringWriter
管道
PipedReader PipedWriter
PipedInputStream, PipedOutputStream

文件节点流

FileInputStream FileOutputStream 是文件字节流,是一种节点流
文件字节输入流的构造方法:
  • FileInputStream("文件名称"),如果文件不存在则FileNotFoundException
  • FileInputStream(File)
文件字节输出流的构造方法 :
  • FileOutputStream(“文件名称”) 如果文件不存在则新建文件,如果文件存在则覆盖文件内容
  • FileOutputStream(String name文件名称, boolean append是否采用追加方式)
FileReader FileWriter 类似

FileInputStreamFileOutputStream两个类属于结点流,第一个类的源端和第二个类的目的端都是磁盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。

如:

FileInputStream infile = new FileInputStream("myfile.dat");
FileOutputStream outfile = new FileOutputStream("results.dat");
要注意的是,构造 FileInputStream, 对应的文件必须存在并且是可读的,而构造 FileOutputStream 时,如输出文件已存在,则必须是可覆盖的。

内存数组节点 

如果文本则使用 char[] ,如果二进制则使用 byte[]
构造器方法
  • CharArrayReader(char[] buf)其中char[]就是数据的来源,也就是说Reader就是从char[]中读取数
  • CharArrayRead(char[] buf, int offset, int length)
CharArrayWriter 用于实现向一个字符数组中写入数据,这个数组可以自动调整大小
ByteArrayInputStream ByteArrayOutputStream CharArrayReader 以及 CharArrayWriter 类似,支持操作的内容不同而已,操作byte[] char[]

内存字串流 

StringReader 用于从一个字串 String 中读取数据  
String str = " 亚洲说: 我爱小黑 ’" ;
StringReader sr = new StringReader ( str );
int cc ;
while (( cc = sr . read ()) !=- 1 )
System . out . print (( char ) cc );
sr . close ();

StringWriter用于给一个StringBuffer中写入数据,实现一个可边长的字串 

 Scanner sc=new Scanner(System.in);

try (
StringWriter sw = new StringWriter ();
Writer fw = new FileWriter ( "c:/console.txt" )
){
String temp = sc . nextLine ();
while ( ! temp . equals ( "quit" )){
if ( temp != null && temp . trim (). length () > 0 )
sw . write ( temp + "\n" );
temp = sc . nextLine ();
}
fw . write ( sw . toString ());
}

总结  

  •  读写文件使用节点流FileInputStream/FileOutputStreamFileReader/FileWriter,如果操作文本文件,建议使用FileReader/FileWriter,如果操作二进制文件建议使用 FileInputStream/FileOutputStream
  • 需要建立缓冲区(建立临时文件的方式效率低),可以考虑使用内存节点,例如 CharArrayReader/CharArrayWriterStringReader/StringWriterByteArrayInputStream/ByteArrayOutputStream
  • 如果需要一个二进制缓冲区可以使用ByteArrayInputStream/ByteArrayOutputStream,如果需要一个字符缓存可以使用CharArrayReader/CharArrayWriterStringReader/StringWriter
  • 如果数据量不是特别大使用CharArrayReader/CharArrayWriter更为方便,如果数据量大而且可能需要直接操作缓冲区则使用StringReader/StringWriter
  • StringWriter中提供了方法getBuffer():StringBuffer

过滤流类型 

过滤流就是在节点流的基础上附加功能
处理类型字符流字节流
缓存
BufferedReader BufferedWriter
BufferedInputStream
BufferedOutputStream
过滤类型
FilterReader FilterWriter
FilterInputStream
FilterOutputStream
桥接处理
InputStreamReader
OutputStreamWriter
对象序列化处理
ObjectInputStream
ObjectOutputStream
数据转换
DataInputStream
DataOutputStream
行数统计
LineNumberReader
LineNumberInputStream
回滚处理
PushbackReader
PushbackInputStream
打印功能
PrintWriter
PrintStream

 过滤流

 就是decorate模式中的抽象装饰角色

FilterInputStream/FilterOutputStream FilterReader/FilterWriter
public class FilterInputStream extends InputStream { // 典型的装饰模式
protected volatile InputStream in ; // 被装饰目标
protected FilterInputStream ( InputStream in ) { // 通过构造器组装被装饰对象
this . in = in ;
}
public int read () throws IOException { // 调用 Filter 中的 read 方法时实际操作是由
被装饰对象实现的
return in . read ();
}
}

 所谓的过滤流实际上就是类似上面的加密处理,在输入之后(后置处理,被装饰对象先执行)或者输出之前(前置处理,先处理然后被装饰对象执行)进行一下额外的处理,最终实际操作是调用被装饰对象的方法完成工作,依靠这种装饰模式实现在节点流的基础上附加额外功能.当然也允许多个过滤流嵌套从而达到功能累加的目的

FilterInputStream实际上就是一个装饰抽象角色

自定义流实现循环13加密:

        读取数据不变:FileReader---BufferedReader

        写出数据自定义过滤流SecurityWriter(FilterWriter)

public class SecurityWriter extends FilterWriter {
protected SecurityWriter ( Writer out ) {
super ( out );
}
public void write ( int c ) throws IOException {
if ( c >= 'a' && c <= 'z' ) {
c = ( c - 'a' + 13 ) % 26 + 'a' ;
} else if ( c >= 'A' && c <= 'Z' ) {
c = ( c - 'A' + 13 ) % 26 + 'A' ;
}
super . write ( c );
}
}

 public class SecurityReader extends FilterReader {

protected SecurityReader ( Reader in ) {
super ( in );
}
public int read () throws IOException {
int c = super . read ();
if ( c >= 'a' && c <= 'z' ) {
c = ( c - 'a' + 13 ) % 26 + 'a' ;
} else if ( c >= 'A' && c <= 'Z' ) {
c = ( c - 'A' + 13 ) % 26 + 'A' ;
}
return c ;
}
}

 加密算法:

  • 数字:如果不是9的数字,在原来的基础上加1,比如5变成6, 3变成4,如果是9的数字,变成0
  • 字母字符:如果是非z字符,向右移动一个,比如d变成e, G变成H,如果是zz->a, Z-A。字符需要保留大小写
  • 非字母字符:比如‘,&^ 保留不变,中文也保留不变
数字字符解密 -1 可以等价于 +9 ,字母解密 -1 可以等价于 +25

 桥接转换流

 InputStreamReader和OutputStreamWriterjava.io包中用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字节方式表示的流转换为特定平台上的字符表示。

转换流可以在构造时指定其编码字符集

InputStreamReader 用于将一个 InputStream 类型的输入流自动转换为 Reader 字符流
OutputStreamWriter 用于将一个 Writer 字符输出流转换为 OutputStream 字节输出流

 InputStreamReader构造器

  •  InputStreamReader(InputStream)
  • InputStreamReader(InputStream, String)
  • InputStreamReader(InputStream, Charset)
  • InputStreamReader(InputStream, CharsetDecorder)
Reader r = new InputStreamReader ( System . in );
int kk = r . read (); // 例如输入的是 中国 ,这里实际读取的是 " "
// 因为这里读取的是一个字节,所以输入 " 中国 " ,实际读取的是 " " 的一个字节,输出显示为 ?
kk = System . in . read ();
System . out . println ( " 输入的是: " + ( char ) kk );

InputSteram is=new InputStreamReader(System.in,”iso8859-1”);  

 Reader r=new InputStreamReader(System.in, "gbk");

int kk = r . read (); // 例如输入的是 " 中国 " ,实际读取的是 " "
System . out . println ( " 输入的是: " + ( char ) kk );

注意:一般不建议自行设置编码字符集,除非是必须的 

 缓冲流

 缓冲流是套接在响应的节点流之上,对续写的数据提供缓冲的功能,提高读写的效率,同时增加了一些新方法

以介质是硬盘为例,字节流和字符流的弊端:在每一次读写的时候,都会访问硬盘。 如果读写的频率比较高的时候,其性能表现不佳。为了解决以上弊端,采用缓存流。

缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。

 InputStream is = new FileInputStream("d:\\FileTest.java");

long start=System.currentTimeMillis();// 获取从 1970-1-1 0:0:0 到当前的毫米值
int con = is.read();
while (con != -1) {
System.out.write(con);
con = is.read();
}
long end=System.currentTimeMillis();
is.close();
System.out.println(" 统计时间为 :"+(end-start)+"ms");
60ms

构造方法  

  • BufferedReader(Reader)不定义缓存大小,默认8192
  • BufferedReader(Reader in, int size)size为自定义缓冲区的大小
  • BufferedWriter(Writer)
  • BufferedWriter(Writer out, int size)size为自定义缓冲区的大小
  • BufferedInputStream(InputStream)
  • BufferedInputStream(InputStream in, int size)size为自定义缓冲区的大小
  • BufferedOutputStream(OutputStream)
  • BufferedOutputStream(OuputStream out, int size)size为自定义缓冲区的大小

InputStream is = new BufferedInputStream(new
FileInputStream("d:\\FileTest.java"));
long start=System.currentTimeMillis();
int con = is.read();// 这里并不是直接从文件中进行读取,而是从缓存中进行读
while (con != -1) {
System.out.write(con);
con = is.read();
}
long end=System.currentTimeMillis();
is.close();
System.out.println(" 统计时间为 :"+(end-start)+"ms");
is.close();
10ms

缓冲输入流的方法  

BuffedReader提供了一个方法readLine():String,但是BufferedInputStream中并没有这个

  • BufferedReader提供了readLine方法用于读取一行字符串,以\r\n分割(换行符)
  • 如果读取内容为null,则表示读取到了流的末尾
  • readLine方法会自动剔除本行内容末尾的换行符
  • BufferedWriter提供了newLine方法用于写入一个行分隔符
对于输出的缓冲流,写入的数据会先在内存中缓存,使用 flush 方法会使内存中的数据立即写出

 键盘录入

System.in:InputStream 用于指代系统默认的输入设备 键盘
方法 read():int 可以实现代码执行到这里则会阻塞等待,只要输入数据为止
BufferedReader br = new BufferedReader ( new InputStreamReader ( System . in ));
System . out . println ( " 输入数据 " )
String temp = "" ;
while (( temp = br . readLine ()). trim (). length () > 0 ){
if ( "quit" . equals ( temp )) break ;
System . out . println ( temp );
}
br . close ();
BufferedWriter bw = new BufferedWriter ( new OutputStreamWriter ( System . out ));
bw . write ( " 只有缓冲区满才自动进行输出显示 " );
bw . flush (); // 刷新缓冲区,否则看不到输出内容
System . in . read ();
bw . close (); // 关闭输出时会首先自动进行刷新缓冲区
强调:使用缓存流并没有添加什么额外方法,只是它能够在执行过程中自动引入缓存,从而提高执行效率

 过滤流使用必须有对应的节点流,因为过滤流是装饰节点流,不是有具体的操作目标

new BufferedReader(new FileReader(..)) new BufferedWriter(new FileWriter()) 实际上使用的还是Reader/Writer那些方法,这里从编码的角度上说,没有任何区别,但是从执行性能上说,比
FileReader/Writer 效率高,可以减少磁盘的读写次数
执行 close 方法会自动关闭被装饰的对象,所以不需要再关闭 FileReader FileWriter
执行 flush 会自动刷新数据到节点流上,但是并没有执行关闭流。针对输出流关闭时会自动先 flush 缓存再执行关闭

 数据流

DataInputStream DataOutputStream 两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写Java 数据。所以比较适合于网络上的数据传输。
这两个流也是过滤器流常以其它流如InputStream OutputStream 作为它们的输入或输出
DataInputStram DataOutputStream 分别继承自 InputStream OuputStream ,属于过滤流,需要分别套接在InputStream OutputStream 类型的节点流上
  • 只有字节流,没有对应的字符流
DataInputStream DataOutputStream 提供了可以存取与机器无关的 Java 原始类型数据的方法
DataInputSteram DataOutputStream 构造方法为
  • DataInputStream(InputStream)
  • DataOutputStream(OutputStream)

读取、写出一个double数据到文件中  

// 使用数据流就可以直接操作简单类型数据
double dd = 123.4567 ;
FileOutputStream fos = new FileOutputStream ( "d:\\a.data" );
fos . write (( dd + "" ). getBytes ());
fos . close ();
// 如果不使用数据流,则需要额外编码进行数据类型转换
FileInputStream fis = new FileInputStream ( "d:/a.data" );
byte [] buffer = new byte [ 8192 ];
int len = fis . read ( buffer );
fis . close ();
String str = new String ( buffer , 0 , len );
double dd = Double . parseDouble ( str );
System . out . println ( dd );

 加入需要写一个double,然后一个String,然后再一个int 需要将输入内容转换为String,并且为了区分数据需要引入特殊符号,例如@@,输入数据为123.456@@shi ya zhou@@12。从功能角度上说没问题,但是编码太复杂了,所以引入Data类型的输入输出流

// 这里不使用 OutputStream 定义变量的原因是:需要使用 DataOutputStream 中定义的特殊方法,而
不是父类中定义的通用方法
DataOutputStream dos = new DataOutputStream ( new
FileOutputStream ( "d:\\a.data" ));
dos . writeDouble ( 123.456 );
dos . writeChars ( " 赵天爱小猴 !" );
dos . writeInt ( 12 );
dos . close ();
由于读取出现问题,针对中间的 String 数据引入一个额外的数据,其中存储 String char 个数
写出数据
double salary = 123.456 ;
String ss = " 赵天爱小猴,小猿爱小主,小胡招小天 " ;
int age = 12 ;
DataOutputStream dos = new DataOutputStream ( new BufferedOutputStream ( new
FileOutputStream ( "d:\\aa.data" )));
dos . writeDouble ( salary );
dos . writeInt ( ss . length ());
dos . writeChars ( ss );
dos . writeInt ( age );
dos . close ();

读取数据

double salary=0;

String str = "" ;
int age = 0 ;
// 读取数据的前提是必须知道数据的结构
DataInputStream dis = new DataInputStream ( new BufferedInputStream ( new
FileInputStream ( "d:\\aa.data" )));
salary = dis . readDouble ();
StringBuilder sb = new StringBuilder ();
int len = dis . readInt ();
for ( int i = 0 ; i < len ; i ++ ) sb . append ( dis . readChar ());
str = sb . toString ();
age = dis . readInt ();
System . out . println ( salary + "---" + str + "---" + age );
注意:读取数据判断文件结束 EOFException ,这里没有 -1
在具体应用中建议针对字串使用 readUTF writeUTF

 DataOutputStream dos=new DataOutputStream(new FileOutputStream("data2.txt"));

dos . writeDouble ( 1234.56 );
String str = " 猴子愛小終,小終愛信心 " ;
dos . writeUTF ( str );
dos . writeInt ( 99 );
dos . close ();
DataInputStream dis = new DataInputStream ( new FileInputStream ( "data2.txt" ));
double d1 = dis . readDouble ();
String ss = dis . readUTF ();
int kk = dis . readInt ();
System . out . println ( d1 + "\t" + ss + "\t" + kk );
dis . close ();

打印流  

PrintStream PrintWriter 都属于输出流,分别针对字节和字符
PrintWriter PrintStream 都提供了重载的 print println 方法用于输出多种类型数据
print(Object):void
  • 输出引用类型,实际上是调用对象的toString方法转换为String进行输出

public void println ( Object x ) {
String s = String . valueOf ( x ); // 调用 String 类中的静态方法将 object 类型的
数据转换为字符串
synchronized ( this ) {
print ( s );
newLine (); //print('\n')
}
}
//String 中的 valueOf 方法的定义
public static String valueOf ( Object obj ) {
return ( obj == null ) ? "null" : obj . toString (); // 如果输出对象非空,则
调用对象的 toString 方法
}
println 表示输出后自动换行
  • PrintWriterPrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
  • PrintWriterPrintStream有自动的flush功能 textOut.flushBuffer();
PrintWriter(Writer)
PrintWriter(Writer out, boolean autoFlush) 自动刷新 ----println
PrintWriter ( OutputStream out ) // 参数是一个字节流,但是不需要通过桥接处理
PrintWriter ( OutputStream out , boolean autoFlush )
PrintStream ( OutputStream )
PrintStream ( OutputStream out , boolean autoFlush )

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值