3

我正在研究 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();
    }

这两个产生了相同的结果。所以,我想知道,为什么我不应该在这里使用字节流而使用字符流?(我在stackoverflow上阅读了一些文章以及相关问题,他们这么说)我知道字符流会逐个字符地读取它,但这给我带来了什么好处?或者如果我使用字节流读取字符会出现什么问题?我希望我的问题很清楚。我会欣赏真实案例。

4

2 回答 2

2

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

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

System.out.println("Success: " + "Привет!".equals(input));
于 2017-10-22T13:54:53.753 回答
1

java.io.FileInputStreamjavadoc 状态:

FileInputStream 用于读取原始字节流,例如图像数据。要读取字符流,请考虑使用 FileReader。

java.io.FileOutputStreamjavadoc 声明了一些类似的东西:

FileOutputStream 用于写入原始字节流,例如图像数据。要写入字符流,请考虑使用 FileWriter。

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

在您的示例中,当您将文件内容复制到另一个文件中时,操作charbyte不会产生很大的不同。
在您的情况下, aFileInputStream或 aBufferedInputStream似乎更合适。

但是,如果您使用流从/向String实例中读取/写入字符,则使用FileReader/FileWriter确实可以简化事情并使事情变得更清晰。
此外,您还可以换FileReader/FileWriterBufferedReader/BufferedWriter并从字符、数组和行的高效读/写中受益。

 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();
于 2017-10-22T13:54:46.110 回答