Java IO 流
Posted Zview
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java IO 流相关的知识,希望对你有一定的参考价值。
关于面向对象的方法的一个说明。 对于多态而言,可以使用子类来实例化父类,这对于面向对象有很重要的作用,但是,子类中的一些独有的方法父类就掉用不到了,这个时候可以使用向下转型,将父类进行强行的数据转型,就可以使用这些方法了
字节流和字符流
字节流InputStream/OutputStream ,只能操作byte
字符流Reader/Writer
FileoutputStream(File f)
字节流本身是只能操作byte的。
对于这一个类,如果文件不存在会自动创建
write()方法默认会将文件进行覆盖
可以使用构造方法FileoutputStream(File f,boolean append),这样就可以指定要不要使用追加模式
FileoutputStream(File f)
方法 - available() 获得可以读取的字节数
字符流
一般一个字符为两个字节,可以直接操作字符串
会用到缓冲区
FileWriter/FileReader
默认依然是覆盖,要追加只要和FileoutputStream类似加boolean标志就好了
Filereader读取到char/char[]
字节流和字符流的不同
字节流是直接与文件操作,不会用到缓冲区 字符流数据先放在缓冲区,然后再从缓冲区写到文件,要记得fiush()或者close()
字节-字符的转换流
- InputStreamReader
将一个输入字节流转为字符流,是Reader的子类 - OutputStreamWriter
将一个输出字节流转为字符流,是Writer的子类
FileWriter是OutputStreamWriter的子类 FileReader是OutputStreamReader的子类
内存操作流
ByteArrayInputStream(byte[])
将byte中是数据写入内存中
ByteArrayOutputStream()
实际的意思就是说,通过输入流将数据写入到内存里面,然后通过输出流把内存里面的东西取出来!
private static void tesByteArrayInputStream() {
// 创建ByteArrayInputStream字节流,内容是ArrayLetters数组
ByteArrayInputStream bais = new ByteArrayInputStream(ArrayLetters);
// 从字节流中读取5个字节
for (int i=0; i<LEN; i++) {
// 若能继续读取下一个字节,则读取下一个字节
if (bais.available() >= 0) {
// 读取“字节流的下一个字节”
int tmp = bais.read();
System.out.printf("%d : 0x%s\n", i, Integer.toHexString(tmp));
}
}
// 若“该字节流”不支持标记功能,则直接退出
if (!bais.markSupported()) {
System.out.println("make not supported!");
return ;
}
// 标记“字节流中下一个被读取的位置”。即--标记“0x66”,因为因为前面已经读取了5个字节,所以下一个被读取的位置是第6个字节”
// (01), ByteArrayInputStream类的mark(0)函数中的“参数0”是没有实际意义的。
// (02), mark()与reset()是配套的,reset()会将“字节流中下一个被读取的位置”重置为“mark()中所保存的位置”
bais.mark(0);
// 跳过5个字节。跳过5个字节后,字节流中下一个被读取的值应该是“0x6B”。
bais.skip(5);
// 从字节流中读取5个数据。即读取“0x6B, 0x6C, 0x6D, 0x6E, 0x6F”
byte[] buf = new byte[LEN];
bais.read(buf, 0, LEN);
// 将buf转换为String字符串。“0x6B, 0x6C, 0x6D, 0x6E, 0x6F”对应字符是“klmno”
String str1 = new String(buf);
System.out.printf("str1=%s\n", str1);
// 重置“字节流”:即,将“字节流中下一个被读取的位置”重置到“mark()所标记的位置”,即0x66。
bais.reset();
// 从“重置后的字节流”中读取5个字节到buf中。即读取“0x66, 0x67, 0x68, 0x69, 0x6A”
bais.read(buf, 0, LEN);
// 将buf转换为String字符串。“0x66, 0x67, 0x68, 0x69, 0x6A”对应字符是“fghij”
String str2 = new String(buf);
System.out.printf("str2=%s\n", str2);
}
}
管道流
管道流就是实现两个进程之间的通信
PipeOutputStream PipeInputStream 使用的时候要使用connect()把输入输出流连接起来,Connect是PipeOutputStream的方法,用来连接一个PipeInputStream
打印流
PrintStream
定义了很多的print和pringtln方法,可以打印任意数据类型
System.out就是定位在输出设备的PrintStream
构造方法,指定输出的位置
PrintSTream(OutputStream out)
这样打印输出更加方便了,PrintStream就是OutputStream的子类,可以方便的进行输出,这样的设计称之为装饰设计模式
PrintWriter与上面的类似
格式化输出
类似于C语言的格式化输出 %d,%s,%f,%c
ps.printf("姓名%s,年龄:%d",a,b);
System.in以及BufferedReader(字符流)
是一个InputStream
BufferedReader buf=null;
buf=new BufferedReader(new InputStreamReader(System.in));
String str=null;
try {
while ((str=buf.readLine())!=null){
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
输入输出重定向
System.setOut(new PrintStream(new FileOutputStream("D:/a.txt")));
实际上in、out、err就是System的三个常量,可以通过set方法改变,然后就完成了重定向的作用。
Scanner
在java.util包中,可以实现BufferedReader的全部功能,是一个工具类
- 默认的分隔符是空格,可以自行设置
- 非常强大,可以接受多种类型的数据,但是对于日期类型没有支持,可以使用Scanner.hasNext(Pattern)/next(Pattern)匹配来取出数据
-
可以接受File,做一系列文件操作
Scanner scanner=new Scanner(System.in); scanner.useDelimiter("\n");//修改分割符 int a=0; float f=0f; String date=null; if(scanner.hasNextInt()){ a=scanner.nextInt(); } if(scanner.hasNextFloat()){ f=scanner.nextFloat(); } if(scanner.hasNext("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")){ date=scanner.next("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}"); } System.out.println(a+" "+f+" "+date); try { Date date1=new SimpleDateFormat("yy-MM-dd hh:mm:ss").parse(date); System.out.println(date1); } catch (ParseException e) { e.printStackTrace(); }
合并流
压缩流
支持三种格式的压缩,zip/jar/Gzip,这里以zip为例另外两种都是一样的
ZipEntry,就是压缩文件目录下的每一个文件
-
ZipOutputStream(OutputStream)
- PutNextEntry(ZipEntry ?)
可以将文件、文件夹进行压缩
ZipFile类
专门表示压缩文件的类
回退流
字符编码
获得本机编码
System.getProperity("file.encoding")
常见的编码格式
- iso8859-1单字节编码,只能表示英文
- GBK国标,表示汉字
- unicode 16进制两个字节的编码,最标准的,但是不兼容iso-8859-1
- utf 变长的编码,一个字符长度1--6不等,可以表示所有语言的字符、
关于io流的结构
输入流
- InputStream
- ByteArrayInputStream(byte[])
- FileInputStream(File)
- PipedInputStream
- SequenceInputStream(InputStream,InputStream)
- FilterInputStream
- BufferedInputStream(InputStream)
- PushbackInputStream
- DataInputStream
- ObjectInputStream
输出流
- OutputStream
- ByteArrayOutputStream
- FileOutputStream
- PipedOutputStream
- FilterOutputStream
- BufferedOutputStream
- PrintWriter
- DataOutputStream
- ObjectOutputStream
常见的方法
InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法.Inputstream类中的常用方法:
1 public abstract int read( ):读取一个byte的数据,返回值是高位补0的int类型值。
2 public int read(byte b[ ]):读取b.length个字节的数据放到b数组中。返回值是读取的字节数。该方法实际上是调用下一个方法实现的
3 public int read(byte b[ ], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。
4 public int available( ):返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用,
5 public long skip(long n):忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取
6 public int close( ) :我们在使用完后,必须对我们打开的流进行关闭.
OutputStream提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。
1. public void write(byte b[ ]):将参数b中的字节写到输出流。
2. public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流。
3. public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。
4. public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。
5. public void close( ) : 关闭输出流并释放与流相关的系统资源。
java的流类提供了结构化方法,如,底层流和高层过滤流。
而高层流不是从输入设备读取,而是从其他流读取。同样高层输出流也不是写入输出设备,而是写入其他流。
使用"分层对象(layered objects)",为单个对象动态地,透明地添加功能的做法,被称为Decorator
Pattern。Decorator模式要求所有包覆在原始对象之外的对象,都必须具有与之完全相同的接口。这使得
decorator的用法变得非常的透明--无论对象是否被decorate过,传给它的消息总是相同的。这也是Java I/O
类库要有"filter(过滤器)"类的原因:抽象的"filter"类是所有decorator的基类
- DataInputStream 包含了一整套读取primitive数据的接口
- BufferedInputStream,为InputStream增加了一个缓冲区,缓冲区的大小是8k
- PushbackInputStream 有一个"弹压单字节"的缓冲区,可以把最后读到的那个字节再压回去
- DataOutputStream 包括写入primitive数据的全套接口。
- PrintStream(inpurstream,boolean autoflush) 打印流
- BufferedOutputStream 有缓冲区
以上是关于Java IO 流的主要内容,如果未能解决你的问题,请参考以下文章
JAVA IO流相关代码(Serializable接口,管道流PipedInputStream类,RandomAccessFile类相关代码)
JAVA IO流相关代码(Serializable接口,管道流PipedInputStream类,RandomAccessFile类相关代码)