对java中的流的概念认识不是很好,想问一个关于流方面的知识。程序如下:
import java.io.*;
public class TestFileWriter {
public static void main(String[] args) {
FileWriter fw = null;
try {
fw = new FileWriter("d:\\unicode.dat");
for(int c=0;c<=30000;c++){
fw.write(c);
}
fw.close();
} catch (IOException e1) {
e1.printStackTrace();
System.out.println("文件写入错误");
System.exit(-1);
}
}
}
对于上面的这个程序,fw.write(c) 这句为什么写入的是数字,而写入到文件的却是一些字符,但是如果换成fw.write('c');或者fw.write("你好");却是保持不变,而当要写入java的基本数据类型的时候,如long int 这些类型的数的时候就必须要用数据流才可以,这种字节流的"字节"的意义到底是什么,其内部到底是如何进行的,我能不能把一个其它的比如一个视频文件写入到另一个文件中呢?

解决方案 »

  1.   

    首先,fw 是一个 FileWriter,就是 java.io.Writer 类的子类。所谓的 Writer ,就是字符输出流(而不是字节流)。任意一个文件,包括图像、声音、视频文件都是由字节构成的,也就是说字节流可以处理任意类型的文件;而字符文件也是由字节组成的,只不过在读取这些字节之后,文本编辑器按照一定的编码,将一个或几个字节解析成一个文字符号,比如字母和汉字,再将其显示出来罢了。Java 中 Stream 结尾的流就是字节流,Reader 或者 Writer 结尾的流就是字符流。Writer 字符流的目的是一次输出一个 16-bit Unicode 字符,也就是 Java 内部的 char 类型。所以写入文件的并不是数字,而是一个字符。但是为什么这个方法的参数类型为 int 呢?那是因为以下这种用法很好,非常的好:out.write(in.read())。java.io.Reader 类的 read 方法是返回 int 的,所以如果 write 方法的参数为 char,就不能用这种优美的写法了,因为 int 型不能自动转换成 char。那么为什么 read 方法会返回 int 而不是 char 呢?原因在于 read 方法 用 -1(C、C++ 里的 EOF)表示到达文件结尾。int 类型不光能容纳 char 类型(16-bit unsigned,范围 0 - 65535)的所有内容,还能容纳这个 -1。到此,我们知道了为什么 write 方法接收一个 int 类型的参数来写入一个字符。然后,在参数传递进去之后,write 方法将这个 int 的高 16 位舍弃,只使用它的低 16 位(相当于一个 char)。如果你给一个 char 作为参数,就像 fw.write('c'),它会先把 'c' 转换成 int,再使用这个 int 的低 16 位。(还是等于这个 'c')然后就是字符流的输出处理了。因为是 FileWriter 类的对象,所以 fw 使用 JDK 所在平台的默认字符编码(Windows Vista 中文版是 GBK,Linux 是 UTF-8)先将这个 char 编码,得到若干个字节,再将这若干个字节一个一个地写入文件中。(再次说明,文件最终都是由字节构成的,图像、声音、视频文件也不例外)至于你用的 fw.write("你好"),则是另一个接受 String 参数的 write 方法。这个方法相当于将 String 中的每一个 char 传进 write(int) 方法写入文件。如果想用其他的编码代替平台默认编码,就应该构造一个 FileOutputStream 对象,然后用这个对象去构造一个是用特定字符集的 OutputStreamWriter 对象。然后可以读这个文件。还是要注意每个文件实际上都是许多个字节,无论是用 InputStream 还是 Reader 来读这个文件,它们面对的都是一串字节。用字节流读的时候,它直接返回一个字节,而用字符流读的时候,它就会使用平台默认的(或者是我们自己提供的)字符集检测,第一个字节构不构成一个字符?如果不够,再读第二个字节,如果两个字节还不能构成字符,再读第三个,第四个,直到在字符集中找到这些字节能构成的字符为止。找到这个字符后,用 Java 内部使用的字符表示方法(很像 UTF-16 字符集,但不是)再对这个字符进行编码,生成一个 char,然后返回它。也就是说,Reader 每 read 一次,就可能读了文件里的多个字节。至于你说的数字(int)的写入,有两种方法。比如我们有一个 int,13。我们可以这样:
    方法一:将 13 转化成 String,就是字符 '1' 和字符 '3',然后使用字符流按照上面说的方法将这两个字符分别写入文件中。例如用 UTF-8 字符集时,字符 '1' 和 '3' 都只用一个字节表示,所以我们实际上写入了两个字节到文件中。方法二:直接将 00000000 00000000 00000000 00001101 这几个字节也就是 int 类型 13 的二进制表示使用字节流写入文件中,这也就是 DataOutputStream 的 writeInt 所做的事情。显而易见,这种方法向文件里写入了四个字节。附:如果说的不清,我再继续解释。
      

  2.   

    弄错了,就是 UTF-16 字符集。抱歉。