[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] [笑] 好吧。一个需要。在这里,我们走了。 当我们想到的一个文件 - “”哦,等等。抱歉。 [笑]好吧。 嘿。 当我们想到一个文件 - 当你想到一个文件 - 好。告诉我,当你准备好了。 哦,太棒了。 虽然从提词器读取似乎是 - 没有。我的坏。