11.3.4 注意问题
上面介绍了IO类的基本使用,熟悉了实体流和装饰流的基本使用,但是在IO类实际使用时,还是会遇到一系列的问题,下面介绍一些可能会经常遇到的问题。
11.3.4.1 类的选择
对于初次接触IO技术的初学者来说,IO类体系博大精深,类的数量比较庞大,在实际使用时经常会无所适从,不知道该使用那些类进行编程,下面介绍一下关于IO类选择的一些技巧。
选择类的第一步是选择合适的实体流。
选择实体流时第一步是按照连接的数据源种类进行选择,例如读写文件应该使用文件流,如FileInputStream/FileOutputStream、FileReader/FileWriter,读写字节数组应该使用字节数组流等,如ByteArrayInputStream/ByteArrayOutputStream。
选择实体流时第二步是选择合适方向的流。例如进行读操作时应该使用输入流,进行写操作时应该使用输出流。
选择实体流时第三步是选择字节流或字符流。除了读写二进制文件,或字节流中没有对应的流时,一般都优先选择字符流。
经过以上步骤以后,就可以选择到合适的实体流了。下面说一下装饰流的选择问题。
在选择IO类时,实体流是必需的,装饰流是可选的。另外在选择流时实体流只能选择一个,而装饰流可以选择多个。
选择装饰流时第一步是选择符合要求功能的流。例如需要缓冲流的话选择BufferedReader/BufferedWriter等,有些时候也可能只是为了使用某个装饰流内部提供的方法。
选择装饰流时第二步是选择合适方向的流,这个和实体流选择中的第二步一致。
当选择了多个装饰流以后,可以使用流之间的多层嵌套实现要求的功能,流的嵌套之间没有顺序。
11.3.4.2 非依次读取流数据
由于IO类设计的特点,在实际读取时,只能依次读取流中的数据,而且在通常情况下,已经读取过的数据无法再进行读取。如果需要重复读取流中某段数据时,一般的做法是将从流中读取的数据使用数组存储起来,然后根据需要读取数组中的内容即可,但是有些时候,还是有一些特殊的情况的,IO类对于这些都进行了支持。
1、间断性的读取流中的数据
对于某些特殊格式的文件,例如字体文件等,在实际读取数据时不需要顺序进行读取,而只需要根据内容的位置进行读取。这样可以使用流中的skip方法实现。例如:
int n =
fis.skip(100);
该行代码的作用是,以流fis当前位置为基础,当前位置可以是流中的任何位置,向后跳过100个单位(字节流单位为字节,字符流单位是字符),如果再使用read方法继续读取,就是读取跳跃以后新位置的内容,也就相当于跳过了100个单位的内容。
而实际在使用时,实际真正跳过的单位数量作为skip方法的返回值返回。
2、重复读取流中某段数据
当必须重复读取流中同一段数据时,如果对应的流支持mark(标记)的话,则可以重复读取同一段数据。
下面以重复读取控制台输入流System.in为例子,来介绍mark的使用,示例代码如下:
import
java.io.*;
/**
*
mark使用示例
*/
public class MarkUseDemo {
public
static void main(String[] args) {
byte[] b = new byte[1024];
try{
//读取数据
int data =
System.in.read();
//输出第一个字节的数据
System.out.println("第一个字节:" +
data);
//判断该流是否支持mark
if(System.in.markSupported()){
//记忆当前位置,可以从当前位置
//向后最多读取100个字节
System.in.mark(100);
//读取数据
int n =
System.in.read(b);
//输出读取到的内容
System.out.print("第一次读取到的内容:");
for(int i =
0;i < n;i++){
System.out.print(b[i] + " ");
}
System.out.println();
//回到标记位置
System.in.reset();
//重复读取标记位置以后的内容
n =
System.in.read(b);
//输出读取到的内容
System.out.print("第二次读取到的内容:");
for(int i =
0;i < n;i++){
System.out.print(b[i] + " ");
}
System.out.println();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
在该示例中,首先调用System.in流中的read方法,读取流中的第一个字节,并把读取到的数据赋值给data,然后将读取到的第一个字节的数据输出出来。
然后调用System.in流中的markSupported判断该流是否支持mark功能,如果支持的话则markSupported方法将返回true。
如果流System.in支持mark,则标记当前位置,并允许从当前位置开始最多读取后续100个字节的数据,其实IO类内部的只读取这些数据,而不真正从流中将这些数据删除。
后续继续读取流中的数据,如果读取的数据超过100个字节,则mark标记失效,并把读取到的有效数据输出到控制台。
如果需要从标记位置重复读取已经读取过的数据,则只需要调用流对象中的reset方法重置流的位置,使流可以回到mark的位置,如果继续读取的话,则从该位置开始可以向后读取。这样就可以从mark的位置开始,再次读取后续的数据了。
例如在控制台输入123456789,则该程序的执行结果是:
第一个字节:49
第一次读取到的内容:50 51 52 53 54 55 56 57 13 10
第二次读取到的内容:50 51 52 53 54 55 56 57 13
10
其中输入的第一个字节是1,读取时该字符的编码是49,而后续的内容就是流的结构,其中流末尾的13和10是在输入时,添加的回车和换行字符。
11.3.4.3 中文问题
由于JDK设计时,对于国际化支持比较好,所以JDK在实际实现时支持很多的字符集,这样在进行特定字符集的处理时就需要特别小心了。
其实在进行中文处理时,只需要注意一个原则就可以了,这个原则就是将中文字符转换为byte数组时使用的字符集,需要和把byte数组转换为中文字符串时的字符集保持一致,这样就不会出现中文问题了。
当然,如果不想手动实现字符串和byte数组的转换,可以使用DataInputStream和DataOutputStream中的readUTF和writeUTF实现读写字符串。
11.4 总结
关于IO类的使用,还需要在实际开发过程中多进行使用,从而更深入的体会IO类设计的初衷,并掌握IO类的使用。
另外,IO类是Java中进行网络编程的基础,所以熟悉IO类的使用也是学习网络编程必须的一个基础。
分享到:
相关推荐
ABPLC编程软件RSLOGIX入门——组态IO.pdf
java基础——IO流及File-RandomAccessFile对象.docx
JAVA_IO操作总结——节点流和处理流.pdf JAVA_IO操作总结——节点流和处理流.pdf
javaIO流
JAVA-SE入门学习——第九讲IO流
java IO教程,java IO教程,java IO教程,java IO教程java IO教程java IO教程java IO教程java IO教程,java IO教程java IO教程java IO教程java IO教程java IO教程,java IO教程,java IO教程,java IO教程,java IO...
Java图书管理系统(IO流版)(csdn)————程序
Java SE编程入门教程 java IO(共28页).pptx Java SE编程入门教程 java Math(共11页).pptx Java SE编程入门教程 java object(共9页).pptx Java SE编程入门教程 java static final(共24页).pptx Java SE编程...
单片机课程设计——IO口基本输出(仿真代码).zip
设备管理——IO设备(ppt80).pptx
收集了Java IO 文件读写等操作的实例
本文给大家介绍了STM32GPIO——快速IO的使用。
ABPLC编程软件RSLOGIX5000入门2——组态IO.pdf
第8章JavaIO第8章JavaIO第8章JavaIO
蓝桥杯之单片机学习(十三)——IO扩展技术与存储器映射扩展的代码文件
AB_PLC编程软件RSLOGIX5000入门2——组态_IOdoc,提供“AB_PLC编程软件RSLOGIX5000入门2——组态_IO”免费资料下载,本文介绍了编程软件RSLOGIX5000组态_IO的步骤,可供学习使用。
如果没有很好的理解抽象类和接口的概念,那么要想充分的理解IO操作是很难的,在整个IO操作之中,完整的体现了Java语言多态性的设计思想,而且在学习IO的时候必须始终把握住一个原则:“根据使用的子类不同,输入输出...
Java基础入门教程 Java编程技术11 Java IO(2学时)(共30页).ppt Java基础入门教程 Java编程技术12 网络编程(2学时)(共20页).ppt Java基础入门教程 Java编程技术13 JDBC编程(4学时)(共35页).ppt Java基础入门...
java零基础自学 之 JavaIO流处理java零基础自学 之 JavaIO流处理
JavaIO使用例子。