CodeGym /Java 博客 /随机的 /Java 中的输入/输出。FileInputStream、FileOutputStream 和 BufferedI...
John Squirrels
第 41 级
San Francisco

Java 中的输入/输出。FileInputStream、FileOutputStream 和 BufferedInputStream 类

已在 随机的 群组中发布
“嗨!在今天的课程中,我们将继续讨论 Java 中的输入和输出流 ( Java I/O )。这不是关于该主题的第一课,当然也不会是最后一课 :) Java 中的输入/输出。 FileInputStream、FileOutputStream 和 BufferedInputStream 类 - 1因为它碰巧,Java 语言提供了很多处理 I/O 的方法。有相当多的类实现了这个功能,所以我们把它们分成几节课——所以你不会从一开始就感到困惑 :) 过去课程,我们谈到了BufferedReader,以及抽象类InputStreamOutputStream几个后代。今天我们将考虑 3 个新类:FileInputStream FileOutputStream和 BufferedInputStream

文件输出流类

该类的主要目的FileOutputStream是将字节写入文件。 没什么复杂的:)FileOutputStream是抽象类的实现之一OutputStream。在构造函数中,此类的对象采用目标文件(应写入字节的位置)的路径或对象File。我们将检查每个示例:

public class Main { 

   public static void main(String[] args) throws IOException { 

       File file = new File("C:\\Users\\Username\\Desktop\\test.txt"); 
       FileOutputStream fileOutputStream = new FileOutputStream(file); 

       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
}
创建File对象时,我们将所需的路径传递给构造函数。我们不需要提前创建它:如果它不存在,程序会创建它。您也可以在不创建额外对象的情况下通过,只需传递一个带有路径的字符串:

public class Main { 

    public static void main(String[] args) throws IOException { 

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt"); 
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
} 
两种情况下的结果都是一样的。 我们可以打开我们的文件并在那里看到以下内容:

Hi! Welcome to CodeGym — The best site for would-be programmers!
但这里有一个细微差别。尝试连续多次运行上述示例中的代码。然后查看文件并回答这个问题:它有多少行?只有一个。但是你多次运行代码。事实证明,数据每次都被覆盖——旧的被新的取代。如果这不适合我们并且我们需要按顺序写入文件,我们该怎么办?如果我们想连续三次将问候语写入文件怎么办?这一切都非常简单。由于语言无法知道我们在每种情况下需要什么行为,FileOutputStream构造函数可以采用一个额外的参数——boolean append. 如果它的值为真,数据将被写入文件的末尾。如果为 false(默认情况下为 false),任何旧数据都将被删除并由新数据替换。让我们通过运行修改后的代码三次来检查这一点:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt", true); 
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!\r\n"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
} 
文件内容:

Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers!
现在不一样了!在使用 I/O 类时不要忘记这个特性。曾经有一段时间,我在任务上花费了数小时,绞尽脑汁数小时,试图了解我的数据是如何从文件中消失的:)当然,就像其他 I/O 类一样,不要忘记使用该close()方法释放资源。

文件输入流类

FileInputStream相反的目的——从文件中读取字节。正如FileOutputStreaminherits一样OutputStream,这个类派生自InputStream抽象类。我们将在我们的“ test.txt ”文件中写入几行文本:

"So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters"
Java 中的输入/输出。 FileInputStream、FileOutputStream 和 BufferedInputStream 类 - 2这是使用以下方法从文件中读取数据的样子FileInputStream

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt"); 

       int i; 

       while((i=fileInputStream.read())!= -1){ 

           System.out.print((char)i); 

       } 
   } 
}
我们从文件中读取一个字节,将读取的字节转换为字符并显示在控制台上。这是控制台输出:

So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters

缓冲输入流类

我认为,鉴于过去课程中的知识,您可以很容易地说出我们为什么需要这个BufferedInputStream类以及它与FileInputStream:) 相比有什么优势:) 我们已经遇到过缓冲流,所以在继续阅读之前尝试猜测(或记住):) 缓冲流主要用于优化 I/O。 访问数据源,例如从文件中读取,在性能方面是一项昂贵的操作,而访问文件以读取每个字节是一种浪费。这就是为什么BufferedInputStream不是一次一个字节地读取数据,而是以块为单位读取数据,并将它们临时存储在一个特殊的缓冲区中。这让我们可以通过减少访问文件的次数来优化程序。让我们看看这是什么样子的:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt"); 

       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 200); 

       int i; 

       while((i = bufferedInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 
   } 
} 
这里我们创建了一个BufferedInputStream对象。InputStream它的构造函数采用该类或其任何后代的实例,所以FileInputStream会这样做。 作为附加参数,它采用以字节为单位的缓冲区大小。由于这个参数,现在将从文件中读取的数据不是一次一个字节,而是一次 200 个字节!想象一下我们减少了多少文件访问次数。FileInputStream要比较性能,您可以获取一个大文本文件(几兆字节的文本)并使用和比较读取和输出到控制台所花费的时间(以毫秒为单位)BufferedInputStream。下面是演示这两个选项的代码:

public class Main { 

   public static void main(String[] args) throws IOException { 

       Date date = new Date(); 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\textBook.rtf"); 
       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 

       int i; 
       while((i = bufferedInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 

       Date date1 = new Date(); 
       System.out.println((date1.getTime() - date.getTime())); 
   } 
} 

 
public class Main { 

   public static void main(String[] args) throws IOException { 

       Date date = new Date(); 
       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\26951280.rtf"); 

       int i; 
       while((i = fileInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 


       Date date1 = new Date(); 
       System.out.println((date1.getTime() - date.getTime())); 
   }
}
在我的计算机上读取一个 1.5 MB 的文件时,FileInputStream在 ~3500 毫秒内完成了工作,但BufferedInputStream在 ~1700 毫秒内完成了它。如您所见,缓冲流优化了工作,将其减半!:) 我们将继续研究 I/O 课程——待会见!
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION