I am using C Script within Siemens WinCC 7.0 to read a text file containing source and destination comma separated e.g.
C:\Users\Administrator\Desktop\C File Transfer Test\Source\Cat.txt,P:\Cat.txt
C:\Users\Administrator\Desktop\C File Transfer Test\Source\Cat1.txt,P:\Cat1.txt
C:\Users\Administrator\Desktop\C File Transfer Test\Source\Cat2.txt,P:\Cat2.txt
C:\Users\Administrator\Desktop\C File Transfer Test\Source\Cat3.txt,P:\Cat3.txt
C:\Users\Administrator\Desktop\C File Transfer Test\Source\Cat4.txt,P:\Cat4.txt
I am using the following code to open this file and loop through moving the files from source to destination
#include "apdefap.h"
void File_Transfer()
{
#define MODUL "CopyProjekt "
char pathIn[100];
char pathOut[100];
char szProjektname[255];
FILE * fpInFile ;
FILE * fpOutFile ;
FILE *TempSource;
FILE *TempDestination;
#pragma code ("kernel32.dll")
BOOL CopyFileA(LPCTSTR,LPCTSTR,BOOL);
#pragma code ()
DM_DIRECTORY_INFO dmDirInfo;
DM_PROJECT_INFO dmProjectInfo;
CMN_ERROR dmError;
char *source;
char *destination;
char line[1000];
char * tokens;
char *tempTokens;
int i;
char tempString[1000];
if (DMGetProjectDirectory("PDLRT", szProjektname, &dmDirInfo, &dmError )!= NULL)
{
strcat(pathIn , dmDirInfo.szProjectDir) ;
strcat(pathOut, dmDirInfo.szProjectDir) ;
strcat(pathIn ,"FilesForTransfer\\FileData.txt");
strcat(pathOut ,"FilesForTransfer\\FileDataTemp.txt");
//(NULL,pathIn ,"2", MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL);
}
//Open the file containing the folder names and paths
fpInFile = fopen(pathIn,"r" );
fpOutFile = fopen(pathOut,"w" );
while (fgets(line,sizeof line,fpInFile) != NULL)
{
MessageBox(NULL,line,"Read Line",MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL);
tempTokens = line;
tokens = strtok(tempTokens ,",");
while (tokens != NULL)
{
if (i == 0)
{
source = tokens ;
}
else
{
destination = tokens ;
}
i = i + 1;
//read the tokens again
tokens = strtok(NULL ,",");
}
//MessageBox(NULL,source ,destination, MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL);
//Move the file from source to destination
//if (CopyFileA(source,destination,FALSE) != 0)
if (rename(source ,destination )!=0)
{
MessageBox(NULL,"FAILED" ,"Transfer", MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL);
}
else
{
MessageBox(NULL,"PASSED","Transfer",MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL);
}
}
//rename(source,destination)
//fputs(tempstring,fpOutFile );
fclose(fpInFile );
fclose(fpOutFile );
remove(pathIn);
rename(pathOut ,pathIn );
//MessageBox(NULL,"done" ,"Done" , MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL);
}
The message boxes are executing properly every time and the source and destination will be displayed correctly. However only the last file rename will work. If there is only one line in the reference file of source,destination then it will work fine. If there are more than one it will only work on the last.
From what I can work out the code is running through the loop properly and getting the right data from the lookup file but the rename is just not working properly.
Any ideas would be appreciated.
Thanks
fgets() stores the new-line character in the buffer it is populating if found:
Reads at most count - 1 characters from the given file stream and stores them in str. The produced character string is always NULL-terminated. Parsing stops if end-of-file occurs or a newline character is found, in which case str will contain that newline character.
So the destination file name will contain the new-line character, which is illegal. Remove it before attempting the rename():
char* nl_ptr = strrchr(destination, '\n');
if (nl_ptr) *nl_ptr = 0;
The last line works because there is no new-line character.
Related
#EDIT: I think the problem is that I put my 2 text files on desktop. Then, I move them to the same place as the source file and it works. But the program cannot run this time, the line:
cok = 0;
shows "exception thrown".
// end EDIT
I have the assignment at school to write a C program to create 2 text files. 1 file stores 25 keywords, and 1 file stores the fake resume. The problem is, my program cannot read my keywords.txt file. Anyone can help me? Thank you so much.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//*****************************************************
// MAIN FUNCTION
int main()
{
//File pointer for resume.txt file declared
FILE *fpR;
//File pointer for keywords.txt file declared and open it in read mode
FILE* fpK = fopen("keywords.txt", "r");
//To store character extracted from keyword.txt file
char cK;
//To store character extracted from resume.txt file
char cR;
//To store word extracted from keyword.txt file
char wordK[50];
//To store word extracted from resume.txt file
char wordR[50];
//To store the keywords
char keywords[10][50];
//To store the keywords counter and initializes it to zero
int keywordsCount[10] = { 0, 0, 0, 0 };
int coK, coR, r, r1;
coK = coR = r = r1 = 0;
//Checks if file is unable to open then display error message
if (fpK == NULL)
{
printf("Could not open files");
exit(0);
}//End of if
//Extracts a character from keyword.txt file and stores it in cK variable and Loops till end of file
while ((cK = fgetc(fpK)) != EOF)
{
//Checks if the character is comma
if (cK != ',')
{
//Store the character in wordK coK index position
wordK[coK] = cK;
//Increase the counter coK by one
coK++;
}//End of if
//If it is comma
else
{
//Stores null character
wordK[coK] = '\0';
//Copies the wordK to the keywords r index position and increase the counter r by one
strcpy(keywords[r++], wordK);
//Re initializes the counter to zero for next word
coK = 0;
fpR = fopen("resume.txt", "r");
//Extracts a character from resume.txt file and stores it in cR variable and Loops till end of file
while ((cR = fgetc(fpR)) != EOF)
{
//Checks if the character is space
if (cR != ' ')
{
//Store the character in wordR coR index position
wordR[coR] = cR;
//Increase the counter coR by one
coR++;
}//End of if
else
{
//Stores null character
wordR[coR] = '\0';
//Re initializes the counter to zero for next word
coR = 0;
//Compares word generated from keyword.txt file and word generated from resume.txt file
if (strcmp(wordK, wordR) == 0)
{
//If both the words are same then increase the keywordCounter arrays r1 index position value by one
keywordsCount[r1] += 1;
}//End of if
}//End of else
}//End of inner while loop
//Increase the counter by one
r1++;
//Close the file for resume
fclose(fpR);
}//End of else
}//End of outer while loop
//Close the file for keyword
fclose(fpK);
//Display the result
printf("\n Result \n");
for (r = 0; r < r1; r++)
printf("\n Keyword: %s %d time available", keywords[r], keywordsCount[r]);
}//End of main
I think the problem is the text files, aren't they?
The name of my 1st test file is "keywords.txt", and its content is:
Java, CSS, HTML, XHTML, MySQL, College, University, Design, Development, Security, Skills, Tools, C, Programming, Linux, Scripting, Network, Windows, NT
The name of my 2nd test file is "resume.txt", and its content is:
Junior Web developer able to build a Web presence from the ground up -- from concept, navigation, layout, and programming to UX and SEO. Skilled at writing well-designed, testable, and efficient code using current best practices in Web development. Fast learner, hard worker, and team player who is proficient in an array of scripting languages and multimedia Web tools. (Something like this).
I don't see any problem with these 2 files. But my program still cannot open the file and the output keeps showing "Could not open files".
while ((cK = fgetc(fpK)) != EOF)
If you check the documentation, you can see that fgets returns an int. But since cK is a char, you force a conversion to char, which can change its value. You then compare the possibly changed value to EOF, which is not correct. You need to compare the value that fgets returns to EOF since fgetc returns an EOF on end of file.
When trying to open a file with fopen(path, "2"); i get NULL on an existing path
iv'e tried to enter only the file name and it works but i want the program to write the file in the path...
Yes, i write the path with double backslashes "\\" when it's necesary.
Yes the path without doubt exists.
FILE* log;
char directory_path[PATH_LEN] = { 0 };
char directory_file[PATH_LEN] = { 0 };
//directory_path is the directory, entered by the user
//LOG_NAME is the files name without the path - "log.txt"
//#define PATH_LEN 100
printf("Folder to scan: ");
fgets(directory_path, PATH_LEN, stdin);
directory_path[strlen(directory_path) - 1] = 0;
//this section connects the path with the file name.
strcpy(directory_file, directory_path);
strcat(directory_file, "\\");
strcat(directory_file, LOG_NAME);
if ((log = fopen(directory_file, "w")) == NULL)
{
printf("Error");
}
My program worked until i tried to write into a file in order to create a log file. This means that the path is correct without doubt.
Can anyone tell me the problem here?
You have several issues in your code:
For one, fopen(path, "2"); is not valid.
The mode argument needs to include one of a, r, and w and can optionally include b or +.
As another thing, directory_path[strlen(directory_path) - 1] = 0; may truncate the end of your path (if it's over PATH_LEN characters long).
There also may be a possible issue with buffer overflow due to the fact that you copy a string to a buffer of the same size and then concatenate two other strings to it. Therefore, you should change this line:
char directory_file[PATH_LEN] = { 0 };
to this:
char directory_file[PATH_LEN+sizeof(LOG_NAME)+1] = { 0 };
To debug this issue, you should print the string entered and ask for confirmation before using it (wrap this in #ifdef DEBUG).
I am trying to figure out why using C function strtok is not working properly for me. Here's the problem:
I have a file which contains two types of information: headers and text descriptions. Each line in the file is either a header or part of a text description. A header starts with '>'. The description text follows the header and can span multiple lines. At the end of the text there is an empty line which separates the description from the next header. My aim is to write two separate files: one contains the headers on each line and the other contains the corresponding description on a line by itself. To implement the codes in C, I used fgets to read the file one line at a time into dynamically allocated memory. In order to write the description text on one single line, I used `strtok to get rid of any new line characters exists in the text.
My code is working properly for the header files. However, for the descriptions file, I noticed that the last character of the text is not printed out to the file even though it is printed to the stdout.
FILE *headerFile = fopen("Headers", "w"); //to write headers
FILE *desFile = fopen("Descriptions", "w"); //to write descriptions
FILE *pfile = fopen("Data","r");
if ( pfile != NULL )
{
int numOfHeaders =0;
char **data1 = NULL; //an array to hold a header line
char **data2 = NULL; //an array to hold a description line
char line[700] ; //maximum size for the line
while (fgets(line, sizeof line, pfile ))
{
if(line[0] =='>') //It is a header
{
data1 = realloc(data1,(numOfHeaders +1)* sizeof(*data1));
data1[numOfHeaders]= malloc(strlen(line)+1);
strcpy(data1[numOfHeaders],line);
fprintf(headerFile, "%s",line);//writes the header
if(numOfHeaders >0)
fprintf(desFile, "\n");//writes a new line in the desc file
numOfHeaders++;
}
//it is not a header and not an empty line
if(line[0] != '>' && strlen(line)>2)
{
data2 = realloc(data2,(numOfHeaders +1)* sizeof(*data2));
data2[numOfHeaders]= malloc(strlen(line)+1);
char *s = strtok(line, "\n ");
strcpy(data2[numOfHeaders],s);
fprintf(desFile, "%s",data2[numOfHeaders]);
printf(desFile, "%s",data2[numOfHeaders]);
}
} //end-while
fclose(desFile);
fclose(headerFile);
fclose(pfile );
printf("There are %d headers in the file.\n",numOfHeaders);
}
As mentioned in the comments:
fprintf(desFile, "%s",data2[numOfHeaders]); //okay
printf(desFile, "%s",data2[numOfHeaders]); //wrong
Second line should be:
printf("%s",data2[numOfHeaders]); //okay
Or, you could do this:
sprintf(buffer, "%s",data2[numOfHeaders]);
fprintf(desFile, buffer);
printf(buffer);
Other possible issues:
Without an input file it is not possible to know for certain what strtok() is doing, but here is a guess based on what you have described:
In these two lines:
data2[numOfHeaders]= malloc(strlen(line)+1);
char *s = strtok(line, "\n ");
if the string contained in data2 has any embedded spaces, s will only contain the segment occurring before that space. And because you are only calling it once before line gets refreshed:
while (fgets(line, sizeof line, pfile ))
only one token (the very first segment) will be read.
Not always, but Normally, strtok() is called in a loop:
char *s = {0};
s= strtok(stringToParse, "\n ");//make initial call before entering loop
while(s)//ALWAYS test to see if s contains new content, else NULL
{
//do something with s
strcpy(data2[numOfHeaders],s);
//get next token from string
s = strtok(NULL, "\n ");//continue to tokenize string until s is null
}
But, as I said above, you are calling it only once on that string before the content of the string is changed. It is possible then, that the segment not printing has simply not yet been tokenized by strtok().
I have a code for reading the header of a csv file. First I check whether the extenson is .csv or not. Then I read the file. But the problem is, if I rename any other file, say a .xml file or a .docx file to .csv and then try to read it, then this file extension check doesn't work. It then crashes.
But I want to throw a proper error in such cases. Can anyone help? Here are the relevant code snippets:
// Extracting the extension of the file. Since only csv files are allowed,
// for rest of the extensions, appropriate error is being thrown
sExt = wcsrchr(sFile, L'.');
if(wcscmp(sExt, L".csv") != 0)
{
return -1;
}
_wfopen_s(&fpInpFile, sFile, L"rt");
if(fpInpFile == NULL)
{
return -1;
}
while(sChar[lCharIndx] = fgetwc(fpInpFile))
{
lVarLength ++;
lHeaderLength ++;
// If Variable name is too long, or if the length of the header is too long, throw an error
if(lVarLength >= 100 || lHeaderLength >= 100)
{
fclose(fpInpFile);
return -1;
}
// Resetting varibale length before reading length of next variable
if(sChar[lCharIndx] == ',')
lVarLength = 0;
// Header reading is done, so exiting the loop
if(sChar[lCharIndx] == '\n')
break;
lCharIndx ++;
}
fclose(fpInpFile);
while(sChar[lCharIndx] = fgetwc(fpInpFile))
You should't check for end-of-file this way. Instead:
wint_t wch;
while ((wch = fgetwc(fpInpFile)) != WEOF)
{
sChar[lCharIndx] = wch;
Also, you should check whether lCharIndx is within array size of sChar or not.
This question already has an answer here:
fgetc not starting at beginning of large txt file
(1 answer)
Closed 9 years ago.
Problem solved here:
fgetc not starting at beginning of large txt file
I am working in c and fgetc isn't getting chars from the beginning of the file. It seems to be starting somewhere randomly within the file after a \n. The goal of this function is to modify the array productsPrinted. If "More Data Needed" or "Hidden non listed" is encountered, the position in the array, productsPrinted[newLineCount], will be changed to 0. Any help is appreciated.
Update: It works on smaller files, but doesn't start at the beginning of the larger,617kb, file.
function calls up to category:
findNoPics(image, productsPrinted);
findVisible(visible, productsPrinted);
removeCategories(category, productsPrinted);
example input from fgetc():
Category\n
Diagnostic & Testing /Scan Tools\n
Diagnostic & Testing /Scan Tools\n
Hidden non listed\n
Diagnostic & Testing /Scan Tools\n
Diagnostic & Testing /Scan Tools\n
Hand Tools/Open Stock\n
Hand Tools/Sockets and Drive Sets\n
More Data Needed\n
Hand Tools/Open Stock\n
Hand Tools/Open Stock\n
Hand Tools/Open Stock\n
Shop Supplies & Equip/Tool Storage\n
Hidden non listed\n
Shop Supplies & Equip/Heaters\n
Code:
void removeCategories(FILE *category, int *prodPrinted){
char more[17] = { '\0' }, hidden[18] = { '\0' };
int newLineCount = 0, i, ch = 'a', fix = 0;
while ((ch = fgetc(category)) != EOF){ //if fgetc is outside while, it works//
more[15] = hidden[16] = ch;
printf("%c", ch);
/*shift char in each list <- one*/
for (i = 0; i < 17; i++){
if (i < 17){
hidden[i] = hidden[i + 1];
}
if (i < 16){
more[i] = more[i + 1];
}
}
if (strcmp(more, "More Data Needed") == 0 || strcmp(hidden, "Hidden non listed") == 0){
prodPrinted[newLineCount] = 0;
/*printf("%c", more[0]);*/
}
if (ch == '\n'){
newLineCount++;
}
}
}
Let computers do the counting. You have not null terminated your strings properly. The fixed strings (mdn and hdl are initialized but do not have null terminators, so string comparisons using them are undefined.
Given this sample data:
Example 1
More Data Needed
Hidden non listed
Example 2
Keeping lines short.
But as they get longer, the overwrite is worse...or is it?
Hidden More Data Needed in a longer line.
Lines containing "Hidden non listed" are zapped.
Example 3
This version of the program:
#include <stdio.h>
#include <string.h>
static
void removeCategories(FILE *category, int *prodPrinted)
{
char more[17] = { '0' };
char hidden[18] = { '0' };
char mdn[17] = { "More Data Needed" };
char hnl[18] = { "Hidden non listed" };
int newLineCount = 0, i, ch = '\0';
do
{
/*shift char in each list <- one*/
for (i = 0; i < 18; i++)
{
if (i < 17)
hidden[i] = hidden[i + 1];
if (i < 16)
more[i] = more[i + 1];
}
more[15] = hidden[16] = ch = fgetc(category);
if (ch == EOF)
break;
printf("%c", ch); /*testing here, starts rndmly in file*/
//printf("<<%c>> ", ch); /*testing here, starts rndmly in file*/
//printf("more <<%s>> hidden <<%s>>\n", more, hidden);
if (strcmp(more, mdn) == 0 || strcmp(hidden, hnl) == 0)
{
prodPrinted[newLineCount] = 0;
}
if (ch == '\n')
{
newLineCount++;
}
} while (ch != EOF);
}
int main(void)
{
int prod[10];
for (int i = 0; i < 10; i++)
prod[i] = 37;
removeCategories(stdin, prod);
for (int i = 0; i < 10; i++)
printf("%d: %d\n", i, prod[i]);
return 0;
}
produces this output:
Example 1
More Data Needed
Hidden non listed
Example 2
Keeping lines short.
But as they get longer, the overwrite is worse...or is it?
Hidden More Data Needed in a longer line.
Lines containing "Hidden non listed" are zapped.
Example 3
0: 37
1: 0
2: 0
3: 37
4: 37
5: 37
6: 0
7: 0
8: 37
9: 37
You may check which mode you opened the file, and you may have some error-check to make sure you have got the right return value.
Here you can refer to man fopen to get which mode to cause the stream position.
The fopen() function opens the file whose name is the string pointed to
by path and associates a stream with it.
The argument mode points to a string beginning with one of the follow‐
ing sequences (Additional characters may follow these sequences.):
r Open text file for reading. The stream is positioned at the
beginning of the file.
r+ Open for reading and writing. The stream is positioned at the
beginning of the file.
w Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
w+ Open for reading and writing. The file is created if it does
not exist, otherwise it is truncated. The stream is positioned
at the beginning of the file.
a Open for appending (writing at end of file). The file is cre‐
ated if it does not exist. The stream is positioned at the end
of the file.
a+ Open for reading and appending (writing at end of file). The
file is created if it does not exist. The initial file position
for reading is at the beginning of the file, but output is
always appended to the end of the file.
And there is another notice, that the file you operated should not more than 2G, or there maybe problem.
And you can use fseek to set the file position indicator.
And you can use debugger to watch these variables to see why there are random value. I think debug is efficient than trace output.
Maybe you can try rewinding the file pointer at the beginning of your function.
rewind(category);
Most likely another function is reading from the same file. If this solves your problem, it would be better to find which other function (or previous call to this function) is reading from the same file and make sure rewinding the pointer won't break something else.
EDIT:
And just to be sure, maybe you could change the double assignment to two different statements. Based on this post, your problem might as well be caused by a compiler optimization of that line. I haven't checked with the standard, but according to best answer the behavior in c and c++ might be undefined, therefore your strange results. Good luck