Re: file overwrite data manipulation

J

John Harrison

Comments below.

Mike Dundee said:
I have a file of the form:

header<newline>
data...delimiter...data...delimiter
purge_date_field...delimiter<newline>
end_of_file_marker<newline>

I want to open the file up and update the purge_date field with a
particular date. Here is most of my code.

int main(int argc, char* argv[])
{

//
// set up vars
//
static char filename[15];
char byte;
int TildeCount = 0;


strcpy(filename, argv[1]);
// open a file for read and write operations
ifstream in(filename, ios_base::in | ios_base::eek:ut
| ios_base::trunc);

Why filename, and why is is static? What if file name is longer than 15?

Better and simpler is

ifstream in(argv[1], ios_base::in | ios_base::eek:ut
| ios_base::trunc);

but you should add a check that argv[1] exists (if (argc < 2) etc.)
while (in.get(byte)) // read char by char until in correct
position in file
{
if(byte == '~'){ // tilde is my delimiter
TildeCount++ ;
}
if(TildeCount == 5){
cout << "reached purge date" << endl; // just my debug code
Sleep(2000);
// change purge date here to new date
in.close(); // debug code until I get this working

Unnecessary, C++ streams close themselves when the stream variable no longer
exists.
return 0;
}
}

in.close();
Ditto.


return 0;
}

How do I go about writing to the file at this position?

First thing to do is a seek, you cannot switch from reading to writing
without doing a seek in between. Since you are at the desired position, you
just have to seek to the current position

in.seekp(0, ios_base::cur);
Can I overwrite chars in the file or do I have to read to a buffer and
modify the buffer prior to writing back to a new file?

Either. If you need to read before you can tell what to write then read, if
not then start writing now.

If you need to do the former then forget the above code and do this

streampos pos = in.tellg(); // save current position
read the date somehow
in.seekp(pos, ios_base::beg); // go back to saved position
start writing
can I delete chars in a file.

Absolutely not. If the change you are making requires a change in the number
of characters in the file, then the only way to read the entire contents of
the file into memory, make the change in memory and them write the memory
back out to the file. Do this in three phases

1) open file for reading only, read file
2) make change in memory
3) open file for writing only, write file

The whole stream thing is confusing me!

C++ streams follow the same basic concepts (and them some) as any other file
I/O system. All the above would be true even if you were using C (but the
syntax would be different obviously).
Thanks in advance for any help.

I am using borland C++ pro ver. 5

Mike Dundee

john
 
M

Mike Dundee

John Harrison said:
Comments below.

Mike Dundee said:
I have a file of the form:

header<newline>
data...delimiter...data...delimiter
purge_date_field...delimiter<newline>
end_of_file_marker<newline>

I want to open the file up and update the purge_date field with a
particular date. Here is most of my code.

int main(int argc, char* argv[])
{

//
// set up vars
//
static char filename[15];
char byte;
int TildeCount = 0;


strcpy(filename, argv[1]);
// open a file for read and write operations
ifstream in(filename, ios_base::in | ios_base::eek:ut
| ios_base::trunc);

Why filename, and why is is static? What if file name is longer than 15?

Better and simpler is

ifstream in(argv[1], ios_base::in | ios_base::eek:ut
| ios_base::trunc);

but you should add a check that argv[1] exists (if (argc < 2) etc.)
while (in.get(byte)) // read char by char until in correct
position in file
{
if(byte == '~'){ // tilde is my delimiter
TildeCount++ ;
}
if(TildeCount == 5){
cout << "reached purge date" << endl; // just my debug code
Sleep(2000);
// change purge date here to new date
in.close(); // debug code until I get this working

Unnecessary, C++ streams close themselves when the stream variable no longer
exists.
return 0;
}
}

in.close();
Ditto.


return 0;
}

How do I go about writing to the file at this position?

First thing to do is a seek, you cannot switch from reading to writing
without doing a seek in between. Since you are at the desired position, you
just have to seek to the current position

in.seekp(0, ios_base::cur);
Can I overwrite chars in the file or do I have to read to a buffer and
modify the buffer prior to writing back to a new file?

Either. If you need to read before you can tell what to write then read, if
not then start writing now.

If you need to do the former then forget the above code and do this

streampos pos = in.tellg(); // save current position
read the date somehow
in.seekp(pos, ios_base::beg); // go back to saved position
start writing
can I delete chars in a file.

Absolutely not. If the change you are making requires a change in the number
of characters in the file, then the only way to read the entire contents of
the file into memory, make the change in memory and them write the memory
back out to the file. Do this in three phases

1) open file for reading only, read file
2) make change in memory
3) open file for writing only, write file

The whole stream thing is confusing me!

C++ streams follow the same basic concepts (and them some) as any other file
I/O system. All the above would be true even if you were using C (but the
syntax would be different obviously).
Thanks in advance for any help.

I am using borland C++ pro ver. 5

Mike Dundee

john

My entire code deals with the arg testing and returns various vals
depending on error condition. The above code that I posted is a
snippet of the main function. Reason for static char filename: I
don't know! (inexperience). Filename is always 10 chars long, I made
it 15 to be inefficient I guess :)

Here is the deal:

I am not sure how to read the entire contents into memory. I was
thinking of opening up two streams, one for the input file and one for
the output file. I will read (from infile) and output (to outfile)
char by char up to point where correct delimiter is encountered. I
will then output "newdate" ignoring input from infile at this point up
to next delimiter. I will continue reading from infile and outputting
to new file char by char until I reach EOF. This seems a bit "clunky"
but my C++ is not so good. I will delete the infile when
"translation" is complete. The filename is not an issue, as I am
outputting to a directory that is being monitored for all files and is
only interested in the file contents and not the filename.

I am sure there is a much more efficient way of doing things, and I
would mind any suggestions, please be aware that I am somewhat of a
rookie.

Thanks again for the suggestions
 
J

John Harrison

My entire code deals with the arg testing and returns various vals
depending on error condition. The above code that I posted is a
snippet of the main function. Reason for static char filename: I
don't know! (inexperience). Filename is always 10 chars long, I made
it 15 to be inefficient I guess :)

Here is the deal:

I am not sure how to read the entire contents into memory. I was
thinking of opening up two streams, one for the input file and one for
the output file. I will read (from infile) and output (to outfile)
char by char up to point where correct delimiter is encountered. I
will then output "newdate" ignoring input from infile at this point up
to next delimiter. I will continue reading from infile and outputting
to new file char by char until I reach EOF. This seems a bit "clunky"
but my C++ is not so good.

It is clunky, but it is a limitation of the underlying file system. You
can't do anything about it.
I will delete the infile when
"translation" is complete. The filename is not an issue, as I am
outputting to a directory that is being monitored for all files and is
only interested in the file contents and not the filename.

I am sure there is a much more efficient way of doing things, and I
would mind any suggestions, please be aware that I am somewhat of a
rookie.

No, sounds like you know what to do.
Thanks again for the suggestions

john
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top