FileWriter(String fileName):采用这种方式创建文件,该文件就会被创建到指定目录下,如果该目录下已有同名文件,将覆盖。也就是说每次new都要重新创建,原来数据就没有了。
FileWriter(String fileName, boolean append):采用这种方式,并给append赋值true,如果不存在则创建新文件,如果已存在同名文件,则不覆盖,并且会在文件末尾处续写新的数据,原来数据不会丢失。
在IO流操作的异常处理中,输入流,最后关闭流操作的时候,要对每个流的close分别去try、catch。读取流不用。
在windows系统中,换行是由两个字符来表示:\r\n,其中\r是回车符(ASCII码13),\n是换行符(ASCII码10),而在Linux/Unix里,用\n就是换行。如果用\n换行的文本用记事本打开时会没有换行(有的显示是个小黑框),而用\r\n结尾的文件在Linux的vi中显示时会将\r显示成^M。复杂一点的编辑工具会既识别\r\n也识别\n,比如EditPlus。
中文操作系统默认编码是GBK。支持中文的编码表有两个,分别是UTF-8(万国码)、GBK。在UTF-8中,每个字符占用的字节数是变长的,能用几个字节表示完,就用几个字节表示完(节省容量),比如一个英文字母占用的是一个字节,而一个汉字占用三个字节。
在GBK中,一个英文字符占用一个字节,一个汉字占用两个字节。
FileReader(String fileName)在创建时就要保证文件的存在,如果不存在会抛出FileNotFoundException,它是IOException的一个子类。
Writer类的写方法:
void write(char[] cbuf):写入字符数组。
abstract void write(char[] cbuf, int off, int len):写入字符数组的某一部分。
void write(int c):写入单个字符。
void write(String str):写入字符串。
void write(String str, int off, int len):写入字符串的某一部分。
Reader类的读方法:
int read():读取单个字符。返回该字符的int值。
int read(char[] cbuf):将字符读入数组。返回读取的字符数,如果已到达流末尾则返回 -1。
abstract int read(char[] cbuf, int off, int len):将字符读入数组的某一部分。 cbuf-目标缓冲区,off-开始存储字符处的偏移量,len-要读取的最多字符数。返回读取的字符数,如果已到达流的末尾,则返回 -1。
long skip(long n):跳过n个字符。返回实际跳过的字符数。
疑问①:read(char[] cbuf)返回的是读到的字符数,若到末尾返回-1,那么该方法有没有返回0的可能呢?
论坛里朋友们的回答是这样,read(char[] cbuf) 返回的是字符数组的长度,当数组为"null"时,即为0。
疑问②:
关于用字符流和字节流读取文本文件的例子:
文本文件内容如下:
abcde
fgh你好
代码如下:
import java.io.*;
class FileStreamTest
{
public static void main(String[] args) throws IOException
{
readerMode();
streamMode();
}
public static void readerMode() throws IOException
{
System.out.println("-------------------readerMode---------------------");
FileReader in = new FileReader("3.txt");
char[] buf = new char[1024];
int len = 0;
while((len = in.read(buf)) != -1)
{
System.out.println("len="+len);
System.out.println(new String(buf,0,len));
}
in.close();
}
public static void streamMode() throws IOException
{
System.out.println("-------------------streamMode---------------------");
FileInputStream in = new FileInputStream("3.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len = in.read(buf)) != -1)
{
System.out.println("len="+len);
System.out.println(new String(buf,0,len));
}
in.close();
}
}
用字符流读取时,得到的总长度是12,而为什么用字节流读取时,得到的却是14?
应该这样理解:字符流读取时,返回的是字符的总个数,而一个中文或者一个英文字母,都是一个字符。所以加上回车换行\r\n,一共12个字符。而字节流读取时,返回的是字节的总个数,在读取文件时,它会按照默认的字符集(GBK)去找相应的编码,而在GBK编码表中,一个英文字母占一个字节,一个中文汉字占两个字节,这样加上回车换行\r\n,一共是14个字节。
读取键盘录入的常用写法(一次读取一行数据):
BufferedWriter bufr = new BufferedWriter(new OutputStreamWriter(System.out));
疑问③:
毕老师Java基础视频19天-21的视频中,写了这样一个程序:
import java.io.*;
class ExceptionInfo {
public static void main(String[] args) throws FileNotFoundException {
try {
int[] arr = new int[2];
System.out.println(arr[3]);
} catch (Exception e) {
e.printStackTrace(new PrintStream("a.txt"));
}
}
}
为什么在main方法中,既然大的异常Exception被捕捉了,还能抛出IOException异常,这样做为什么可以?
原因是try/catch了解可能出现的异常,并可以将其捕捉,在catch里进行一些操作。而catch里边如果某些操作也可能出现异常时,可以选择继续catch,或者throw。即,一个异常对应一个catch或者一个throw,要么将其捕获处理,要么抛出交给调用此方法的模块处理(主函数抛了,会由虚拟机处理)。