1、字符流
字符流用于处理文本文件。所有字符流都继承于抽象类Reader和Writer两个父类。其中Reader为读取字符流的父类, Writer为写入字符流的父类。
Reader
方法 | 描述 |
---|---|
int read() | 从流中读取一个字符,并将其返回,读到末尾返回-1 |
int read(char[] buffer) | 将流中读出的字符放到字符数组buffer中,返回读出的字符数 |
int read(char[] buffer, int off,int len) | 将流中指定位置off开始读取数据的前len个字符,并将其读入字节型数据中。读取完毕,返回-1 |
void close() | 关闭输入流,并释放所有与该流相关联的系统资源 |
分支结构
Writer
方法 | 描述 |
---|---|
void write(int c) | 将参数c的低16位组成字符写入流中 |
void write(char[] buffer) | 将字符数组buffer中的字符写入流中 |
void write (char[] buffer,int off,int len) | 将字符数组buffer中从off开始的len个字符写入流中 |
void write(String str) | 将str字符串写入流中 |
void flush() | 刷新该输出流,并强制写出所有缓冲输出字节 |
void close() | 关闭输入流,并释放所有与该流相关联的系统资源 |
分支结构
字符流类的用法和字节流类的用法大致相同。因此,下面我们同样将字符流分为低级流和高级流,并做简单介绍。
低级流
字符流中的低级流包括:
- 对内存数组进行操作的CharArrayReader和CharArrayWriter类,与ByteArrayInputStream和ByteArrayOutputStream类似,其数据源为内存中的字符数组。
- 对内存中的String对象进行操作的StringReader和StringWriter类,其数据源为内存中的String对象。
- 对线程管道进行操作的PipedReader和PipedWriter类,与PipedInputStream和PipedOutputStream类似,其数据源为线程管道。
- 对文本文件进行读写操作的FileReader和FileWriter类,与FileInputStream和FileOutputStream类似,其数据源为磁盘文件。FileReader和FileWriter按照本地操作系统平台的默认字符编码,读写文件。
代码FileReader示例:
private static void reader() {
String path = "F:"+File.separator+
"包"+File.separator+"sss"
+File.separator+"ss"+
File.separator+"s"+
File.separator+"FileWriter.txt";
FileReader f = null;
try {
f = new FileReader(path);
char[] b = new char[1024];
int i = 0,j=0;
while((i = f.read(b)) != -1) {
for (char c : b) {
if(i == j) {break;}
System.out.print(c);
j++;
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
f.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
高级流
字符流中常用的高级流包括:
- 缓冲流:包括BufferedReader和BufferedWriter类,利用缓冲区来提高读写数据的效率。
- 转换流:用于字节数据到字符数据之间的转换,包括InputStreamReader和OutputStreamWriter。
- 打印输出流:包括PrintWriter类,允许将基本类型数据打印输出到字符串流中,PrintWriter带有带自动刷新(Flush)功能。
代码转换流 示例:
//字节转字符 将字节文件读取为字符放入内存中
private static void inputStreamReader() {
// TODO Auto-generated method stub
InputStreamReader isr = null;
try {
String path = "F:"+File.separator+
"包"+File.separator+"sss"
+File.separator+"ss"+
File.separator+"s"+
File.separator+"OutputStreamWriterDemo.txt";
//在字节流中取出数据为字符流
isr = new InputStreamReader(new FileInputStream(path),"utf-8");
//使用BufferedReader 可以读取一行
BufferedReader br = new BufferedReader(isr);
// byte[] c = new byte[20];
// in.read(c);
// System.out.println("转换前读取:" + Arrays.toString(c));
System.out.println("转换后的读取:");
// String str = null;
// while((str= br.readLine())!= null) {
// System.out.println(str);
// }
StringBuffer sb = new StringBuffer();
int i =0;
while((i = isr.read())!= -1) {
sb.append((char)i);
}
System.out.println(sb);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
isr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//字符转字节 字符在内存中转换为字节存入文件
private static void outputStreamWriter() {
// TODO Auto-generated method stub
OutputStreamWriter osw = null;
BufferedWriter bw = null;
try {
String path = "F:" + File.separator + "包" + File.separator + "sss" + File.separator + "ss" + File.separator
+ "s" + File.separator + "OutputStreamWriterDemo.txt";
// 使用OutputStreamWriter 写入一个字节中
osw = new OutputStreamWriter(new FileOutputStream(path), "utf-8");
bw = new BufferedWriter(osw);
bw.write("这个是第一行!");
bw.newLine();
bw.write("这是第二行!");
bw.newLine();
bw.newLine();
bw.write("这是第四行!!");
bw.flush();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
bw.close();
osw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2、对Java I/O库中的流类使用原则:
一、按数据源分类
- 如果数据源是文件,对于字节流,使用FileInputStream和FileOutputStream;对于字符流,使用FileReader和 FileWriter。
- 如果数据源是字节数组byte[],则使用ByteArrayInputStream和ByteArrayOutputStream。
- 如果数据源是字符数组Char[],则使用CharArrayReader和CharArrayWriter。
- 如果数据源是String对象,对于字节流,则使用StringBufferInputStream和StringBufferOutputStream;对于字符流,则使用StringReader和StringWriter。
- 如果数据源是网络数据流,对于字节流,使用InputStream和OutputStream;对于字符流,使用Reader和Writer。
二、按是否格式化输出分:要格式化输出,则使用PrintStream或PrintWriter。
三、按是否要缓冲分,要缓冲的话,对于字节流使用BufferedInputStream和BufferedOutputStream;对于字节流,使用BufferedReader和BufferedWriter。
四、按数据格式分
- 二进制格式(只要不能确定是纯文本的):使用InputStream、OutputStream 及其所有带 Stream结束的子类。
- 纯文本格式(含纯英文与汉字或其他编码方式):使用Reader、Writer 及其所有带 Reader、Writer 的子类。
五、按输入输出分
- 输入:使用Reader、InputStream 类型的子类。
- 输出:使用Writer、OutputStream 类型的子类。
六、特殊需要
- 从Stream到Reader、Writer的转换类:InputStreamReader、OutputStreamWriter。
- 对象输入输出:ObjectInputStream、ObjectOutputStream。
- 线程间通信:PipeInputStream、PipeOutputStream、PipeReader、PipeWriter。
- 合并输入:SequenceInputStream。
- 更特殊的需要:PushbackInputStream、PushbackReader、LineNumberInputStream、LineNumberReader。
在不考虑特殊需求的情况,决定使用哪个类以及它的构造进程的一般准则如下:
首先,考虑最原始的数据格式是什么:原则四。
第二,是输入还是输出:原则五。
第三,是否需要转换流:原则六第1点。
第四,数据源是什么:原则一。
第五,是否要缓冲:原则三(特别注明:一定要注意的是readLine()是否有定义,有什么比 read()、write()更特殊的输入或输出方法)。
第六,是否要格式化输出:原则二。