[Powered by Google Translate] [文件I / O]
[贾森·赫塞豪恩，哈佛大学]
这是CS50，CS50.TV]
当我们想到一个文件，想到什么是Microsoft Word文档，
JPEG图像，或一首MP3歌曲，
和与每个这些不同的方式中的文件类型的交互。
例如，在Word文档中添加文本
一个JPEG图像时，我们可能会裁剪的边缘或修饰的颜色。
然而，引擎盖下的所有的文件在我们的电脑都更
比一个长序列的零和一。
它是由与该文件的特定的应用程序进行交互
决定如何处理这个长序列，并提交给用户。
一方面，一个文件可能看起来只是一个字节，
或8个零和的，并显示在屏幕上的一个ASCII字符。
另一方面，在3个字节，位图图像可能看起来
或24个0的，
并把它们解释为3个十六进制数字
表示红色，绿色，和蓝色的值
在一个像素中的图像。
无论它们看起来像在你的屏幕上，在他们的核心，
文件只不过是不是一个序列的零和一。
因此，让我们的潜水和看我们如何实际操作这些零和一
当它涉及到从文件的写入和读取。
>> 我将首先把它分解成三部分组成的一个简单的过程。
接下来，我将深入到两个代码示例，说明这三个部分。
最后，我会检讨的过程和它的一些最重要的细节。
由于坐落在您的桌面上的任何文件，
做的第一件事是打开它。
在C语言中，我们做到这一点，声明一个指针，指向一个预定义的结构
代表磁盘上的文件。
在这个函数中调用，我们还决定，我们是否要写入或读取的文件。
接下来，我们做了实际的阅读和写作。
有许多专门的功能，我们可以在这部分，
和几乎所有的人都开始用字母“F”，表示文​​件。
最后，类似的小红色的X在右上角的文件在您的计算机上打开，
最后一个函数调用，我们关闭文件。
现在，我们有一个总体思路，我们要做的是什么，
让我们深入到代码。
>> 在这个目录中，我们有两个C文件和其对应的可执行文件。
的的打字机程序需要一个命令行参数，
我们要创建的文件的名称。
在这种情况下，我们叫它doc.txt的。
让我们来运行程序并输入几行。
你好。我的名字是贾森。
最后，我们将键入“退出”。
如果我们现在在这个目录中列出的所有文件，
我们看到一个新的文档存在被称为doc.txt。
刚创建的文件，这个程序。
当然，它也没有什么更比一个长序列的零和一。
如果我们打开这个新文件，
我们看到了3行代码中，我们进入到我们的程序 -
你好。五月的名字是贾森。
但实际上上运行时typewriter.c？
我们感兴趣的是第一行第24行。
在这条线，我们宣布我们的文件指针。
函数，返回this指针，FOPEN，需要两个参数。
第一个是文件名，包括文件的扩展名（如适用）。
回想一下，不影响文件的文件扩展名的最低水平。
我们一直在处理一个长序列的零和一。
但它确实会影响文件的解释和使用哪些应用程序打开。
的FOPEN的第二个参数是一个单一的字母
代表我们打开文件后，我们打算做什么。
这种说法有三个选项 - W，R，和A.
我们选择w在这种情况下，因为我们要写入的文件。
R，你可能已经猜到了，是阅读文件。
一个是附加到文件。
虽然两者w和可用于写入文件，
w将开始编写的文件从一开始就
和潜在的覆盖任何先前已被存储的数据。
默认情况下，我们打开的文件，如果它已经不存在，
是建立在我们的当前工作目录。
但是，如果我们要访问或创建一个文件在不同的位置，
在第一个参数的FOPEN，
除了文件名中，我们可以指定一个文件路径。
虽然这个过程的第一部分是只有一行代码长，
它总是个好习惯，另一组线
检查，以确保该文件被成功打开或创建。
如果FOPEN返回null，我们不希望我们的计划，开拓进取，
这可能发生，如果操作系统的内存
或者，如果我们试图打开一个文件，一个目录，而我们没有适当的权限。
>> 第二部分的过程中发生在打字机的while循环。
我们使用CS50的库函数来获取来自用户的输入，
并假设他们不想退出程序，
我们使用的功能FPUTS的的字符串，并写入的文件。
FPUTS是唯一的众多功能之一，我们可以用它来写的文件。
其他包括的FWRITE，的fputc，甚至fprintf。
不管特定的功能，我们最终使用，虽然，
所有的人都需要知道，通过他们的观点，
至少有两件事情 -
需要写什么，它需要被写入到。
在我们的例子中，输入的字符串，需要编写
计划生育是我们的地方，我们正在编写的指针。
在这个程序中，第二部分的过程是相当简单的。
我们只是一个来自用户的字符串
并直接将其添加到我们的文件，小到没有输入验证或安全检查。
然而，通常情况下，第二部分将占用大量的代码。
最后，第三部分是在第58行，我们关闭文件。
在这里，我们调用fclose，并通过它我们原来的文件指针。
在随后的行中，我们返回零，我们的节目结束的信号。
是的，第三部分是那样简单。
>> 让我们从文件读取。
早在我们的目录中，我们有一个名为printer.c。
让我们运行它与我们刚创建的​​文件 -
doc.txt。
这个程序，顾名思义，会简单地打印出的文件的内容传递给它。
在那里，我们有它。
该行代码中，我们输入了和保存在doc.txt。
你好。我的名字是贾森。
如果我们深入printer.c，
我们看到了很多的代码看起来类似于我们刚刚走过的typewriter.c。
事实上，第22行，在这里我们打开的文件，
第39行，我们关闭了文件，
既是几乎相同的typewriter.c，保存为fopen的第二个参数。
这一次我们从文件中读取，
因此我们选择了R替代的W。
因此，让我们关注的第二个过程的一部分。
在第35行中，在我们的4回路的第二个条件，
我们对fgets拨打电话，
的伴侣功能从之前到FPUTS。
这一次，我们有三个参数。
首先是指针的数组的字符的字符串将被存储。
第二个是要读取的最大字符数。
第三个是我们工作的文件指针。
你会发现，在for循环结束时，与fgets返回null。
有两个原因，这可能发生。
首先，可能发生错误。
其次，更可能的文件，最终达成，并没有更多的字符读。
如果你想知道，有两个功能，使我们能够告诉
其中的原因是这个特殊的空指针的原因。
而且，这并不奇怪，因为他们所要做的工作的文件，
FERROR功能和的FEOF的功能开始用字母“F”。
>> 最后，在一个快速的注意事项有关的文件的功能，我们可以得出结论，
其中，刚才提到的，写的是为FEOF。
通常情况下，你会发现自己使用whil​​e和for循环，逐步读取文件的通过自己的方式。
因此，你需要的方式来结束这些循环后，到达终点这些文件。
，调用FEOF上的文件指针和检查，看它是否是真实的
做到这一点。
因此，一个while循环的条件（文件指针（FP））可能看起来像一个完全合适的解决方案。
不过，说我们有一个线留在我们的文本文件。
我们将进入我们的while循环，按计划，一切都会迎刃而解。
通过下一轮，我们的计划将检查，如果FEOF的FP是真正的，
但是 - 这是了解这里的关键点 -
它不会是真实的，只是还没有。
这是因为是不检查的目的FEOF
如果读出功能的下一个呼叫将命中的文件的结尾，
而是，以检查是否已达到了该文件的结束。
在本实施例的情况下，
阅读我们的文件的最后一行是完全顺利，
但该方案还不知道，我们已经打到最后我们的文件。
这不是一个额外的读出，直到它，计数器结束的文件。
因此，正确的条件将以下内容：
fgets和它的三个参数 - 输出，输出的大小，和FP -
和所有的，不等于空。
这是我们采取的方法在printer.c，
和在这种情况下，循环退出时，后
你可以调用的feof或FERROR退出这个循环的具体理由通知用户。
>> 写入和读取文件，在其最基本的，
三部分组成的一个简单的过程。
首先，我们打开该文件。
第二，我们把一些东西到我们的文件或采取了一些东西的。
第三，我们关闭该文件。
的第一和最后的部分很容易的。
中间部分是棘手的问题所在。
虽然引擎盖下的，我们一直在处理一个长序列的零和一，
它添加了一个抽象层编码时
将序列更接近于我们已经习惯看到的东西。
例如，如果我们正在使用一个24位位图文件，
我们很可能会被读取或写入三个字节的时间。
在这种情况下，这将是有意义的定义和适当的命名
一个结构，是3个字节。
>> 虽然工作的文件可能看起来很复杂，
利用它们，可以让我们做一些真正了不起的。
我们的节目外，我们可以改变世界的状态，
我们可以创造一些生活以外的生活我们的计划，
我们之前创建的程序开始运行，甚至可以改变的东西。
互动的文件是一个真正强大的部分用C语言编程
我很高兴能看到你要创建它的代码来。
我的名字是贾森·赫塞豪恩。这是CS50。
[CS50.TV]
>> [笑]
好吧。一个需要。在这里，我们走了。
当我们想到的一个文件 - “”哦，等等。抱歉。
[笑]好吧。
嘿。
当我们想到一个文件 -
当你想到一个文件 - 好。告诉我，当你准备好了。
哦，太棒了。
虽然从提词器读取似乎是 - 没有。我的坏。