- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在打开一个文件并将其内容放入一个字符串缓冲区中,以便对每个字符进行一些词法分析。这样做比使用后续数量的 fread() 调用能够更快地完成解析,并且由于源文件将始终不超过几 MB,我可以放心全部内容文件的一部分将始终被读取。
但是,在检测何时没有更多数据需要解析时似乎有些麻烦,因为ftell() 经常给我一个整数值,该整数值高于文件中的实际字符数.如果尾随字符始终为 -1,则使用 EOF (-1) 宏不会有问题...但情况并非总是如此...
以下是我打开文件并将其读入字符串缓冲区的方式:
FILE *fp = NULL;
errno_t err = _wfopen_s(&fp, m_sourceFile, L"rb, ccs=UNICODE");
if(fp == NULL || err != 0) return FALSE;
if(fseek(fp, 0, SEEK_END) != 0) {
fclose(fp);
fp = NULL;
return FALSE;
}
LONG fileSize = ftell(fp);
if(fileSize == -1L) {
fclose(fp);
fp = NULL;
return FALSE;
}
rewind(fp);
LPSTR s = new char[fileSize];
RtlZeroMemory(s, sizeof(char) * fileSize);
DWORD dwBytesRead = 0;
if(fread(s, sizeof(char), fileSize, fp) != fileSize) {
fclose(fp);
fp = NULL;
return FALSE;
}
这似乎总是工作得很好。接下来是一个简单的循环,它一次检查一个字符的字符串缓冲区的内容,如下所示:
char c = 0;
LONG nPos = 0;
while(c != EOF && nPos <= fileSize)
{
c = s[nPos];
// do something with 'c' here...
nPos++;
}
文件的结尾字节通常是一系列 ý (-3) 和 « (-85) 字符,因此永远不会检测到 EOF。相反,循环简单地继续向前,直到 nPos 最终的值高于 fileSize -- 这对于正确的词法分析是不可取的,因为您通常最终会跳过最后的流中的标记在末尾省略了换行符。
在 Basic Latin 字符集中,假设 EOF char 是任何具有负值的字符是否安全?或者也许有更好的方法来解决这个问题?
#EDIT: 我刚刚尝试将 feof() 函数实现到我的循环中,但还是一样,它没有似乎也没有检测到 EOF。
最佳答案
将评论组合成答案...
当您无法读取时,您会泄漏内存(可能是大量内存)。
您不允许在读取的字符串末尾使用空终止符。
当内存即将被文件中的数据覆盖时,将内存清零毫无意义。
您的测试循环正在越界访问内存; nPos == fileSize
超出了您分配的内存的末尾。
char c = 0;
LONG nPos = 0;
while(c != EOF && nPos <= fileSize)
{
c = s[nPos];
// do something with 'c' here...
nPos++;
}
还有其他问题,之前没有提到。您确实问过是否“假设 EOF 字符是任何具有负值的字符是安全的”,对此我的回答是否。这里有几个问题会影响 C 和 C++ 代码。第一个是普通 char
可能是有符号类型或无符号类型。如果类型是无符号的,那么你永远不能在其中存储负值(或者更准确地说,如果你试图将负整数存储到无符号字符中,它将被截断为最低有效位 8* 位,将被视为阳性。
在上面的循环中,可能会出现两个问题之一。如果 char
是有符号类型,则有一个字符(ÿ、y-umlaut、U+00FF、带分音符的拉丁文小写字母 Y、Latin-1 代码集中的 0xFF)具有相同的类型值为 EOF(始终为负,通常为 -1)。因此,您可能会过早地检测到 EOF。如果 char
是无符号类型,则永远不会有任何字符等于 EOF。但是对字符串的 EOF 测试存在根本性的缺陷; EOF 是 I/O 操作的状态指示符,而不是字符。
在 I/O 操作期间,只有在尝试读取不存在的数据时才会检测到 EOF。 fread()
不会报告 EOF;您要求阅读文件中的内容。如果您在 fread()
之后尝试了 getc(fp)
,您将得到 EOF,除非文件在您测量它的长度后增长了。由于 _wfopen_s()
是一个非标准函数,它可能会影响 ftell()
的行为方式及其报告的值。 (但你后来证实情况并非如此。)
请注意,fgetc()
或 getchar()
等函数被定义为以正整数形式返回字符,以不同的负值形式返回 EOF。
If the end-of-file indicator for the input stream pointed to by
stream
is not set and a next character is present, thefgetc
function obtains that character as anunsigned
converted to an
charint
.If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of- file indicator for the stream is set and the
fgetc
function returns EOF. Otherwise, thefgetc
function returns the next character from the input stream pointed to bystream
. If a read error occurs, the error indicator for the stream is set and thefgetc
function returns EOF.289)289) An end-of-file and a read error can be distinguished by use of the
feof
andferror
functions.
这表明 EOF 如何与 I/O 操作上下文中的任何有效字符分开。
你的评论:
As for any potential memory leakage... At this stage in my project, memory leaks are one of many problems with my code which, as of yet, are of no concern to me. Even if it didn't leak memory, it doesn't even work to begin with, so what's the point? Functionality comes first.
在初始编码阶段阻止错误路径中的内存泄漏比稍后返回并修复它们更容易——因为您可能不会发现它们,因为您可能不会触发错误条件。但是,重要程度取决于该计划的目标受众。如果这是一次性的编码类(class),你可能没问题。如果你是唯一会使用它的人,你可能会没事。但是,如果它将被数以百万计地安装,您将无法在所有地方 retrofit 支票。
I have swapped _wfopen_s() with fopen() and the result from ftell() is the same. However, after changing the corresponding lines to LPSTR s = new char[fileSize + 1], RtlZeroMemory(s, sizeof(char) * fileSize + 1); (which should also null-terminate it, btw), and adding if(nPos == fileSize) to the top of the loop, it now comes out cleanly.
好的。您也可以只使用 s[fileSize] = '\0';
来终止数据,但是使用 RtlZeroMemory()
可以达到相同的效果(但如果该文件的大小为数兆字节)。但我很高兴各种意见和建议帮助您回到正轨。
* 理论上,CHAR_BITS 可能大于 8;实际上,它几乎总是 8 位,为简单起见,我假设这里是 8 位。如果 CHAR_BITS 为 9 或更大,则讨论必须更加细致,但净效果大致相同。
关于c++ - 将文件读入字符串缓冲区并检测 EOF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15330202/
今天我在一个 Java 应用程序中看到了几种不同的加载文件的方法。 文件:/ 文件:// 文件:/// 这三个 URL 开头有什么区别?使用它们的首选方式是什么? 非常感谢 斯特凡 最佳答案 file
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我有一个 javascript 文件,并且在该方法中有一个“测试”方法,我喜欢调用 C# 函数。 c# 函数与 javascript 文件不在同一文件中。 它位于 .cs 文件中。那么我该如何管理 j
需要检查我使用的文件/目录的权限 //filePath = path of file/directory access denied by user ( in windows ) File fil
我在一个目录中有很多 java 文件,我想在我的 Intellij 项目中使用它。但是我不想每次开始一个新项目时都将 java 文件复制到我的项目中。 我知道我可以在 Visual Studio 和
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a software
我有 3 个组件的 Twig 文件: 文件 1: {# content-here #} 文件 2: {{ title-here }} {# content-here #}
我得到了 mod_ldap.c 和 mod_authnz_ldap.c 文件。我需要使用 Linux 命令的 mod_ldap.so 和 mod_authnz_ldap.so 文件。 最佳答案 从 c
我想使用PIE在我的项目中使用 IE7。 但是我不明白的是,我只能在网络服务器上使用 .htc 文件吗? 我可以在没有网络服务器的情况下通过浏览器加载的本地页面中使用它吗? 我在 PIE 的文档中看到
我在 CI 管道中考虑这一点,我应该首先构建和测试我的应用程序,结果应该是一个 docker 镜像。 我想知道使用构建环境在构建服务器上构建然后运行测试是否更常见。也许为此使用构建脚本。最后只需将 j
using namespace std; struct WebSites { string siteName; int rank; string getSiteName() {
我是 Linux 新手,目前正在尝试使用 ginkgo USB-CAN 接口(interface) 的 API 编程功能。为了使用 C++ 对 API 进行编程,他们提供了库文件,其中包含三个带有 .
我刚学C语言,在实现一个程序时遇到了问题将 test.txt 文件作为程序的输入。 test.txt 文件的内容是: 1 30 30 40 50 60 2 40 30 50 60 60 3 30 20
如何连接两个tcpdump文件,使一个流量在文件中出现一个接一个?具体来说,我想“乘以”一个 tcpdump 文件,这样所有的 session 将一个接一个地按顺序重复几次。 最佳答案 mergeca
我有一个名为 input.MP4 的文件,它已损坏。它来自闭路电视摄像机。我什么都试过了,ffmpeg , VLC 转换,没有运气。但是,我使用了 mediainfo和 exiftool并提取以下信息
我想做什么? 我想提取 ISO 文件并编辑其中的文件,然后将其重新打包回 ISO 文件。 (正如你已经读过的) 我为什么要这样做? 我想开始修改 PSP ISO,为此我必须使用游戏资源、 Assets
给定一个 gzip 文件 Z,如果我将其解压缩为 Z',有什么办法可以重新压缩它以恢复完全相同的 gzip 文件 Z?在粗略阅读了 DEFLATE 格式后,我猜不会,因为任何给定的文件都可能在 DEF
我必须从数据库向我的邮件 ID 发送一封带有附件的邮件。 EXEC msdb.dbo.sp_send_dbmail @profile_name = 'Adventure Works Admin
我有一个大的 M4B 文件和一个 CUE 文件。我想将其拆分为多个 M4B 文件,或将其拆分为多个 MP3 文件(以前首选)。 我想在命令行中执行此操作(OS X,但如果需要可以使用 Linux),而
快速提问。我有一个没有实现文件的类的项目。 然后在 AppDelegate 我有: #import "AppDelegate.h" #import "SomeClass.h" @interface A
我是一名优秀的程序员,十分优秀!