Related
I'm trying to use a sparse file to store sparse array of data, logically I thought the code had no bugs but the unit tests keep failing, after many inspections of code I decided to check the file content after every step and found out the holes were not created, aka: write first element, seek x amount of elements, write 2nd element ends up writing first element then second element in file without any space at all between them.
My simplified code:
FILE* file = fopen64(fn.c_str(), "ar+b");
auto const entryPoint = 220; //calculated at runtime, the size of each element is 220 bytes
auto r = fseeko64(file, entryPoint, SEEK_SET);
if(r!=0){
std::cerr << "Error seeking file" << std::endl;
}
size_t written = fwrite(&page->entries[0], sizeof(page->entries), 1, file);
if(written != 1) {
perror("error writing file");
}
fclose(file);
The offset is being calculated correctly, current behavior is writing first element, leaving 20 elements empty then writing 22nd element. When inspecting file using hex dumps it shows 2 elements at offset 0 and 220 (directly after first element). unit tests also fail because reading 2nd element actually returns element number 22.
Anyone could explain what is wrong with my code? maybe I misunderstood the concept of holes???
------Edit1------
Here's my full code
Read function:
FILE* file = fopen64(fn.c_str(), "r+b");
if(file == nullptr){
memset(page->entries, 0, sizeof(page->entries));
return ;
}
MoveCursor(file, id, sizeof(page->entries));
size_t read = fread(&page->entries[0], sizeof(page->entries), 1, file);
fclose(file);
if(read != 1){ //didn't read a full page.
memset(page->entries, 0, sizeof(page->entries));
}
Write function:
auto fn = dir.path().string() + std::filesystem::path::preferred_separator + GetFileId(page->pageId);
FILE* file = fopen64(fn.c_str(), "ar+b");
MoveCursor(file, page->pageId, sizeof(page->entries));
size_t written = fwrite(&page->entries[0], sizeof(page->entries), 1, file);
if(written != 1) {
perror("error writing file");
}
fclose(file);
void MoveCursor(FILE* file, TPageId pid, size_t pageMultiplier){
auto const entryPoint = pid * pageMultiplier;
auto r = fseeko64(file, entryPoint, SEEK_SET);
if(r!=0){
std::cerr << "Error seeking file" << std::endl;
}
}
And here's a simplified page class:
template<typename TPageId uint32_t EntriesCount>
struct PODPage {
bool dirtyBit = false;
TPageId pageId;
uint32_t entries[EntriesCount];
};
The reason I'm saying it is fseeko problem when writing is because when inspecting file content with xdd it shows data is out of order. Break points in MoveCursor function shows the offset is calculated correctly and manual inspection of file fields shows the offset is set correctly however when writing it doesn't leave a hole.
=============Edit2============
Minimal reproducer, logic goes as: write first chunk of data, seek to position 900, write second chunk of data, then try to read from position 900 and compare to data that was supposed to be there. Each operation opens and closes file which is what happens in my original code, keeping a file open is not allowed.
Expected behavior is to create a hole in file, actual behavior is the file is written sequentially without holes.
#include <iostream>
#define _FILE_OFFSET_BITS 64
#define __USE_FILE_OFFSET64 1
#include <stdio.h>
#include <cstring>
int main() {
uint32_t data[10] = {1,2,3,4,5,6,7,8,9};
uint32_t data2[10] = {9,8,7,6,5,4,3,2,1};
{
FILE* file = fopen64("data", "ar+b");
if(fwrite(&data[0], sizeof(data), 1, file) !=1) {
perror("err1");
return 0;
}
fclose(file);
}
{
FILE* file = fopen64("data", "ar+b");
if (fseeko64(file, 900, SEEK_SET) != 0) {
perror("err2");
return 0;
}
if(fwrite(&data2[0], sizeof(data2), 1, file) !=1) {
perror("err3");
return 0;
}
fclose(file);
}
{
FILE* file = fopen64("data", "r+b");
if (fseeko64(file, 900, SEEK_SET) != 0) {
perror("err4");
return 0;
}
uint32_t data3[10] = {0};
if(fread(&data3[0], sizeof(data3), 1, file)!=1) {
perror("err5");
return 0;
}
fclose(file);
if (memcmp(&data2[0],&data3[0],sizeof(data))!=0) {
std::cerr << "err6";
return 0;
}
}
return 0;
}
I think your problem is the same as discussed here:
fseek does not work when file is opened in "a" (append) mode
Does fseek() move the file pointer to the beginning of the file if it was opened in "a+b" mode?
Summary of the two above: If a file is opened for appending (using "a") then fseek only applies to the read position, not to the write position. The write position will always be at the end of the file.
You can fix this by opening the file with "w" or "w+" instead. Both worked for me with your minimal code example.
The short version: I have a C++ code that uses a C call to fprintf(stdout, some_cpp_str.c_str()) and crashes during it. The first 4 calls are fine, only the 5th crashes, and I have no idea why (suspecting unreadable char inside the string). The 1st code I posted was mostly C, so I posted another one, with only C++ except for the fprintf (code added at the bottom of the question). The crashes occur (consistently) on an embedded device. On my own PC the code runs fine
The long version:
I have a code that reads lines from text, and pushes them into a string vector. TO check my progress, I also fprintf them to the screen after the vector is populated:
int main(){
char err_msg[256], * line = NULL, *in_file = "...", *keyword = "blah";
size_t len = 0;
ssize_t num_bytes_read;
int i = 1;
std::vector<std::string> lines_vector;
FILE * fp = fopen(in_file, "r");
if (!fp) {
fprintf(stdout,"can't open file %s for reading\n", in_file);
goto EXIT;
}
while ((num_bytes_read = getline(&line, &len, fp)) != -1) {
/* if found keyword inside line */
if (strstr(line, keyword)) {
/* add 3 lines (entry heading, entry body, newline)*/
lines_vector.push_back(std::string(line));
for(int lines_to_copy = 2; lines_to_copy > 0; lines_to_copy--) {
if((num_bytes_read = getline(&line, &len, fp)) == -1) {
fprintf(stdout,"can't read line from %s\n", in_file);
goto EXIT;
}
lines_vector.push_back(std::string(line));
}
}
}
fprintf(stdout,"finished reading from file\n");
EXIT:
fclose(fp);
free(line);
for (std::vector<std::string>::iterator it = lines_vector.begin() ; it != lines_vector.end(); ++it, ++i) {
fprintf(stdout, "%d)", i);
fprintf(stdout, "%s", (*it).c_str());
}
return 0;
}
This works fine on my VM, but I also run it on an embedded device, where it always crashes on a specific line. The line is:
certificates local generate name localcert common-name sf country(region) AB auto-regenerate-days 12 auto-regenerate-days-warning 11 e-mail X#Y.com locality(city) Z organization Q organization-unit T scep-password-string 57E6CA35452E72E4D1BC4518260ABFC7 scep-url http://0.0.0.0/X/Y/ state(province) s
I don't think there is a problem in the line itself (as it doesn't crash on my VM). When trying to print it to a file instead of to the screen, it doesn't crash:
for (std::vector<std::string>::iterator it = lines_vector.begin(); it != lines_vector.end(); ++it){
sprintf(tmp, "echo \"%s\" >> /X/Y/Z.txt", (*it).c_str());
OS_run(tmp); // run this command on sh shell
}
Since it crashes only on my embedded and not my VM, I thought the file is somehow corrupted. Could it be that the string has an invalid char inside that crashes fprintf, but not echo?
I tried translating this code into proper C++, but I still get a crash in the middle of the last string. I know mixing C/C++ is not good, but shouldn't c_str() be a proper interface between std::string and char * (which fprintf expects)?
If not this, then what could possibly crash during the fprintf?
int main()
{
std::vector<std::string> lines_vector;
std::ifstream infile(in_file);
std::string line;
int counter = 1;
while (std::getline(infile, line)) {
if (line.find(keyword, 0) != std::string::npos) {
lines_vector.push_back(line);
for(int lines_to_copy = 2; lines_to_copy > 0; lines_to_copy--) {
std::getline(infile, line);
lines_vector.push_back(line);
}
}
}
for (std::vector<std::string>::iterator it = lines_vector.begin(); it != lines_vector.end(); ++it){
fprintf(stdout, "%d)%s", counter++, (*it).c_str());
}
}
On an embedded device, you can expect that dynamic memory allocation fail. That means that you absolutely must control all possible allocations (you should anyway even on non embedded device, but the crash risk is much lower...). You really should have:
while ((num_bytes_read = getline(&line, &len, fp)) != -1) {
...
}
if (line == NULL) {
perror("getline could not allocate buffer");
}
This will not fix anything, but at least you will know what happens.
I have respected your coding style here, making heavy use of the C library and also using goto. But I must advise you not to do that in C++ programs.
C library used to be included in C++ standard library because early C++ implementations were lacking too many functionalities. In modern C++ goto is to be banned, as are all raw C strings and C io functions (except in very special use cases). And C++ come with a version of getline (in header <string>) that directly fills a std::string. You really should try to avoid C construct if learning C++.
Per Ben Voigt's comment, there are correct use case to use old style C library if you want to avoid dynamic allocation. But in that case, you should also avoid std::string and std::vector
I have to read a text file into a array of structures.I have already written a program but it is taking too much time as there are about 13 lac structures in the file.
Please suggest me the best possible and fastest way to do this in C++.
here is my code:
std::ifstream input_counter("D:\\cont.txt");
/**********************************************************/
int counter = 0;
while( getline(input_counter,line) )
{
ReadCont( line,&contract[counter]); // function to read data to structure
counter++;
line.clear();
}
input_counter.close();
keep your 'parsing' as simple as possible: where you know the field' format apply the knowledge, for instance
ReadCont("|PE|1|0|0|0|0|1|1||2|0||2|0||3|0|....", ...)
should apply fast char to integer conversion, something like
ReadCont(const char *line, Contract &c) {
if (line[1] == 'P' && line[2] == 'E' && line[3] == '|') {
line += 4;
for (int field = 0; field < K_FIELDS_PE; ++field) {
c.int_field[field] = *line++ - '0';
assert(*line == '|');
++line;
}
}
well, beware to details, but you got the idea...
I would use Qt entirely in this case.
struct MyStruct {
int Col1;
int Col2;
int Col3;
int Col4;
// blabla ...
};
QByteArray Data;
QFile f("D:\\cont.txt");
if (f.open(QIODevice::ReadOnly)) {
Data = f.readAll();
f.close();
}
MyStruct* DataPointer = reinterpret_cast<MyStruct*>(Data.data());
// Accessing data
DataPointer[0] = ...
DataPointer[1] = ...
Now you have your data and you can access it as array.
In case your data is not binary and you have to parse it first you will need a conversion routine. For example if you read csv file with 4 columns:
QVector<MyStruct> MyArray;
QString StringData(Data);
QStringList Lines = StringData.split("\n"); // or whatever new line character is
for (int i = 0; i < Lines.count(); i++) {
String Line = Lines.at(i);
QStringList Parts = Line.split("\t"); // or whatever separator character is
if (Parts.count() >= 4) {
MyStruct t;
t.Col1 = Parts.at(0).toInt();
t.Col2 = Parts.at(1).toInt();
t.Col3 = Parts.at(2).toInt();
t.Col4 = Parts.at(3).toInt();
MyArray.append(t);
} else {
// Malformed input, do something
}
}
Now your data is parsed and in MyArray vector.
As user2617519 says, this can be made faster by multithreading. I see that you are reading each line and parsing it. Put these lines in a queue. Then let different threads pop them off the queue and parse the data into structures.
An easier way to do this (without the complication of multithreading) is to split the input data file into multiple files and run an equal number of processes to parse them. The data can then be merged later.
QFile::readAll() may cause a memory problem and std::getline() is slow (as is ::fgets()).
I faced a similar problem where I needed to parse very large delimited text files in a QTableView. Using a custom model, I parsed the file to find the offsets to the start of a each line. Then when data is needed to display in the table I read the line and parse it on demand. This results in a lot of parsing, but that is actually fast enough to not notice any lag in scrolling or update speed.
It also has the added benefit of low memory usage as I do not read the file contents into memory. With this strategy nearly any size file is possible.
Parsing code:
m_fp = ::fopen(path.c_str(), "rb"); // open in binary mode for faster parsing
if (m_fp != NULL)
{
// read the file to get the row pointers
char buf[BUF_SIZE+1];
long pos = 0;
m_data.push_back(RowData(pos));
int nr = 0;
while ((nr = ::fread(buf, 1, BUF_SIZE, m_fp)))
{
buf[nr] = 0; // null-terminate the last line of data
// find new lines in the buffer
char *c = buf;
while ((c = ::strchr(c, '\n')) != NULL)
{
m_data.push_back(RowData(pos + c-buf+1));
c++;
}
pos += nr;
}
// squeeze any extra memory not needed in the collection
m_data.squeeze();
}
RowData and m_data are specific to my implementation, but they are simply used to cache information about a row in the file (such as the file position and number of columns).
The other performance strategy I employed was to use QByteArray to parse each line, instead of QString. Unless you need unicode data, this will save time and memory:
// optimized line reading procedure
QByteArray str;
char buf[BUF_SIZE+1];
::fseek(m_fp, rd.offset, SEEK_SET);
int nr = 0;
while ((nr = ::fread(buf, 1, BUF_SIZE, m_fp)))
{
buf[nr] = 0; // null-terminate the string
// find new lines in the buffer
char *c = ::strchr(buf, '\n');
if (c != NULL)
{
*c = 0;
str += buf;
break;
}
str += buf;
}
return str.split(',');
If you need to split each line with a string, rather than a single character, use ::strtok().
Say I have a text file like this:
User: John
Device: 12345
Date: 12/12/12
EDIT:
I have my code to successfully search for a word, and display the info after that word. However when I try to edit the code to search for 2 or 3 words and display the info after them instead of just 1 word, I cannot get it to work. I have tried adding codes into the same while loop, and creating a new while loop for the other word, but both doesn't work. There must be something I am doing wrong/not doing.
Please advice, thanks!
Here is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char file[100];
char c[100];
printf ("Enter file name and directory:");
scanf ("%s",file);
FILE * fs = fopen (file, "r") ;
if ( fs == NULL )
{
puts ( "Cannot open source file" ) ;
exit( 1 ) ;
}
FILE * ft = fopen ( "book5.txt", "w" ) ;
if ( ft == NULL )
{
puts ( "Cannot open target file" ) ;
exit( 1 ) ;
}
while(!feof(fs)) {
char *Data;
char *Device;
char const * rc = fgets(c, 99, fs);
if(rc==NULL) { break; }
if((Data = strstr(rc, "Date:"))!= NULL)
printf(Data+5);
if((Data = strstr(rc, "Device:"))!=NULL)
printf(Device+6);
}
fclose ( fs ) ;
fclose ( ft ) ;
return 0;
}
Ok, hope I can clear it this time. Sorry if I get confusing sometimes but my english is not the best.
I'll explain the implementation inside comments:
#define BUFFSIZE 1024
int main()....
char buff[BUFFSIZE];
char delims[] = " "; /*Where your strtok will split the string*/
char *result = NULL;
char *device; /*To save your device - in your example: 12345*/
char *date; /*To save the date*/
int stop = 0;
fp = fopen("yourFile", "r");
while( fgets(buff, BUFFSIZE,fp) != NULL ) /*This returns null when the file is over*/
{
result = strtok( buff, delims ); /*You just need to do reference to buff here, after this, strtok uses delims to know where to do the next token*/
while(result != NULL){ /*Strtok returns null when finishes reading the given string*/
if(strcmp(result,"Device")==0){ /*strcmp returns 0 if the strings are equal*/
result = strtok(NULL, delims); /*this one gets the 12345*/
device = (char*)malloc((strlen(result)+1)*sizeof(char)); /*Alocate the right amount of memory for the variable device*/
strcpy(device, result); /*Now, device is "12345"*/
}
/*Here you do the same but for the string 'Date'*/
if(strcmp(result,"Date")==0){ /*strcmp returns 0 if the strings are equal*/
result = strtok(NULL, delims); /*this one gets the 12345*/
date = (char*)malloc((strlen(result)+1)*sizeof(char)); /*Alocate the right amount of memory for the variable device*/
strcpy(date, result); /*Now, device is "12/12/12"*/
}
/*And you can repeat the if statement for every string you're looking for*/
result = strtok(NULL,delims); /*Get the next token*/
}
}
/*No strtok necessary here */
...
Hope this helps.
fgetc returns an integer value, which is character, promoted to int.
I suppose you meant fgets which reads a whole line, but you need to reserve memory for it, for example:
#define BUF 100
...
char c[BUF];
fgets(c, BUF, fs);
Some helpful links.
There are a couple of problems in your code: basically it never compiled.
Here is a version with small cleanups - which at least compiles:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char file[100];
char c[100];
printf ("Enter file name and directory:");
scanf ("%s",file);
FILE * fs = fopen (file, "r") ;
if ( fs == NULL ) {
puts( "Cannot open source file" ) ;
exit(1 ) ;
}
while(!feof(fs)) {
char *Data;
char const * rc = fgets(c, 99, fs);
if(rc==NULL) { break; }
if((Data = strstr(rc, "Device"))!= NULL)
printf("%s", Data);
}
fclose ( fs ) ;
return 0;
}
Problems I found:
Missing include for exit()
Missing parameter for exit()
Missing while loop to run through the whole input file.
The output file was never used.
Missing return value of 'main'
Fancy Data[5]
Changed fgetc() to fgets()
I only did minimal edits - it's not perfect at all....
IMHO I would go for C++: many things are much simpler there.
If printf() isn't a hard/fast rule, and the input requirements are really this simple, I'd prefer a state-machine and a constant-memory input:
int c, x = 0; // c is character, x is state
while(EOF!=(c=getchar())){ // scanner entry point
if(c == '\n') x=0; // newline resets scanner
else if(x == -1) continue; // -1 is invalid state
else if (x < 7 && c=="Device:"[x])x++; // advance state
else if (x == 7 && isspace(c)) continue; // skip leading/trailing whitespace
else if (x == 7) putchar(c); // successful terminator (exits at \n)
else x = -1; // otherwise move to invalid state
}
I would do that with two loops: one to get a line from the file and other to make tokens from the line read.
something like:
#define BUFFSIZE 1024
int main()....
char buff[BUFFSIZE];
char delims[] = " ";
char *result = NULL;
int stop = 0;
fp = fopen("yourFile", "r");
while( fgets(buff, BUFFSIZE,fp) != NULL ) /*This returns null when the file is over*/
{
result = strtok( buff, delims ); /*You just need to do reference to buff here, after this, strtok uses delims to know where to do the next token*/
while(result != NULL){ /*Strtok returns null when finishes reading the given string*/
if(strcmp(result,"Device")==0){ /*strcmp returns 0 if the strings are equal*/
stop = 1; /*Update the flag*/
break; /*Is now possible to break the loop*/
}
result = strtok(NULL,delims); /*Get the next token*/
}
if(stop == 1) break; /*This uses the inside flag to stop the outer loop*/
}
result = strtok(NULL, delims); /*Result, now, has the string you want: 12345 */
...
this code is not very accurate and I didn't tested it, but thats how I would try to do it.
Hope this helps.
My suggestion is to use fread to read all the file.You could read it character by character, but IMHO (a personal taste here) it's simpler to get a string containing all the characters and then manipulating it.
This is the function prototype:
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
It returns the number of elements read.
For example:
char buffer[100];
size_t n= fread(buffer, 1,100, fs);
Then you can manipulate the string and divide it in tokens.
EDIT
There is a nice reference with also an example of how dividing a string into tokens here:
http://www.cplusplus.com/reference/cstring/strtok/
c and Data are char-pointers, pointers to (the start of a list of) character value(s).
fgetc's prototype is int fgetc ( FILE * stream ); meaning that it returns (one) integer value (an integer is convertible to a single char value).
If fgetc's prototype would've been int * fgetc ( FILE * stream ); the warning wouldn't have appeared.
#Dave Wang
My answer was too big to be a comment. So here it goes:
You're welcome. Glad to help.
If you make a new loop, the fgets won't work because you are already 'down' in the text file. Imagine something like a pointer to the file, every time you 'fget it' from a file pointer, you advance that pointer. You have functions to reload the file or push that pointer up, but it is not efficient, you've already passed by the information you want, there must be a way to know when.
If you're using my implementation, that is done by using another string compare inside the loop:
if(strcmp(result,"date") == 0)
If you enter this if, you know that the next value in result token with strtok is the actual date.
Since you have now two conditions to be tested, you can't break the outer loop before having both of them. This can be accomplished by two ways:
1-Instead of a flag, use a counter that is incremented everytime you want an information. If that counter has the same number of information you want, you can break the outer loop.
2-Don't break the outer loop at all! :)
But in both, since there are 2 conditions, make sure you treat them inside the ifs so you know that you dealing with the right information.
Hope this helps. Anything, just ask.
I'm writing networking programming using socket.h to my studies. I have written server and client simple programs that can transfer files between them using buffer size given by user.
Server
void transfer(string name)
{
char *data_to_send;
ifstream myFile;
myFile.open(name.c_str(),ios::binary);
if(myFile.is_open))
{
while(myFile.eof))
{
data_to_send = new char [buffer_size];
myFile.read(data_to_send, buffer_size);
send(data_to_send,buffer_size);
delete [] data_to_send;
}
myFile.close();
send("03endtransmission",buffer_size);
}
else
{
send("03error",buffer_size);
}
}
Client
void download(string name)
{
char *received_data;
fstream myFile;
myFile.open(name.c_str(),ios::out|ios::binary);
if(myFile.is_open())
{
while(1)
{
received_data = new char[rozmiar_bufora];
if((receivedB = recv(sockfd, received_data, buffer_size,0)) == -1) {
perror("recv");
close(sockfd);
exit(1);
}
if(strcmp(received_data,"03endoftransmission") == 0)
{
cout<<"End of transmission"<<endl;
break;
}
else if (strcmp(received_data,"03error") == 0)
{
cout<<"Error"<<endl;
break;
}
myFile.write(received_data,buffer_size);
}
myFile.close();
}
The problem occurs, when I want to implement my own protocol- two chars (control), 32 chars hash, and the rest of package is data. I tried few times to split it and I end up with this code:
Server
#define PAYLOAD 34
void transfer(string name)
{
char hash[] = "12345678901234567890123456789012"; //32 chars
char *data_to_send;
ifstream myFile;
myFile.open(name.c_str(),ios::binary);
if(myFile.is_open))
{
while(myFile.eof))
{
data_to_send = new char [buffer_size-PAYLOAD];
myFile.read(data_to_send, buffer_size-PAYLOAD);
concatenation = new char[buffer_size];
strcpy(concatenation,"02");
strcat(concatenation,hash);
strcat(concatenation,data_to_send);
send(concatenation,buffer_size);
delete [] data_to_send;
delete [] concatenation;
}
myFile.close();
send("03endtransmission",buffer_size);
}
else
{
send("03error",buffer_size);
}
}
Client
void download(string name)
{
char *received_data;
fstream myFile;
myFile.open(name.c_str(),ios::out|ios::binary);
if(myFile.is_open())
{
while(1)
{
received_data = new char[buffer_size];
if((receivedB = recv(sockfd, received_data, buffer_size,0)) == -1) {
perror("recv");
close(sockfd);
exit(1);
}
if(strcmp(received_data,"03endoftransmission") == 0)
{
cout<<"End of transmission"<<endl;
break;
}
else if (strcmp(received_data,"03error") == 0)
{
cout<<"Error"<<endl;
break;
}
control = new char[3];
strcpy(control,"");
strncpy(control, received_data,2);
control[2]='\0';
hash = new char[33];
strcpy(hash,"");
strncpy(hash,received_data+2,32);
hash[32]='\0';
data = new char[buffer_size-PAYLOAD+1];
strcpy(data,"");
strncpy(data,received_data+34,buffer_size-PAYLOAD);
myFile.write(data,buffer_size-PAYLOAD);
}
myFile.close();
}
But this one inputs to file some ^# instead of real data. Displaying "data" to console looks the same on server and client. If you know how I can split it up, I would be very grateful.
You have some issues which may or may not be your problem.
(1) send/recv can return less than you requested. You may ask to receive 30 bytes but only get 10 on the recv call so all of these have to be coded in loops and buffered somewhere until you actually get the number you wanted. Your first set of programs was lucky to work in this regard and probably only because you tested on a limited amount of data. Once you start to push through more data your assumptions on what you are reading (and comparing) will fail.
(2) There is no need to keep allocating char buffers in the loops; allocate them before the loop or just use a local buffer rather than the heap. What you are doing is inefficient and in the second program you have memory leaks because you don't delete them.
(3) You can get rid of the strcpy/strncpy statements and just use memmove()
Your specific problem is not jumping out at me but maybe this will push in the right direction. More information what is being transmitted properly and exactly where in the data you are seeing problems would be helpful.
But this one inputs to file some ^# instead of real data. Displaying
"data" to console looks the same on server and client. If you know how
I can split it up, I would be very grateful.
You say that the data (I presume the complete file rather than the '^#') is the same on both client and server? If this is the case, then your issue is likely writing the data to file, rather than the actual transmission of the data itself.
If this is the case, you'll probably want to check assumptions about how the program writes to file - for example, are you passing in text data to be written to file, or binary data? If you're writing binary data, but it uses the NULL-terminated string, chances are it will quit early treating valid binary information as a NULL.
If it's text mode, you might want to consider initialising all strings with memset to a default character (other than NULL) to see if it's garbage data being out put.
If both server and client display the '^#' (or whatever data), binary based char data would be incompatible with the strcpy/strcat functions as this rely on NULL termination (where-as binary uses size termination instead).
I can't track down the specific problem, but maybe this might offer an insight or two that helps.