C 打开无windows行结尾的非文本文件
我接管了一个使用以下功能读取文件的项目:C 打开无windows行结尾的非文本文件,c,text-files,fopen,C,Text Files,Fopen,我接管了一个使用以下功能读取文件的项目: char *fetchFile(char *filename) { char *buffer; int len; FILE *f = fopen(filename, "rb"); if(f) { if(verbose) { fprintf(stdout, "Opened file %s successfully\n", filename); } fse
char *fetchFile(char *filename) {
char *buffer;
int len;
FILE *f = fopen(filename, "rb");
if(f) {
if(verbose) {
fprintf(stdout, "Opened file %s successfully\n", filename);
}
fseek(f, 0, SEEK_END);
len = ftell(f);
fseek(f, 0, SEEK_SET);
if(verbose) {
fprintf(stdout, "Allocating memory for buffer for %s\n", filename);
}
buffer = malloc(len + 1);
if(buffer) fread (buffer, 1, len, f);
fclose (f);
buffer[len] = '\0';
} else {
fprintf(stderr, "Error reading file %s\n", filename);
exit(1);
}
return buffer;
}
之所以使用rb
模式,是因为有时文件可以是电子表格,因此我希望信息以文本文件的形式存在
该程序在linux机器上运行,但要读取的文件来自linux和windows
我不确定哪种方法更好不让windows行结尾弄乱我的代码
我正在考虑在这个函数开始时使用dos2unix
。
我也曾想过以r
模式打开,但我相信在打开非文本文件时可能会把事情搞砸
我想更好地理解使用以下各项之间的区别:
dos2unix
r
vsrb
模式注意:我相信我理解
r
vsrb
模式,但如果您能解释为什么它是针对这种特定情况的一个好的或坏的解决方案(我认为它不好,因为有时它会打开电子表格,但我不确定) 代码只是将文件内容复制到分配的缓冲区中。UNIX方式(YMMV)是只对文件进行内存映射,而不是读取它。快得多
// untested code
void* mapfile(const char *name)
{
int fd;
struct stat st;
if ((fd = open(name, O_RDONLY)) == -1)
return NULL;
if (fstat(fd, &st)) {
close(fd);
return NULL;
}
void *p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, 0, fd);
close(fd);
if (p == (void *)MAP_FAILED)
p = NULL;
return p;
}
沿着这条路线的一些东西会起作用。如果还想写入文件,请调整设置
如果我的理解是正确的,则使用rb
模式,因为有时文件可以是电子表格,因此程序只需要文本文件中的信息
你似乎不确定,虽然也许你理解正确,但你的解释并没有给我任何信心
C知道两种截然不同的流:二进制流和文本流。二进制流只是一个有序的字节序列,按原样写入和/或读取,无需任何转换。另一方面,
文本流是按顺序排列的字符序列
行,每行由零个或多个字符加上
终止新行字符。最后一行是否需要
终止新行字符是实现定义的字符
可能必须在输入和输出时添加、更改或删除到
遵守主机中表示文本的不同约定
环境因此,不需要一对一的通信
在流中的字符和外部流中的字符之间
陈述。[…]
()
对于某些实现,如POSIX兼容的实现,这是一个没有区别的区别。对于其他实现,例如针对Windows的实现,差异很重要。特别是在Windows上,文本流在外部表示法中的回车/换行对和内部表示法中的换行(仅)之间进行动态转换
您的fopen()
模式中的b
指定文件应作为二进制流打开,也就是说,不会对从文件读取的字节执行翻译。这是否正确取决于您的环境和应用程序的需求。然而,这在Linux或其他Unix上是没有意义的,因为在这样的系统上,文本流和二进制流之间没有明显的区别
dos2unix
将输入文件中的回车/换行符对转换为单行换行符(换行符)。这将把Windows样式的文本文件或带有混合Windows/Unix行终止符的文本文件转换为Unix文本文件约定。如果文件中同时包含Windows样式和Unix样式的行终止符,则此错误是不可逆的,而且如果文件最初不是文本文件,则可能会损坏文件
如果您的输入有时是二进制文件,则以二进制模式打开是合适的,而通过dos2unix
进行转换可能不是。如果是这种情况,并且您还需要翻译文本文件行终止符,那么您首先需要一种方法来区分哪种情况适用于任何特定文件——例如,通过命令行参数或通过libmagic预分析文件。然后必须为文本文件提供不同的处理方式;你的主要选择是
fetchFile()
函数这会在非Windows系统上运行吗?在非Windows系统中,您有时会读取Windows格式的文本文件(Windows
“\r\n”
行结尾)?如果在包含Windows行结尾的文件的Windows系统上运行此操作,则使用二进制模式将不会将“\r\n”
转换为纯“\n”
。另一方面,如果您在非Windows系统上使用此选项来读取以Windows行结尾的文件,则我建议您使用使用文本的代码来处理这些文件。我更新了我的问题以解决您的问题。让我知道这是否足够,或者我是否应该添加更多细节。你的程序正在读取什么样的文件?文本文件还是二进制(非文本)文件?两者都有,有时会有一些电子表格。你事先不知道吗?或者你能猜到文件的结尾吗?如果您读入一个真正的二进制文件,而该文件意外地包含字节序列“\r”、“\n”,会发生什么。如果我想象你从某个.exe文件中删除了这个…这并不能真正回答问题。也许,也许不是。该代码执行相同的操作,并消除了\r\n问题。现在OP还有一个选择,这很好。嗯,有一个区别,零终止符。所以我的备选方案也必须返回文件的长度。@BjornA:它如何消除\r\n
问题?代码仍然需要处理包含CR或CR+LF的文件。(这在任何情况下都不是一个困难的问题)。我们没有完整的程序,所以我只是在这里猜测。我想