I am try to write a buffer so I can remove a lot of null "00" characters in a file. The characters are useless and are completely random. They are wreaking havoc on the searcher in the program. The code below compiles but just seems to hang when a file is passed to it. Any suggestions will be helpful.
void ReadFile(char *name)
{
FILE *dbg;
char *buffer;
unsigned long fileLen;
//Open file
dbg = fopen(dbg, "w+");
if (!dbg)
{
fprintf(stderr, "Unable to open file %s", name);
return;
}
//Get file length
fseek(dbg, 0, SEEK_END);
fileLen = ftell(dbg);
fseek(dbg, 0, SEEK_SET);
//Allocate memory
buffer = (char *)malloc(fileLen+1);
if (!buffer)
{
fprintf(stderr, "Memory error!");
fclose(dbg);
return;
}
//Read file contents into buffer
fread(buffer, fileLen, 1, dbg);
for(i = fileLen-1; i >= 0 && buffer[i] == 0; i--);
i++;
if (i > 0)
{
fwrite(buffer, 1, i, dbg);
}
fclose(dbg);
//Do what ever with buffer
free(buffer);
}
Change
dbg = fopen(dbg, "w+");
to
dbg = fopen(name, "w+");
Also, if you want to read the file, change it then write it, you shouldn't open it with "w+". You should first open the file with "r", read from it, do whatever change you want, then fclose it, then again open it but this time with "w" so that you write over it. After you have opened it in "w"rite mode, you can write the modified buffer back into the file.
You opened a file for writing and then you try to read from it.
Check the return value of fread and all the other calls.
Related
I can't copy the contents of one file to another in C because there is a segmentation fault occurring and I don't know the cause.
I know it has something to do with the syntax of fgets or the way I am giving the size of the buffer.
char* argument = argv[2];
char buffer[argc + 1];
FILE *fp;
FILE *quiz_log;
fp = fopen(argument, "r+");
quiz_log = fopen("quiz.log", "a");
fgets(buffer, 80, fp);
memcpy("quiz.log", buffer, 80);
fclose(quiz_log);
fclose(fp);
Expected: Successful write to file "quiz.log"
Actual: Segmentation Fault: 11
argc has nothing to do with the size of the file, it's the number of command line arguments. So there's no reason to use it as the size of the buffer.
Rather than try to read the file all at once, use a fixed-size buffer and read the file in a loop. Use fread() rather than fgets(), since that just reads one line.
You need to use fwrite() to write to the output file, not memcpy().
#define BUFFER_SIZE 1000
char* argument = argv[2];
char buffer[BUFFER_SIZE];
FILE *fp;
FILE *quiz_log;
fp = fopen(argument, "r");
if (fp == NULL) {
printf("Unable to open input file\n");
exit(1);
}
quiz_log = fopen("quiz.log", "a");
if (quiz_log == NULL) {
printf("Unable to open quiz.log\n");
exit(1);
}
size_t n;
while ((n = fread(buffer, 1, BUFFER_SIZE, fp)) > 0) {
fwrite(buffer, 1, n, quiz_log);
}
fclose(quiz_log);
fclose(fp);
I'm trying to copy the contents of a file, specifically a PDF file into a character array so that I can send it over the network.
I'm using the fopen with fread for this.
//Get the file path
getFilePath();
//Open the file
fopen_s(&fp, filePath, "r");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
//allocate memory
buffer = (char*)malloc(sizeof(char)*size);
int charsTransferred = fread(buffer, 1, size, fp);
fclose(fp);
free(buffer);
I have charsTransferred to see how many characters were transferred over by fread. Using size I can tell how many characters should have been moved over, but obviously I'm not getting that many back. Does anyone know what the issue here could be?
There may be a problem in the part of your code you didn't show.
This works:
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp;
if (fopen_s(&fp, "somepdfile.pdf", "rb"))
{
printf("Failed to open file\n");
exit(1);
}
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
rewind(fp);
char *buffer = (char*)malloc(sizeof(char)*size);
if (!buffer)
{
printf("Failed to malloc\n");
exit(1);
}
int charsTransferred = fread(buffer, 1, size, fp);
printf("charsTransferred = %d, size = %d\n", charsTransferred, size);
fclose(fp);
free(buffer);
}
Firstly you need to open in binary mode if a PDF, which I believe is a binary format. Then the seek end / ftell method tends to fail for very large files, as well as for text files (which have suppressed characters physically on the disk). There isn't a pure ANSI C way of statting a file, but the function stat() is widely avialable, and gives you file size.
I am attempting to write a bittorrent client. In order to parse the file etc. I need to read a torrent file into memory. I have noticed that fread is not reading the entire file into my buffer. After further investigation it appears that whenever the symbol shown below is encountered in the file, fread stops reading the file. Calling the feof function on the FILE* pointer returns 16 indicating that the end of file has been reached. This occurs no matter where the symbol is placed. Can somebody explain why this happens and any solutions that may work.
The symbol is highlighted below:
Here is the code that does the read operation:
char *read_file(const char *file, long long *len){
struct stat st;
char *ret = NULL;
FILE *fp;
//store the size/length of the file
if(stat(file, &st)){
return ret;
}
*len = st.st_size;
//open a stream to the specified file
fp = fopen(file, "r");
if(!fp){
return ret;
}
//allocate space in the buffer for the file
ret = (char*)malloc(*len);
if(!ret){
return NULL;
}
//Break down the call to fread into smaller chunks
//to account for a known bug which causes fread to
//behave strangely with large files
//Read the file into the buffer
//fread(ret, 1, *len, fp);
if(*len > 10000){
char *retTemp = NULL;
retTemp = ret;
int remaining = *len;
int read = 0, error = 0;
while(remaining > 1000){
read = fread(retTemp, 1, 1000, fp);
if(read < 1000){
error = feof(fp);
if(error != 0){
printf("Error: %d\n", error);
}
}
retTemp += 1000;
remaining -= 1000;
}
fread(retTemp, 1, remaining, fp);
} else {
fread(ret, 1, *len, fp);
}
//cleanup by closing the file stream
fclose(fp);
return ret;
}
Thank you for your time :)
Your question is oddly relevant as I recently ran into this problem in an application here at work last week!
The ASCII value of this character is decimal 26 (0x1A, \SUB, SUBSTITUTE). This is used to represent the CTRL+Z key sequence or an End-of-File marker.
Change your fopen mode ("In [Text] mode, CTRL+Z is interpreted as an end-of-file character on input.") to get around this on Windows:
fp = fopen(file, "rb"); /* b for 'binary', disables Text-mode translations */
You should open the file in binary mode. Some platforms, in text (default) mode, interpret some bytes as being physical end of file markers.
You're opening the file in text rather than raw/binary mode - the arrow is ASCII for EOF. Specify "rb" rather than just "r" for your fopen call.
How do I determine if a file is empty? The file is opened by a C program running on the Windows platform. I want to open a file in append mode, and, if empty, first print a header to it.
// Open CSV & write header
report_csv = fopen("SNR.csv", "a+");
if (!report_csv) {
fprintf(stderr, "Unable to open CSV output file...");
return -1;
}
if (!ftell(report_csv)) {
fprintf(report_csv, "Column A;Column B;Column C\n");
}
// ... print data to file
fclose(report_csv);
I was expecting ftell to return the current file size if the file was not empty, which happens because the code above is looped.
However, ftell always returns 0 and the header is printed multiple times.
I know I could fopen it with r and use fseek/ftell/fclose and then fopen it again with a+, but I think it's possible to do this without opening and closing the file multiple times.
Actually, when fopening a file in append mode, the file pointer is initially at the begining of the file. It moves to the end of it as soon as you write something or use fseek.
I just needed to add fseek(report_csv, 0, SEEK_END); before my if (!ftell(report_csv)).
Let's check this.
Code:
#include <stdio.h>
int main(int argc, char **argv) {
FILE *test;
size_t size;
char buf[100];
/* Truncate file */
test = fopen("test", "w");
if (!test) {
fprintf(stderr, "Cannot open file `test`!\n");
return 1;
}
/* Write something */
fprintf(test, "Something. ");
fclose(test);
/* Open in append */
test = fopen("test", "a+");
if (!test) {
fprintf(stderr, "Cannot open `test` in append mode!\n");
return 1;
}
/* Try to get the file size */
size = ftell(test);
printf("File pointer is: %d\n", size);
fseek(test, 0, SEEK_END);
size = ftell(test);
printf("After `fseek(test, 0, SEEK_END)`, the file pointer is: %d\n", size);
/* Append */
fprintf(test, "And that. ");
fclose(test);
/* Same without fseek */
test = fopen("test", "a+");
if (!test) {
fprintf(stderr, "Cannot open `test` in append mode!\n");
return 1;
}
fprintf(test, "Hello! ");
size = ftell(test);
printf("File size is now: %d\n", size);
fclose(test);
/* Try to read */
test = fopen("test", "r");
if (!test) {
fprintf(stderr, "Unable to open `test` for reading!\n");
return 1;
}
printf("File contents:\n\t");
while (test && !feof(test)) {
fgets(buf, sizeof(buf), test);
printf("%s", buf);
}
/* Cleanup & exit */
fclose(test);
printf("\n\nExiting.\n");
return 0;
}
Output:
File pointer is: 0
After `fseek(test, 0, SEEK_END)`, the file pointer is: 11
File size is now: 28
File contents:
Something. And that. Hello!
Exiting.
When opening a file with fopen with the a+ mode, all writing operations will be performed at the end of the file. You can reposition the internal pointer to anywhere in the file for reading, but writing operations will move it back to the end of file. The initial pointer position for reading is at the beginning of the file.
So you need to call an fseek(pFile, 0, SEEK_END) on your FILE pointer.
You can call _stat() and get the value st_size into struct _stat (you dont need open the file).Declared in sys/types.h followed by sys/stat.h
I don´t know Windows programming, but it can help you: http://msdn.microsoft.com/en-us/library/14h5k7ff.aspx
In my code below, the file is being written correctly as far as I can tell. When I look in the file floats.dat I see this stream of binary ÍÌL#33c#ÍÌÜ#ffFAßOeA^#^#bBf6zE33äCff<83>BÍ̦B
However my program always ends up triggering this if statement:
if(fread(inputFloats, sizeof(float), LENGTH, binaryFile) < LENGTH)
{
fprintf(stderr, "Problem reading some or all data from %s\n\n", binaryFileName);
return EXIT_FAILURE;
}
Does anybody see something I've done wrong here? Full code below.
#include <stdlib.h>
#include <stdio.h>
#define LENGTH 10
int main(void)
{
FILE *binaryFile, *textFile;
char *binaryFileName = "floats.dat", *textFileName = "floats.txt";
float floats[LENGTH] = {3.2, 3.55, 6.9, 12.4, 14.332, 56.5, 4003.4, 456.4, 65.7, 83.4};
float inputFloats[LENGTH];
int i;
if((binaryFile = fopen(binaryFileName, "r+")) == NULL)
{
fprintf(stderr, "Problem opening %s", binaryFileName);
}
if(fwrite(floats, sizeof(float), LENGTH, binaryFile) < LENGTH)
{
fprintf(stderr, "Problem writing some or all data to %s\n", binaryFileName);
return EXIT_FAILURE;
}
printf("DATA WRITTEN SUCCESSFULLY\n");
if(fread(inputFloats, sizeof(float), LENGTH, binaryFile) < LENGTH)
{
fprintf(stderr, "Problem reading some or all data from %s\n\n", binaryFileName);
return EXIT_FAILURE;
}
for(i = 0; i < LENGTH; i++)
{
printf("float[%d] = %f\n", i, floats[i]);
}
return EXIT_SUCCESS;
}
You're not working with text data so you should specify a binary mode when opening the file. Use r+b instead of r+
You need to fseek(binaryFile, 0, SEEK_SET) to "rewind" the file after writing. rewind can also be used for this case - fseek allows you to position the read/write pointer wherever you want.
The FILE structure keeps a record of where in the file it is currently pointing. Since you've just written to binaryFile, the file pointer is at the end of what you've written.
You therefore need to rewind the file, using fseek(binaryFile, 0, SEEK_SET); before you read.
You forgot to rewind your file before reading it:
rewind(binaryFile);
When you finish writing to the file, the FILE pointer is at the end of it, so of course if you try reading it will not work. Try using fseek to move the pointer to the beginning of the file before reading.
Please avoid this :
if((binaryFile = fopen(binaryFileName, "r+")) == NULL) {
and prefer this:
binaryFile = fopen(binaryFileName, "rb+");
if(!binaryFile) {