i have this function to get the content of file ,
#define BUFSIZE 512
vector<int> getContFile(char* pFile) {
ifstream vCin(pFile, ios::binary);
ifstream::pos_type size;
// get vLength of file:
vCin.seekg(0, ios::end);
size = vCin.tellg();
vCin.seekg(0, ios::beg);
vector<int> vTmp;
for (int i = 0; i < size; i++)
vTmp.push_back(vCin.get());
vCin.close();
return vTmp;
}
and this to send to the server
void SendFile() {
SendS("upFileUser");
int i;
vector<int> vTmp = getContFile("/usr/home/alex/Desktop/eval.tar");
for (i = 0; i < vTmp.size(); i += BUFSIZE) {
char *vBuff = new char[BUFSIZE];
for (int j = i; j < BUFSIZE; j++)
vBuff[j] = (char(vTmp[i]));
SendS(vBuff);
}
if (i < (vTmp.size() - 1)) {
char *vBuff = new char[vTmp.size() - i];
for (int j = 0; j < vTmp.size() - i; j++)
vBuff[j + i] = (char(vTmp[j + i]));
SendS(vBuff);
}
sendS("endOfFileTransmision");
}
void SendS(char* pSir) {
int vLen = strlen(pSir);
write(pSocket, &vLen, sizeof (int));
write(pSocket, pSir, vLen);
}
this is the receve function
char* reciveS() {
char* vTmp;
int vCt = 0;
read(pSocket, &vCt, sizeof (vCt));
if (vCt != 0) {
vTmp = new char[vCt];
read(vSocket, vTmp, vCt);
} else {
vTmp = NULL;
}
return vTmp;
}
bool receveFile(void) {
char* vReceve = reciveS();
if (strcmp(vReceve, "upFileUser") == 0)
{
ofstream vCoutFile;
vCoutFile.open("data2.tar", ios::out | ios::binary);
while (true) {
char *vTmp = new char[BUFSIZ];
vTmp = reciveS();
cout<<vTmp;
if (strcmp(vTmp, "endOfFileTransmision") == 0) break;
else {
cout << vTmp;
vCoutFile << vTmp;
}
}
vCoutFile.close();
}
}
and the result are a broke pipe(i run this to freebsd 6.4 amd with g++ compiler) , so what i miss , the connection are good i can transfer text from client to server and reverse the problem are with binary file
I see two problems with your code:
You are making a lot of allocations (new) but you never free the memory.
In the SendS function you are taking the string length, but the data in that "string" is from a vector of integers and is binary. This means that the data can contain the string-terminating '\0' character (the integer 0).
Besides that, I really don't follow what you are doing. Instead of reading into a vector, create a char-buffer and allocate enough memory to put the whole file into that buffer (char *buffer = new char[length_of_file]) and send it, with the length of the buffer first.
Something like this:
std::pair<size_t, char *> getContFile(const char *pFile)
{
ifstream vCin(pFile, ios::binary);
ifstream::pos_type size;
vCin.seekg(0, ios::end);
size = vCin.tellg();
vCin.seekg(0, ios::beg);
char *buffer = new char[size];
vCin.read(buffer, size);
return std::make_pair(static_cast<size_t>(size), buffer);
}
void SendFile()
{
SendS("upFileUser", strlen("upFileUser"));
std::pair<size_t, char *> vTmp = getContFile("/usr/home/alex/Desktop/eval.tar");
SendS(vTmp.second, vTmp.first);
delete [] vTmp.second;
}
void SendS(char *buffer, size_t length)
{
// Send the length
size_t tmp = htonl(length);
write(pSocket, &tmp, sizeof(tmp));
// Send the buffer
while (length > 0)
{
ssize_t sent = write(pSocket, buffer, length);
if (sent <= 0)
{
// Some kind of error
break;
}
buffer += sent;
length -= sent;
}
}
Do something similar on the receiving side.
Related
I'm reading a .txt file. I need to read at most 254 characters into my char* buffer, so I did this:
char *buffer = new char[255];
***Some Code***
if (!feof(fichero))
{
if (fgets(buffer, 254, fichero) != NULL)
{
How do get the size of the buffer read? Right now I'm using a manual method to find '\n' and use its position as the size. But is there a better way?
My code for now:
char *buffer = new char[255];
int tamanio;
***more code***
if (!feof(fichero))
{
if (fgets(buffer, 254, fichero) != NULL)
{
//printarCadena(buffer);
tamanio = limpiarBuffer(buffer);
printf("Tamanio buffer: %i \n", tamanio);
int Gestor::limpiarBuffer(char* buffer)
{
int i;
for(i = 0; i < int(strlen(buffer));i++)
{
if(buffer[i] == '\n')
return i;
}
return int(strlen(buffer) - 1);
}
Edit: I`ve to use Char*, University vibes
Edit2: I've to read line by line, if line ve more than 255 characteres, i read as 2 or more lines
int getSize(char* buffer)
{
int i;
for(i = 0; i < int(strlen(buffer));i++)
{
if(buffer[i] == '\n')
return i;
}
return strlen(buffer);
}
By now no other way to do with char*
i want to call MD5 function more than one time and return the result with blow code.
char *finalenc= (char*)malloc(32);
finalenc = "";
for (int i = 0; i < md5repeatTime; ++i) {
if (i == 0)
finalenc = md5(env, chtime, 0);
else {
finalenc = md5(env, finalenc, 0);
}
}
__android_log_write(ANDROID_LOG_ERROR, "releasetimefortest", finalenc);
i have two problem:
when i Log the result the "finalenc" value is lost and change to unknow value.
when i call this part of code more than one time, i got this error:
libc: Fatal signal 6 (SIGABRT) at 0x000006df
Modified:
char *md5(JNIEnv *env, char *cstr, int mode) {
MD5_CTX context = {0};
MD5Init(&context);
MD5Update(&context, (unsigned char *) cstr, strlen(cstr));
unsigned char dest[16] = {0};
MD5Final(dest, &context);
char mdString[33];
int i;
for (i = 0; i < 16; i++) {
sprintf(&mdString[i*2], "%02x", (unsigned int)dest[i]);
}
return mdString;
}
finally i find the solution:
md5 fuction:
char *md5(JNIEnv *env, char *cstr,char mdString[65]) {
MD5_CTX context = {0};
MD5Init(&context);
MD5Update(&context, (unsigned char *) cstr, strlen(cstr));
unsigned char dest[16] = {0};
MD5Final(dest, &context);
// (*env)->ReleaseStringUTFChars(env, data, cstr);
// char mdString[33];
int i;
for (i = 0; i < 16; i++) {
sprintf(&mdString[i*2], "%02x", (unsigned int)dest[i]);
}
return mdString;
}
and for call that function
char mdString[65]={0};
if (md5enable == 1) {
for (int i = 0; i < md5repeatTime; ++i) {
if (i == 0) {
md5(env, chtime, mdString);
}
else {
md5(env, mdString,mdString);
}
}
}
Example file:
[16bpp] Ponete el cinturon *-*
arfield
Nothing (cumpleanios):
Alkon^
~~|Tampon)
[16bpp] Chico Tonto.
Budin
16bpp] Leooooooooo!!!!!
Ev
16bpp] fedee
etamod
:) mAnKeAno
I want each name on a different array position...
I tried this code:
int c;
FILE *file;
file = fopen("bots.txt", "r");
if (file){
char *buffer;
char *jugadores = new char[1000];
int p;
int pos;
while ((c = getc(file)) != EOF){
if (c == '\n'){
strcpy(jugadores[p], buffer);
p++;
buffer = "";
pos = 0;
} else {
buffer[pos] = c;
pos++;
}
}
fclose(file);
}
But it doesn't even compile...
In php the right code would be something like this:
$data = file_get_contents("file.txt");
$names = explode("\n", $data);
Your code has several flaws in it. You need something more like this instead:
FILE *file = fopen("bots.txt", "r");
if (file)
{
char** lines = new char*[1000];
int maxlines = 1000;
int numlines = 0;
char *buffer = new char[1024];
int maxbuf = 1024;
int buflen = 0;
char *line;
int c;
while ((c = getc(file)) != EOF)
{
if (c == '\n')
{
if (numlines == maxlines)
{
char** tmplines = new char*[maxlines+1000];
memcpy(tmplines, lines, sizeof(char*)*maxlines);
delete[] lines;
lines = tmplines;
maxlines += 1000;
}
line = new char[buflen+1];
memcpy(line, buffer, sizeof(char)*buflen);
line[buflen] = 0;
lines[numlines] = line
numlines++;
buflen = 0;
}
else
{
if (buflen == maxbuf)
{
char* tmpbuf = new char[maxbuf+1024];
memcpy(tmpbuf, buffer, sizeof(char)*maxbuf);
delete[] buffer;
buffer = tmpbuf;
maxbuf += 1024;
}
buffer[buflen] = c;
buflen++;
}
}
fclose(file);
if (buflen > 0)
{
if (numlines == maxlines)
{
char** tmplines = new char*[maxlines+1000];
memcpy(tmplines, lines, sizeof(char*)*maxlines);
delete[] lines;
lines = tmplines;
maxlines += 1000;
}
line = new char[buflen+1];
memcpy(line, buffer, sizeof(char)*buflen);
line[buflen] = 0;
lines[numlines] = line
numlines++;
}
delete[] buffer;
// use lines up to numlines elements as needed...
for (int i = 0; i < numlines; i++)
printf("%s\n", lines[i]);
for (int i = 0; i < numlines; ++i)
delete[] lines[i];
delete[] lines;
}
With that said, since you are using C++, you should use C++ classes that will help manage everything for you. Try something more like this instead:
#include <fstream>
#include <ostream>
#include <string>
#include <vector>
std::ifstream file("bots.txt");
if (file.is_open())
{
std::string line;
std::vector<std::string> lines;
while (std::getline(file, line))
lines.push_back(line);
file.close();
// use lines as needed...
for (int i = 0; i < lines.size(); i++)
std::cout << lines[i] << std::endl;
}
Am working in a project where i have to read a set of files and put it in a buffer.The List comprises of small as well as large files.I have to read these files and for more efficiency i tried implementing it in multiple threads.Each thread will take a file from vector of file names and start reading it put it into a buffer and these buffer have to be put in a queue.I happened to have some error in program and i i don't know where exactly in my program the error occurs also don't know why ? Please help me whether there is any mistake in my logic or in my code and how to correct it. Thanks in advance
using namespace std;
#define MAX_THREADS 2
#define BUFFER_SIZE 8388608
vector<string>files;
deque<string>bufferq;
CRITICAL_SECTION Readlock;
int count = 0;
DWORD WINAPI ReadThread(LPVOID s);
int main(int argc,char *argv[])
{
HANDLE ReadT[MAX_THREADS];
char *filelist[5];
DWORD threadid;
filelist[0] = "1.txt";
filelist[1] = "cloudy.jpg";
filelist[2] = "connectify.exe";
filelist[3] = "VMware.exe";
filelist[4] = "Sherlock.mp4";
for(int i=0;i<5;i++)
files.push_back(filelist[i]);
InitializeCriticalSection(&Readlock);
long t1 = GetTickCount();
for(int k = 0; k< MAX_THREADS; k++)
ReadT[k] = CreateThread(NULL,0,ReadThread,NULL,NULL,&threadid);
WaitForMultipleObjects(MAX_THREADS,ReadT,TRUE,INFINITE);
cout << " Time Taken "<< GetTickCount()-t1 << "ms" ;
system("pause");
return 0;
}
DWORD WINAPI ReadThread(LPVOID s)
{
long pending = 0;
//int freespace = BUFFER_SIZE;
char *filename = new char[50];
char fsize[10];
string file;
char *buf;
buf = new char[BUFFER_SIZE];
long filesize = 0;
int numfiles = files.size();
int filled = 0;
int i = 0;
FILE *fp;
char* ptr;
ptr = buf;
while(true)
{
EnterCriticalSection(&Readlock);
if(files.empty())
{
LeaveCriticalSection(&Readlock);
break;
}
else
{
file = files.front();
files.erase(files.begin());
LeaveCriticalSection(&Readlock);
}
bool buff_full = false;
buf = ptr;
int freespace = BUFFER_SIZE;
memset(buf,0,BUFFER_SIZE);
if(!buff_full)
{
if(pending == 0)
{
fp = fopen(file.c_str(),"rb");
if(!fp)
{
cout<<"\nNo such file";
cout<<files[i];
system("pause");
return 0;
}
int r1 =fseek(fp, 0L, SEEK_END);
filesize = ftell(fp);
int r2 =fseek(fp, 0L, SEEK_SET);
sprintf(fsize, "%ld", filesize);
if(freespace >= (strlen(fsize) + strlen(file.c_str()) + 2))
{
count++;
memcpy(buf, file.c_str(), strlen(file.c_str())+1);
freespace = freespace - strlen(file.c_str()) - 1;
buf += strlen(file.c_str()) + 1;
memcpy(buf,fsize,strlen(fsize)+1);
buf += strlen(fsize) + 1;
freespace = freespace - strlen(fsize) - 1;
cout<<"Files read is "<<count<<"\n";
if(freespace == 0)
{
buff_full = true;
pending = filesize;
break;
}
}
else
{
filled = BUFFER_SIZE - freespace;
fclose(fp);
break;
}
if(freespace >= filesize)
{
fread(buf, 1, filesize, fp);
buf += filesize;
freespace = freespace - filesize;
bufferq.push_back(buf);
//cout << "pop"<<bufferq.size();
//i++;
if(files.empty())
{
filled = BUFFER_SIZE - freespace;
fclose(fp);
break;
}
fclose(fp);
}
else
{
fread(buf, 1, freespace, fp);
bufferq.push_back(buf);
//cout <<"pop "<<bufferq.size();
buff_full = true;
}
}
else
{
if(freespace >= pending)
{
fread(buf, 1, pending, fp);
bufferq.push_back(buf);
freespace = freespace - pending;
pending = 0;
//i++;
if(files.empty())
{
filled = BUFFER_SIZE - freespace;
fclose(fp);
break;
}
if(freespace > 0)
buf += pending;
else
buff_full = true;
fclose(fp);
}
else
{
fread(buf, 1, freespace, fp);
bufferq.push_back(buf);
cout << bufferq.size();
pending = pending - freespace;
buff_full = true;
}
}
}
if(buff_full)
{
buf = ptr;
cout << "popping buffer " << bufferq.size();
//bufferq.pop_back();
}
}
return 0;
}
In the context that bug occurs on big files, I suppose that this line can cause problems
sprintf(fsize, "%ld", filesize);
fsize is char[10], and if filesize is >= 1,000,000,000 you'll overwrite fsize array with trailing 0. This will cause "Run-Time Check Failure #2 - Stack around the variable 'fsize' was corrupted.", as you wrote. Please check the sizes of your test files.
Among others, you are filling files in loop on i, and then you wrote:
files.erase(files.begin());
// ...
cout<<"\nNo such file";
cout<<files[i];
files[i] already points to another element as you erased them, and if files are empty on the last iteration it will cause crash.
And what for are you copying file and fsize to buf if you do not copy it to the bufferq?
As bufferq is writable and is shared between threads the access to it should be protected by lock, critical section as you chose.
That's my little code review.
I've put the contents of a file in a char-array using this function:
void Read::readFile(){
FILE * fp = fopen(this->filename,"rt");
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *pData = new char[size + 1];
fread(pData, sizeof(char), size, fp);
fclose(fp);
this->data = pData;
}
Now I want to strip all line-endings from the char-array.
How do I do this without casting the char-array into a string first?
btw. this is part of a homework where we aren't allowed to use the string-library.
#include <algorithm>
size = std::remove(pData, pData + size, '\n') - pData;
pData[size] = 0; // optional
For some C++11 lambda fun:
#include <algorithm>
size = std::remove_if(pData, pData + size, [](char c) { return c == '\n'; }) - pData;
pData[size] = 0; // optional
The easiest approach is to make a second buffer the size of the original array.
int len = size;
char* newBufer = calloc(len,sizeof(char));
int i = 0;
int j = 0;
int nlCount = 0;
for(i=0; i<len; i++) {
if(pData[i] != '\n') {
newBuffer[j++] = pData[i];
} else {
nlCount++;
}
}
printf("Finished copying array without newlines. Total newlines removed: %d",nlCount);
The added benefit here is since you calloc'ed instead of malloc'ing your array, all values are zero initially, so in this case, once you are done copying, the data at (len-nlCount) through to (len) will all be zero (ie: '\0') so it is automatically null-terminated, like a string would be anyways. Don't forget to free() the array when you are done.
In place removal:
void strip_newlines(char* p) {
char* q = p;
while (p != 0 && *p != '\0') {
if (*p == '\n') {
p++;
*q = *p;
}
else {
*q++ = *p++;
}
}
*q = '\0';
}
Something like this:
void Read::readFile()
{
FILE * fp = fopen(this->filename,"rt");
if (fp)
{
char *pData = NULL;
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
if (size != -1L)
{
pData = new char[size];
if (size > 0)
{
fseek(fp, 0, SEEK_SET);
size = fread(pData, sizeof(char), size, fp);
}
}
fclose(fp);
if (size < 0)
{
delete[] pData;
pData = NULL;
}
else if (size > 0)
{
char *start = pData;
char *end = start + size;
char *ptr = (char*) memchr(pData, '\n', size);
while (ptr)
{
int len = 1;
if ((ptr > start) && ((*ptr-1) == '\r'))
{
--ptr;
++len;
}
memmove(ptr, ptr+len, end - (ptr+len));
end -= len;
ptr = (char*) memchr(ptr, '\n', end - ptr);
}
size = (end - start);
}
this->data = pData;
this->size = size;
}
}