Java 中的字节流与字符流

Byte Stream vs Character Stream in Java

我正在 Java I/O 类 工作。我知道有两种重要的流类型:字节流和字符流。但是......我试图用字节流读写文本文件并且它有效。这是代码:

    File klasor = new File("C:\Java");
    if(!klasor.exists()) klasor.mkdirs();

    File kaynakDosya = new File("C:\Java\kaynak.txt");
    if(!kaynakDosya.exists()) kaynakDosya.createNewFile();

    File hedefDosya = new File("C:\Java\hedef.txt");
    if(!hedefDosya.exists()) hedefDosya.createNewFile();

    FileInputStream kaynak = new FileInputStream(kaynakDosya);
    FileOutputStream hedef = new FileOutputStream(hedefDosya);

    int c;
    while((c = kaynak.read()) != -1) {
        hedef.write(c);
    }

    if(kaynak != null) {
        kaynak.close();
    }

    if(hedef != null) {
        hedef.close();
    }

然后我对字符流做了同样的事情:

    File klasor = new File("C:\Java");
    if(!klasor.exists()) klasor.mkdirs();

    File kaynakDosya = new File("C:\Java\kaynak.txt");
    if(!kaynakDosya.exists()) kaynakDosya.createNewFile();

    File hedefDosya = new File("C:\Java\hedef.txt");
    if(!hedefDosya.exists()) hedefDosya.createNewFile();

    FileReader kaynak = new FileReader(kaynakDosya);
    FileWriter hedef = new FileWriter(hedefDosya);

    int c;
    while((c = kaynak.read()) != -1) {
        hedef.write(c);
    }

    if(kaynak != null) {
        kaynak.close();
    }

    if(hedef != null) {
        hedef.close();
    }

这两个产生了相同的结果。那么,我想知道,为什么我这里不应该使用字节流而是使用字符流呢? (我已经在 Whosebug 上阅读了一些文章以及相关问题,他们是这样说的)我知道字符流会逐个字符地读取它,但这对我有什么好处?或者如果我使用字节流读取字符会出现什么问题?我希望我的问题很清楚。我将不胜感激真实案例。

java.io.FileInputStream javadoc 状态:

FileInputStream is meant for reading streams of raw bytes such as image data. For reading streams of characters, consider using FileReader.

java.io.FileOutputStream javadoc 陈述了足够相似的内容:

FileOutputStream is meant for writing streams of raw bytes such as image data. For writing streams of characters, consider using FileWriter.

FileInputStream/FileOutputStreamFileReader/FileWriter 之间的主要区别之一是前者提供操作字节的方法,而后者提供操作字符的方法。

在您的示例中,当您将一个文件内容复制到另一个文件时,操作 charbyte 并没有太大的区别。
在您的情况下,FileInputStreamBufferedInputStream 似乎更合适。

但是如果你使用一个流来 read/write 个字符 from/into String 个实例, 使用 FileReader/FileWriter 确实简化了事情并使事情变得更清晰。
此外,您还可以将 FileReader/FileWriter 包装到 BufferedReader/BufferedWriter 中,并从字符、数组和行的高效 reading/writting 中受益。

 BufferedWriter writer = new BufferedWriter(new FileWriter("myfile"));
 writer.append(oneString);
 writer.append(oneStringBuffer);
 writer.newLine();

 BufferedReader reader = new BufferedReader(new FileReader("myfile"));
 String currentLine = reader.readLine();

将字符写入面向字节的输出流(或从面向字节的输入流中读取字符)将产生与使用面向字符流相同的结果,前提是流中的所有字符都可以表示为平台默认编码中的单个字节(通常是 UTF-8,但也可能是其他编码)。要对此进行测试,请尝试一个包含需要多个字节才能表示的内容(例如希腊文、西里尔文或阿拉伯文字符)的文件。对于面向字节的流,这些将不起作用。对于面向字符的流,只要两个流都使用支持这些字符的编码(例如 UTF-8)并且输入文件存储在用于输入流的编码中,字符就会被保留。

请注意,您的面向字节的代码实际上并未对此进行测试,因为它只是逐字节复制文件。一切看起来都在工作,但是如果您尝试读取实际字符(例如,将它们与代码中的实际文本进行比较,它将失败。要对此进行测试,请创建一个文件(例如,UTF-8 编码)包含西里尔文文本“Привет!”。然后在代码中,尝试使用面向字节的输入流将该文本读入 String 并测试它是否确实包含您使用

期望的内容
System.out.println("Success: " + "Привет!".equals(input));